Change names. Not use sequence number but request number
[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)
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()
87 {
88     return this->app2client.size();
89 }
90
91 unsigned AppList::currentRequestNumber()
92 {
93     return this->current_req;
94 }
95
96 // Is this function necessary ?
97 unsigned AppList::getRequestNumber(const string &appid)
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 bool AppList::requestFinished()
126 {
127     return this->req_list.empty();
128 }
129
130 struct WMTrigger AppList::getRequest(unsigned req_num)
131 {
132     for (auto &x : this->req_list)
133     {
134         if (req_num == x.req_num)
135         {
136             return x.trigger;
137         }
138     }
139 }
140
141 const vector<struct WMAction> &AppList::getActions(unsigned req_num)
142 {
143     for (auto &x : this->req_list)
144     {
145         if (req_num == x.req_num)
146         {
147             return x.sync_draw_req;
148         }
149     }
150 }
151
152 bool AppList::setAction(unsigned req_num, const struct WMAction &action)
153 {
154     bool result = false;
155     for (auto &x : this->req_list)
156     {
157         if (req_num != x.req_num)
158         {
159             continue;
160         }
161         x.sync_draw_req.push_back(action);
162         result = true;
163         break;
164     }
165
166     return result;
167 }
168
169 /**
170  * Note:
171  * This function set action with parameters.
172  * if visible is true, it means app should be visible, so enddraw_finished parameter should be false.
173  * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
174  * This function doesn't support actions for focus yet.
175  */
176 bool AppList::setAction(unsigned req_num, const string &appid, const string &role, const string &area, bool visible)
177 {
178     bool result = false;
179     for (auto &x : req_list)
180     {
181         if (req_num != x.req_num)
182         {
183             continue;
184         }
185         bool edraw_f = (visible) ? false : true;
186         WMAction action{appid, role, area, visible, edraw_f};
187
188         x.sync_draw_req.push_back(action);
189         result = true;
190         break;
191     }
192     return result;
193 }
194
195 /**
196  * This function checks
197  *   * req_num is equal to current request number
198  *   * appid and role are equeal to the appid and role stored in action list(sync_draw_req)
199  */
200 bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const string &role)
201 {
202     bool result = false;
203     for (auto &x : req_list)
204     {
205         if (req_num < x.req_num)
206         {
207             break;
208         }
209         if (req_num == x.req_num)
210         {
211             for (auto &y : x.sync_draw_req)
212             {
213                 if (y.appid == appid && y.role == role)
214                 {
215                     y.end_draw_finished = true;
216                     result = true;
217                 }
218             }
219         }
220     }
221     this->reqDump();
222     return result;
223 }
224
225 /**
226  * @brief  check all actions of the requested sequence is finished
227  * @param  unsigned request_number
228  * @return true if all action is set.
229  */
230 bool AppList::endDrawFullfilled(unsigned req_num)
231 {
232     bool result = false;
233     for (const auto &x : req_list)
234     {
235         if (req_num < x.req_num)
236         {
237             break;
238         }
239         if (req_num == x.req_num)
240         {
241             result = true;
242             for (const auto &y : x.sync_draw_req)
243             {
244                 result &= y.end_draw_finished;
245                 if (!result)
246                 {
247                     break;
248                 }
249             }
250         }
251     }
252     return result;
253 }
254
255 void AppList::removeRequest(unsigned req_num)
256 {
257     this->req_list.erase(remove_if(this->req_list.begin(), this->req_list.end(),
258                                    [req_num](WMRequest x) {
259                                        return x.req_num == req_num;
260                                    }));
261 }
262
263 void AppList::next()
264 {
265     ++this->current_req;
266     if (0 == this->current_req)
267     {
268         this->current_req = 1;
269     }
270 }
271
272 bool AppList::haveRequest()
273 {
274     return !this->req_list.empty();
275 }
276
277 void AppList::clientDump()
278 {
279     DUMP("======= client dump =====");
280     for (const auto &x : this->app2client)
281     {
282         const auto &y = x.second;
283         y->dumpInfo();
284     }
285     DUMP("======= client dump end=====");
286 }
287
288 void AppList::reqDump()
289 {
290     DUMP("======= req dump =====");
291     DUMP("current request : %d", current_req);
292     for (const auto &x : req_list)
293     {
294         DUMP("requested with  : %d", x.req_num);
295         DUMP("Trigger : (APPID :%s, ROLE :%s, AREA :%s, TASK: %d)",
296              x.trigger.appid.c_str(),
297              x.trigger.role.c_str(),
298              x.trigger.area.c_str(),
299              x.trigger.task);
300
301         for (const auto &y : x.sync_draw_req)
302         {
303             DUMP(
304                 "Action  : (APPID :%s, ROLE :%s, AREA :%s, END_DRAW_FINISHED: %d)",
305                 y.appid.c_str(),
306                 y.role.c_str(),
307                 y.area.c_str(),
308                 y.end_draw_finished);
309         }
310     }
311     DUMP("======= req dump end =====\n");
312 }
313 } // namespace wm