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