06c1d86ce75045083c2fe5804140f0b04f3fc387
[apps/agl-service-windowmanager.git] / src / applist.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <iostream>
17 #include <algorithm>
18 #include "applist.hpp"
19 #include "../include/hmi-debug.h"
20
21 using std::shared_ptr;
22 using std::string;
23 using std::vector;
24
25 const static int kReserveReqSize = 10;
26 const static int kReserveCLSize = 100;
27
28 namespace wm
29 {
30
31 AppList::AppList()
32     : current_req(1)
33 {
34     req_list.reserve(kReserveReqSize);
35     app2client.reserve(kReserveCLSize);
36 }
37
38 void AppList::addClient(const string &appid, const string &role)
39 {
40     shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, role);
41     this->app2client[appid] = client;
42     this->clientDump();
43 }
44
45 void AppList::addClient(const std::string &appid, unsigned layer, unsigned surface, const std::string &role)
46 {
47     shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, layer, surface, role);
48     this->app2client[appid] = client;
49     this->clientDump();
50 }
51
52 void AppList::removeClient(const string &appid)
53 {
54     this->app2client.erase(appid);
55 }
56
57 bool AppList::contains(const string &appid) const
58 {
59     auto result = this->app2client.find(appid);
60     return (this->app2client.end() != result) ? true : false;
61 }
62
63 void AppList::removeSurface(unsigned surface_id){
64     // This function may be very slow
65     bool ret = false;
66     for (auto &x : this->app2client)
67     {
68         ret = x.second->removeSurfaceIfExist(surface_id);
69         if(ret){
70             HMI_DEBUG("wm", "remove surface %d from Client %s finish", surface_id, x.second->appID().c_str());
71             break;
72         }
73     }
74 }
75
76 /**
77  * @brief  get WMClient object. Before call this function, must call "contains"
78  * to check the key is contained, otherwise, you have to take care of std::out_of_range.
79  * @param string[in] application id(key)
80  * @return WMClient object
81  */
82 shared_ptr<WMClient> AppList::lookUpClient(const string &appid)
83 {
84     return this->app2client.at(appid);
85 }
86
87 int AppList::countClient() const
88 {
89     return this->app2client.size();
90 }
91
92 unsigned AppList::currentRequestNumber() const
93 {
94     return this->current_req;
95 }
96
97 WMError AppList::popFloatingSurface(unsigned pid, unsigned *surface)
98 {
99     WMError ret = WMError::NO_ENTRY;
100
101     for (auto itr = this->floating_surfaces.begin(); itr != this->floating_surfaces.end(); ++itr)
102     {
103         if(pid == itr->pid){
104             *surface = itr->surface_id;
105             itr = this->floating_surfaces.erase(itr);
106             ret = WMError::SUCCESS;
107             HMI_DEBUG("wm", "Erase surface %d", *surface);
108             break;
109         }
110     }
111     return ret;
112 }
113
114 WMError AppList::popFloatingSurface(const std::string &appid, unsigned *surface)
115 {
116     HMI_ERROR("wm", "This function is not implemented");
117     return WMError::SUCCESS;
118 }
119
120 void AppList::addFloatingClient(const std::string &appid, unsigned layer, const std::string &role)
121 {
122 }
123
124 void AppList::addFloatingSurface(unsigned surface, unsigned pid)
125 {
126     struct FloatingSurface fsurface{surface, pid};
127     this->floating_surfaces.push_back(fsurface);
128 }
129
130 void AppList::removeFloatingSurface(unsigned surface)
131 {
132     for (auto itr = this->floating_surfaces.begin(); itr != this->floating_surfaces.end(); ++itr)
133     {
134         if (surface == itr->surface_id)
135         {
136             HMI_DEBUG("wm", "Erase surface %d", itr->surface_id);
137             itr = this->floating_surfaces.erase(itr);
138             break;
139         }
140     }
141 }
142
143 WMError AppList::appendRole(const std::string &id, const std::string &role, unsigned surface)
144 {
145     WMError wm_err = WMError::NO_ENTRY;
146     if (this->contains(id))
147     {
148         auto x = this->lookUpClient(id);
149         x->addSurface(role, surface);
150         wm_err = WMError::SUCCESS;
151     }
152     return wm_err;
153 }
154
155 unsigned AppList::getRequestNumber(const string &appid) const
156 {
157     for (const auto &x : this->req_list)
158     {
159         // Since app will not request twice and more, comparing appid is enough?
160         if ((x.trigger.appid == appid))
161         {
162             return x.req_num;
163         }
164     }
165     return 0;
166 }
167
168 unsigned AppList::addAllocateRequest(WMRequest req)
169 {
170     if (this->req_list.size() == 0)
171     {
172         req.req_num = current_req;
173     }
174     else
175     {
176         HMI_SEQ_DEBUG(this->current_req, "add: %d", this->req_list.back().req_num + 1);
177         req.req_num = this->req_list.back().req_num + 1;
178     }
179     this->req_list.push_back(req);
180     return req.req_num; // return 1; if you test time_expire
181 }
182
183 struct WMTrigger AppList::getRequest(unsigned req_num, bool *found)
184 {
185     *found = false;
186     for (const auto &x : this->req_list)
187     {
188         if (req_num == x.req_num)
189         {
190             *found = true;
191             return x.trigger;
192         }
193     }
194     return WMTrigger{"", "", "", Task::TASK_INVALID};
195 }
196
197 const vector<struct WMAction> &AppList::getActions(unsigned req_num, bool* found)
198 {
199     *found = false;
200     for (auto &x : this->req_list)
201     {
202         if (req_num == x.req_num)
203         {
204             *found = true;
205             return x.sync_draw_req;
206         }
207     }
208 }
209
210 WMError AppList::setAction(unsigned req_num, const struct WMAction &action)
211 {
212     WMError result = WMError::FAIL;
213     for (auto &x : this->req_list)
214     {
215         if (req_num != x.req_num)
216         {
217             continue;
218         }
219         x.sync_draw_req.push_back(action);
220         result = WMError::SUCCESS;
221         break;
222     }
223
224     return result;
225 }
226
227 /**
228  * Note:
229  * This function set action with parameters.
230  * if visible is true, it means app should be visible, so enddraw_finished parameter should be false.
231  * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
232  * This function doesn't support actions for focus yet.
233  */
234 WMError AppList::setAction(unsigned req_num, const string &appid, const string &role, const string &area, bool visible)
235 {
236     WMError result = WMError::NOT_REGISTERED;
237     for (auto &x : req_list)
238     {
239         if (req_num != x.req_num)
240         {
241             continue;
242         }
243         bool edraw_f = (visible) ? false : true;
244         WMAction action{appid, role, area, visible, edraw_f};
245
246         x.sync_draw_req.push_back(action);
247         result = WMError::SUCCESS;
248         break;
249     }
250     return result;
251 }
252
253 /**
254  * This function checks
255  *   * req_num is equal to current request number
256  *   * appid and role are equeal to the appid and role stored in action list(sync_draw_req)
257  */
258 bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const string &role)
259 {
260     bool result = false;
261     for (auto &x : req_list)
262     {
263         if (req_num < x.req_num)
264         {
265             break;
266         }
267         if (req_num == x.req_num)
268         {
269             for (auto &y : x.sync_draw_req)
270             {
271                 if (y.appid == appid && y.role == role)
272                 {
273                     y.end_draw_finished = true;
274                     result = true;
275                 }
276             }
277         }
278     }
279     this->reqDump();
280     return result;
281 }
282
283 /**
284  * @brief  check all actions of the requested sequence is finished
285  * @param  unsigned request_number
286  * @return true if all action is set.
287  */
288 bool AppList::endDrawFullfilled(unsigned req_num)
289 {
290     bool result = false;
291     for (const auto &x : req_list)
292     {
293         if (req_num < x.req_num)
294         {
295             break;
296         }
297         if (req_num == x.req_num)
298         {
299             result = true;
300             for (const auto &y : x.sync_draw_req)
301             {
302                 result &= y.end_draw_finished;
303                 if (!result)
304                 {
305                     break;
306                 }
307             }
308         }
309     }
310     return result;
311 }
312
313 void AppList::removeRequest(unsigned req_num)
314 {
315     this->req_list.erase(remove_if(this->req_list.begin(), this->req_list.end(),
316                                    [req_num](WMRequest x) {
317                                        return x.req_num == req_num;
318                                    }));
319 }
320
321 void AppList::next()
322 {
323     ++this->current_req;
324     if (0 == this->current_req)
325     {
326         this->current_req = 1;
327     }
328 }
329
330 bool AppList::haveRequest() const
331 {
332     return !this->req_list.empty();
333 }
334
335 void AppList::clientDump()
336 {
337     DUMP("======= client dump =====");
338     for (const auto &x : this->app2client)
339     {
340         const auto &y = x.second;
341         y->dumpInfo();
342     }
343     DUMP("======= client dump end=====");
344 }
345
346 void AppList::reqDump()
347 {
348     DUMP("======= req dump =====");
349     DUMP("current request : %d", current_req);
350     for (const auto &x : req_list)
351     {
352         DUMP("requested with  : %d", x.req_num);
353         DUMP("Trigger : (APPID :%s, ROLE :%s, AREA :%s, TASK: %d)",
354              x.trigger.appid.c_str(),
355              x.trigger.role.c_str(),
356              x.trigger.area.c_str(),
357              x.trigger.task);
358
359         for (const auto &y : x.sync_draw_req)
360         {
361             DUMP(
362                 "Action  : (APPID :%s, ROLE :%s, AREA :%s, END_DRAW_FINISHED: %d)",
363                 y.appid.c_str(),
364                 y.role.c_str(),
365                 y.area.c_str(),
366                 y.end_draw_finished);
367         }
368     }
369     DUMP("======= req dump end =====\n");
370 }
371 } // namespace wm