2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "applist.hpp"
19 #include "../include/hmi-debug.h"
21 using std::shared_ptr;
28 const static int kReserveClientSize = 100;
29 const static int kReserveReqSize = 10;
32 * AppList Constructor.
34 * Reserve the container size to avoid re-allocating memory.
36 * @note Size should be changed according to the system.
37 * If the number of applications becomes over the size, re-allocating memory will happen.
44 this->app2client.reserve(kReserveClientSize);
45 this->req_list.reserve(kReserveReqSize);
48 AppList::~AppList() {}
50 // =================== Client Date container API ===================
53 * Add Client to the list
55 * Add Client to the list.
56 * The Client means application which has role, layer, surface
57 * This function should be called once for the app.
58 * Caller should take care not to be called more than once.
60 * @param string[in] Application id. This will be the key to withdraw the information.
61 * @param unsigned[in] Layer ID in which the application is
62 * @param unsigned[in] surface ID which the application has
63 * @param string[in] Role which means what behavior the application will do.
65 * @attention This function should be called once for the app
66 * Caller should take care not to be called more than once.
68 void AppList::addClient(const std::string &appid, unsigned layer, unsigned surface, const std::string &role)
70 std::lock_guard<std::mutex> lock(this->mtx);
71 shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, layer, surface, role);
72 this->app2client[appid] = client;
77 * Remove WMClient from the list
79 * @param string[in] Application id. This will be the key to withdraw the information.
81 void AppList::removeClient(const string &appid)
83 std::lock_guard<std::mutex> lock(this->mtx);
84 this->app2client.erase(appid);
85 HMI_INFO("wm", "Remove client %s", appid.c_str());
89 * Check this class stores the appid.
91 * @param string[in] Application id. This will be the key to withdraw the information.
92 * @return true if the class has the requested key(appid)
94 bool AppList::contains(const string &appid) const
96 auto result = this->app2client.find(appid);
97 return (this->app2client.end() != result) ? true : false;
101 * Remove surface from client
103 * @param unsigned[in] surface id.
106 void AppList::removeSurface(unsigned surface){
107 // This function may be very slow
108 std::lock_guard<std::mutex> lock(this->mtx);
110 for (auto &x : this->app2client)
112 ret = x.second->removeSurfaceIfExist(surface);
114 HMI_DEBUG("wm", "remove surface %d from Client %s finish",
115 surface, x.second->appID().c_str());
123 * Get WMClient object.
125 * After get the WMClient object, caller can call the client method.
126 * Before call this function, caller must call "contains"
127 * to check the key is contained, otherwise, you have to take care of std::out_of_range.
129 * @param string[in] application id(key)
130 * @return WMClient object
131 * @attention Must call cantains to check appid is stored before this function.
133 shared_ptr<WMClient> AppList::lookUpClient(const string &appid)
135 return this->app2client.at(appid);
141 * Returns the number of client stored in the list.
144 * @return The number of client
146 int AppList::countClient() const
148 return this->app2client.size();
152 * Get AppID with surface and role.
154 * Returns AppID if found.
156 * @param unsigned[in] surfaceID
157 * @param string[in] role
158 * @param bool[in,out] AppID is found or not
160 * @attention If AppID is not found, param found will be false.
162 string AppList::getAppID(unsigned surface, const string& role, bool* found) const
165 for (const auto &x : this->app2client)
167 if(x.second->surfaceID(role) == surface){
169 return x.second->appID();
175 // =================== Request Date container API ===================
178 * Get current request number
180 * Request number is the numeric ID to designate the request.
181 * But returned request number from this function doesn't mean the request exists.
182 * This number is used as key to withdraw the WMRequest object.
185 * @return current request number.
186 * @note request number is more than 0.
188 unsigned AppList::currentRequestNumber() const
190 return this->current_req;
196 * Request number is the numeric ID to designate the request.
197 * But returned request number from this function doesn't mean the request exists.
198 * This number is used as key to withdraw the WMRequest object.
201 * @return request number.
202 * @attention If returned value is 0, no request exists.
204 unsigned AppList::getRequestNumber(const string &appid) const
206 for (const auto &x : this->req_list)
208 // Since app will not request twice and more, comparing appid is enough?
209 if ((x.trigger.appid == appid))
220 * Request number is the numeric ID to designate the request.
221 * But returned request number from this function doesn't mean the request exists.
222 * This number is used as key to withdraw the WMRequest object.
224 * @param WMRequest[in] WMRequest object caller creates
225 * @return Request number
226 * @attention If the request number is different with curent request number,
227 * it means the previous request is not finished.
229 unsigned AppList::addRequest(WMRequest req)
231 std::lock_guard<std::mutex> lock(this->mtx);
232 if (this->req_list.size() == 0)
234 req.req_num = current_req;
238 HMI_SEQ_INFO(this->current_req, "add: %d", this->req_list.back().req_num + 1);
239 req.req_num = this->req_list.back().req_num + 1;
241 this->req_list.push_back(req);
246 * Get trigger which the application requests
248 * WMTrigger contains which application requests what role and where to put(area) and task.
249 * This is used for input event to Window Policy Manager(state machine).
251 * @param unsigned[in] request number
252 * @param bool[in,out] Check request number of the parameter is valid.
253 * @return WMTrigger which associates with the request number
254 * @attention If the request number is not valid, parameter "found" is false
255 * and return value will be meaningless value.
256 * Caller can check the request parameter is valid.
258 struct WMTrigger AppList::getRequest(unsigned req_num, bool *found)
261 for (const auto &x : this->req_list)
263 if (req_num == x.req_num)
269 HMI_SEQ_ERROR(req_num, "Couldn't get request : %d", req_num);
270 return WMTrigger{"", "", "", Task::TASK_INVALID};
274 * Get actions which the application requests
276 * WMAciton contains the information of state transition.
277 * In other words, it contains actions of Window Manager,
278 * which role should be put to the area.
280 * @param unsigned[in] request number
281 * @param bool[in,out] Check request number of the parameter is valid.
282 * @return WMTrigger which associates with the request number
283 * @attention If the request number is not valid, parameter "found" is false
284 * and return value will be no reference pointer.
285 * Caller must check the request parameter is valid.
287 const vector<struct WMAction> &AppList::getActions(unsigned req_num, bool* found)
290 for (auto &x : this->req_list)
292 if (req_num == x.req_num)
295 return x.sync_draw_req;
298 HMI_SEQ_ERROR(req_num, "Couldn't get action with the request : %d", req_num);
302 * Set actions to the request.
304 * Add actions to the request.
305 * This function can be called many times, and actions increase.
306 * This function is used for decision of actions of Window Manager
307 * according to the result of Window Policy Manager.
309 * @param unsigned[in] request number
310 * @param WMAction[in] Action of Window Manager.
311 * @return WMError If request number is not valid, FAIL will be returned.
313 WMError AppList::setAction(unsigned req_num, const struct WMAction &action)
315 std::lock_guard<std::mutex> lock(this->mtx);
316 WMError result = WMError::FAIL;
317 for (auto &x : this->req_list)
319 if (req_num != x.req_num)
323 x.sync_draw_req.push_back(action);
324 result = WMError::SUCCESS;
332 * @note This function set action with parameters.
333 * If visible is true, it means app should be visible, so enddraw_finished parameter should be false.
334 * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
335 * This function doesn't support actions for focus yet.
338 * Set actions to the request.
340 * This function is overload function.
341 * The feature is same as other one.
343 * @param unsigned[in] request number
344 * @param string[in] application id
345 * @param string[in] role
346 * @param string[in] area
347 * @param Task[in] the role should be visible or not.
348 * @return WMError If request number is not valid, FAIL will be returned.
349 * @attention This function set action with parameters, then caller doesn't need to create WMAction object.
350 * If visible is true, it means app should be visible, so enddraw_finished parameter will be false.
351 * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
352 * This function doesn't support actions for focus yet.
354 WMError AppList::setAction(unsigned req_num, const string &appid, const string &role, const string &area, TaskVisible visible)
356 std::lock_guard<std::mutex> lock(this->mtx);
357 WMError result = WMError::FAIL;
358 for (auto &x : req_list)
360 if (req_num != x.req_num)
364 // If visible task is not invisible, redraw is required -> true
365 bool edraw_f = (visible != TaskVisible::INVISIBLE) ? false : true;
366 WMAction action{appid, role, area, visible, edraw_f};
368 x.sync_draw_req.push_back(action);
369 result = WMError::SUCCESS;
376 * Set end_draw_finished param is true
378 * This function checks
379 * - req_num is equal to current request number
380 * - appid and role are equeal to the appid and role stored in action list
381 * If it is valid, set the action is finished.
383 * @param unsigned[in] request number
384 * @param string[in] application id
385 * @param string[in] role
386 * @return If the parameters are not valid in action list, returns false
388 bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const string &role)
390 std::lock_guard<std::mutex> lock(this->mtx);
392 for (auto &x : req_list)
394 if (req_num < x.req_num)
398 if (req_num == x.req_num)
400 for (auto &y : x.sync_draw_req)
402 if (y.appid == appid && y.role == role)
404 HMI_SEQ_INFO(req_num, "Role %s finish redraw", y.role.c_str());
405 y.end_draw_finished = true;
416 * Check all actions of the requested sequence is finished
418 * @param unsigned[in] request_number
419 * @return true if all action is set.
421 bool AppList::endDrawFullfilled(unsigned req_num)
424 for (const auto &x : req_list)
426 if (req_num < x.req_num)
430 if (req_num == x.req_num)
433 for (const auto &y : x.sync_draw_req)
435 result &= y.end_draw_finished;
447 * Finish the request, then remove it.
449 * @param unsigned[in] request_number
451 * @note Please call next after this function to receive or process next request.
453 void AppList::removeRequest(unsigned req_num)
455 std::lock_guard<std::mutex> lock(this->mtx);
456 this->req_list.erase(remove_if(this->req_list.begin(), this->req_list.end(),
457 [req_num](WMRequest x) {
458 return x.req_num == req_num;
463 * Move the current request to next
470 std::lock_guard<std::mutex> lock(this->mtx);
472 if (0 == this->current_req)
474 this->current_req = 1;
479 * Check the request exists is in request list
482 * @return true if WMRequest exists in the request list
484 bool AppList::haveRequest() const
486 return !this->req_list.empty();
489 void AppList::clientDump()
491 DUMP("======= client dump =====");
492 for (const auto &x : this->app2client)
494 const auto &y = x.second;
497 DUMP("======= client dump end=====");
500 void AppList::reqDump()
502 DUMP("======= req dump =====");
503 DUMP("current request : %d", current_req);
504 for (const auto &x : req_list)
506 DUMP("requested : %d", x.req_num);
507 DUMP("Trigger : (APPID :%s, ROLE :%s, AREA :%s, TASK: %d)",
508 x.trigger.appid.c_str(),
509 x.trigger.role.c_str(),
510 x.trigger.area.c_str(),
513 for (const auto &y : x.sync_draw_req)
516 "Action : (APPID :%s, ROLE :%s, AREA :%s, VISIBLE : %s, END_DRAW_FINISHED: %d)",
520 (y.visible == TaskVisible::INVISIBLE) ? "invisible" : "visible",
521 y.end_draw_finished);
524 DUMP("======= req dump end =====");