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