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