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