2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3 * Copyright (c) 2018 Konsulko Group
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 #include "window_manager.hpp"
22 #include "json_helper.hpp"
23 #include "applist.hpp"
27 #include <systemd/sd-event.h>
32 using std::unordered_map;
37 static const uint64_t kTimeOut = 3ULL; /* 3s */
39 /* DrawingArea name used by "{layout}.{area}" */
40 const char kNameLayoutNormal[] = "normal";
41 const char kNameLayoutSplit[] = "split";
42 const char kNameAreaFull[] = "full";
43 const char kNameAreaMain[] = "main";
44 const char kNameAreaSub[] = "sub";
46 /* Key for json obejct */
47 const char kKeyDrawingName[] = "drawing_name";
48 const char kKeyDrawingArea[] = "drawing_area";
49 const char kKeyDrawingRect[] = "drawing_rect";
50 const char kKeyX[] = "x";
51 const char kKeyY[] = "y";
52 const char kKeyWidth[] = "width";
53 const char kKeyHeight[] = "height";
54 const char kKeyWidthPixel[] = "width_pixel";
55 const char kKeyHeightPixel[] = "height_pixel";
56 const char kKeyWidthMm[] = "width_mm";
57 const char kKeyHeightMm[] = "height_mm";
58 const char kKeyScale[] = "scale";
59 const char kKeyIds[] = "ids";
61 static const vector<string> kListEventName{
71 static sd_event_source *g_timer_ev_src = nullptr;
72 static AppList g_app_list;
73 static WindowManager *g_context;
78 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
80 HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
81 reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
85 static void onStateTransitioned(vector<WMAction> actions)
87 g_context->startTransitionWrapper(actions);
92 g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
99 WindowManager::WindowManager()
102 const char *path = getenv("AFM_APP_INSTALL_DIR");
105 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
109 this->lc = std::make_shared<LayerControl>(root);
111 HMI_DEBUG("Layer Controller initialized");
114 int WindowManager::init()
116 LayerControlCallbacks lmcb;
117 lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
118 this->surface_created(surface);
120 lmcb.surfaceDestroyed = [&](unsigned surface){
121 this->surface_removed(surface);
124 if(this->lc->init(lmcb) != WMError::SUCCESS)
129 // TODO: application requests by old role,
130 // so create role map (old, new)
132 this->loadOldRoleDb();
134 // Store my context for calling callback from PolicyManager
137 // Initialize PMWrapper
138 this->pmw.initialize();
140 // Register callback to PolicyManager
141 this->pmw.registerCallback(onStateTransitioned, onError);
143 // Make afb event for subscriber
144 for (int i = Event_ScreenUpdated; i < Event_Error; i++)
146 map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str());
149 const struct rect css_bg = this->lc->getAreaSize("fullscreen");
150 Screen screen = this->lc->getScreenInfo();
151 rectangle dp_bg(screen.width(), screen.height());
153 dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
154 dp_bg.fit(screen.width(), screen.height());
155 dp_bg.center(screen.width(), screen.height());
156 HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
157 css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
159 double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
160 this->lc->setupArea(dp_bg, scale);
165 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
167 // TODO: application requests by old role,
168 // so convert role old to new
169 const char *new_role = this->convertRoleOldToNew(drawing_name);
171 string str_id = appid;
172 string role = new_role;
175 if(!g_app_list.contains(str_id))
177 lid = this->lc->getNewLayerID(role);
180 // register drawing_name as fallback and make it displayed.
181 lid = this->lc->getNewLayerID(string("fallback"));
182 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
185 return Err<int>("Designated role does not match any role, fallback is disabled");
188 this->lc->createNewLayer(lid);
189 // add client into the db
190 g_app_list.addClient(str_id, lid, drawing_name);
193 // generate surface ID for ivi-shell application
194 auto rname = this->id_alloc.lookup(role);
197 // name does not exist yet, allocate surface id...
198 auto id = int(this->id_alloc.generate_id(role));
199 this->tmp_surface2app[id] = {str_id, lid};
201 auto client = g_app_list.lookUpClient(str_id);
202 client->registerSurface(id);
204 // Set role map of (new, old)
205 this->rolenew2old[role] = std::string(drawing_name);
210 // Check currently registered drawing names if it is already there.
211 return Err<int>("Surface already present");
214 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
217 // TODO: application requests by old role,
218 // so convert role old to new
219 const char *new_role = this->convertRoleOldToNew(drawing_name);
221 string str_id = appid;
222 string role = new_role;
224 unsigned sid = std::stol(ivi_id);
225 HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
227 * IVI-shell doesn't send surface_size event via ivi-wm protocol
228 * if the application is using XDG surface.
229 * So WM has to set surface size with original size here
231 WMError ret = this->lc->setXDGSurfaceOriginSize(sid);
234 HMI_ERROR("%s", errorDescription(ret));
235 HMI_WARNING("The main user of this API is runXDG");
239 if(!g_app_list.contains(str_id))
241 unsigned l_id = this->lc->getNewLayerID(role);
244 // register drawing_name as fallback and make it displayed.
245 l_id = this->lc->getNewLayerID("fallback");
246 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
249 return "Designated role does not match any role, fallback is disabled";
252 this->lc->createNewLayer(l_id);
253 // add client into the db
254 g_app_list.addClient(str_id, l_id, drawing_name);
257 auto rname = this->id_alloc.lookup(role);
261 return "Surface already present";
264 // register pair drawing_name and ivi_id
265 this->id_alloc.register_name_id(role, sid);
267 auto client = g_app_list.lookUpClient(str_id);
268 client->addSurface(sid);
270 // Set role map of (new, old)
271 this->rolenew2old[role] = std::string(drawing_name);
276 void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
277 char const *drawing_area, const reply_func &reply)
279 // TODO: application requests by old role,
280 // so convert role old to new
281 const char *c_role = this->convertRoleOldToNew(drawing_name);
284 string role = c_role;
285 string area = drawing_area;
287 if(!g_app_list.contains(id))
289 reply("app doesn't request 'requestSurface' or 'setRole' yet");
292 auto client = g_app_list.lookUpClient(id);
294 Task task = Task::TASK_ALLOCATE;
295 unsigned req_num = 0;
296 WMError ret = WMError::UNKNOWN;
298 ret = this->setRequest(id, role, area, task, &req_num);
300 if(ret != WMError::SUCCESS)
302 HMI_ERROR(errorDescription(ret));
303 reply("Failed to set request");
308 if (req_num != g_app_list.currentRequestNumber())
310 // Add request, then invoked after the previous task is finished
311 HMI_SEQ_DEBUG(req_num, "request is accepted");
316 ret = this->checkPolicy(req_num);
318 if (ret != WMError::SUCCESS)
321 HMI_SEQ_ERROR(req_num, errorDescription(ret));
322 g_app_list.removeRequest(req_num);
323 this->processNextRequest();
327 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
328 const reply_func &reply)
330 // TODO: application requests by old role,
331 // so convert role old to new
332 const char *c_role = this->convertRoleOldToNew(drawing_name);
335 string role = c_role;
336 string area = ""; //drawing_area;
337 Task task = Task::TASK_RELEASE;
338 unsigned req_num = 0;
339 WMError ret = WMError::UNKNOWN;
341 ret = this->setRequest(id, role, area, task, &req_num);
343 if (ret != WMError::SUCCESS)
345 HMI_ERROR(errorDescription(ret));
346 reply("Failed to set request");
351 if (req_num != g_app_list.currentRequestNumber())
353 // Add request, then invoked after the previous task is finished
354 HMI_SEQ_DEBUG(req_num, "request is accepted");
359 ret = this->checkPolicy(req_num);
361 if (ret != WMError::SUCCESS)
364 HMI_SEQ_ERROR(req_num, errorDescription(ret));
365 g_app_list.removeRequest(req_num);
366 this->processNextRequest();
370 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
372 // TODO: application requests by old role,
373 // so convert role old to new
374 const char *c_role = this->convertRoleOldToNew(drawing_name);
377 string role = c_role;
378 unsigned current_req = g_app_list.currentRequestNumber();
379 bool result = g_app_list.setEndDrawFinished(current_req, id, role);
383 HMI_ERROR("%s is not in transition state", id.c_str());
387 if (g_app_list.endDrawFullfilled(current_req))
389 // do task for endDraw
391 WMError ret = this->doEndDraw(current_req);
393 if(ret != WMError::SUCCESS)
395 //this->emit_error();
397 // Undo state of PolicyManager
398 this->pmw.undoState();
399 this->lc->undoUpdate();
401 this->emitScreenUpdated(current_req);
402 HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
404 g_app_list.removeRequest(current_req);
406 this->processNextRequest();
410 HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
415 bool WindowManager::api_subscribe(afb_req_t req, EventType event_id)
418 char* appid = afb_req_get_application_id(req);
419 if(event_id < Event_Val_Min || event_id > Event_Val_Max)
421 HMI_ERROR("not defined in Window Manager", event_id);
424 HMI_INFO("%s subscribe %s : %d", appid, kListEventName[event_id].c_str(), event_id);
425 if(event_id == Event_ScreenUpdated)
427 // Event_ScreenUpdated should be emitted to subscriber
428 afb_event_t event = this->map_afb_event[kListEventName[event_id]];
429 int rc = afb_req_subscribe(req, event);
439 auto client = g_app_list.lookUpClient(id);
440 if(client != nullptr)
442 ret = client->subscribe(req, kListEventName[event_id]);
448 result<json_object *> WindowManager::api_get_display_info()
450 Screen screen = this->lc->getScreenInfo();
452 json_object *object = json_object_new_object();
453 json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
454 json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
456 json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
457 json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
458 json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
460 return Ok<json_object *>(object);
463 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
467 // TODO: application requests by old role,
468 // so convert role old to new
469 const char *c_role = this->convertRoleOldToNew(drawing_name);
470 string role = c_role;
472 // Check drawing name, surface/layer id
473 auto const &surface_id = this->id_alloc.lookup(role);
476 return Err<json_object *>("Surface does not exist");
479 // Set area rectangle
480 struct rect area_info = this->area_info[*surface_id];
481 json_object *object = json_object_new_object();
482 json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
483 json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
484 json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
485 json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
487 return Ok<json_object *>(object);
493 void WindowManager::surface_created(unsigned surface_id)
496 if(this->tmp_surface2app.count(surface_id) != 0)
498 string appid = this->tmp_surface2app[surface_id].appid;
499 auto client = g_app_list.lookUpClient(appid);
500 if(client != nullptr)
502 WMError ret = client->addSurface(surface_id);
503 HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
504 if(ret != WMError::SUCCESS)
506 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
509 this->tmp_surface2app.erase(surface_id);
513 void WindowManager::surface_removed(unsigned surface_id)
515 HMI_DEBUG("Delete surface_id %u", surface_id);
516 this->id_alloc.remove_id(surface_id);
517 g_app_list.removeSurface(surface_id);
520 void WindowManager::removeClient(const string &appid)
522 HMI_DEBUG("Remove clinet %s from list", appid.c_str());
523 auto client = g_app_list.lookUpClient(appid);
524 this->lc->appTerminated(client);
525 g_app_list.removeClient(appid);
528 void WindowManager::exceptionProcessForTransition()
530 unsigned req_num = g_app_list.currentRequestNumber();
531 HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
532 g_app_list.removeRequest(req_num);
533 HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
534 this->processNextRequest();
537 void WindowManager::timerHandler()
539 unsigned req_num = g_app_list.currentRequestNumber();
540 HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
541 g_app_list.reqDump();
542 g_app_list.removeRequest(req_num);
543 this->processNextRequest();
546 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
549 unsigned req_num = g_app_list.currentRequestNumber();
553 if (g_app_list.haveRequest())
555 HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
556 goto proc_remove_request;
560 HMI_SEQ_DEBUG(req_num, "There is no request");
565 for (auto &act : actions)
570 auto const &surface_id = this->id_alloc.lookup(act.role);
571 if(surface_id == nullopt)
573 goto proc_remove_request;
575 string appid = g_app_list.getAppID(*surface_id, &found);
578 if (TaskVisible::INVISIBLE == act.visible)
580 // App is killed, so do not set this action
585 HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
590 auto client = g_app_list.lookUpClient(appid);
591 act.req_num = req_num;
595 ret = g_app_list.setAction(req_num, act);
596 if (ret != WMError::SUCCESS)
598 HMI_SEQ_ERROR(req_num, "Setting action is failed");
603 HMI_SEQ_DEBUG(req_num, "Start transition.");
604 ret = this->startTransition(req_num);
605 if (ret != WMError::SUCCESS)
607 if (ret == WMError::NO_LAYOUT_CHANGE)
609 goto proc_remove_request;
613 HMI_SEQ_ERROR(req_num, "Transition state is failed");
622 HMI_SEQ_ERROR(req_num, errorDescription(ret));
623 this->pmw.undoState();
626 g_app_list.removeRequest(req_num);
627 this->processNextRequest();
630 void WindowManager::processError(WMError error)
632 unsigned req_num = g_app_list.currentRequestNumber();
635 HMI_SEQ_ERROR(req_num, errorDescription(error));
636 g_app_list.removeRequest(req_num);
637 this->processNextRequest();
640 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
641 Task task, unsigned* req_num)
643 if (!g_app_list.contains(appid))
645 return WMError::NOT_REGISTERED;
648 auto client = g_app_list.lookUpClient(appid);
653 unsigned current = g_app_list.currentRequestNumber();
654 unsigned requested_num = g_app_list.getRequestNumber(appid);
655 if (requested_num != 0)
657 HMI_SEQ_INFO(requested_num,
658 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
662 WMRequest req = WMRequest(appid, role, area, task);
663 unsigned new_req = g_app_list.addRequest(req);
665 g_app_list.reqDump();
667 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
669 return WMError::SUCCESS;
672 WMError WindowManager::checkPolicy(unsigned req_num)
677 // get current trigger
679 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
680 auto trigger = g_app_list.getRequest(req_num, &found);
683 ret = WMError::NO_ENTRY;
686 string req_area = trigger.area;
688 // Input event data to PolicyManager
689 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
691 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
695 // Execute state transition of PolicyManager
696 if (0 > this->pmw.executeStateTransition())
698 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
702 ret = WMError::SUCCESS;
704 g_app_list.reqDump();
709 WMError WindowManager::startTransition(unsigned req_num)
711 bool sync_draw_happen = false;
713 WMError ret = WMError::SUCCESS;
714 auto actions = g_app_list.getActions(req_num, &found);
717 ret = WMError::NO_ENTRY;
718 HMI_SEQ_ERROR(req_num,
719 "Window Manager bug :%s : Action is not set", errorDescription(ret));
723 g_app_list.reqDump();
724 for (const auto &action : actions)
726 if (action.visible == TaskVisible::VISIBLE)
728 sync_draw_happen = true;
729 struct rect r = this->lc->getAreaSize(action.area);
730 action.client->emitSyncDraw(action.area, r);
734 if (sync_draw_happen)
740 // deactivate only, no syncDraw
741 // Make it deactivate here
742 for (const auto &x : actions)
744 this->lc->visibilityChange(x);
745 x.client->emitActive(false);
746 x.client->emitVisible(false);
748 this->lc->renderLayers();
749 ret = WMError::NO_LAYOUT_CHANGE;
754 WMError WindowManager::doEndDraw(unsigned req_num)
758 auto actions = g_app_list.getActions(req_num, &found);
759 WMError ret = WMError::SUCCESS;
762 ret = WMError::NO_ENTRY;
766 HMI_SEQ_INFO(req_num, "do endDraw");
768 // layout change and make it visible
769 for (const auto &act : actions)
771 if(act.visible != TaskVisible::NO_CHANGE)
774 ret = this->lc->layoutChange(act);
775 if(ret != WMError::SUCCESS)
777 HMI_SEQ_WARNING(req_num,
778 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
781 ret = this->lc->visibilityChange(act);
783 act.client->emitActive((act.visible == VISIBLE));
784 act.client->emitVisible((act.visible == VISIBLE));
786 if (ret != WMError::SUCCESS)
788 HMI_SEQ_WARNING(req_num,
789 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
792 HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
795 this->lc->renderLayers();
797 HMI_SEQ_INFO(req_num, "emit flushDraw");
799 for(const auto &act_flush : actions)
801 if(act_flush.visible == TaskVisible::VISIBLE)
803 act_flush.client->emitFlushDraw();
810 void WindowManager::emitScreenUpdated(unsigned req_num)
813 HMI_SEQ_DEBUG(req_num, "emit screen updated");
815 auto actions = g_app_list.getActions(req_num, &found);
818 HMI_SEQ_ERROR(req_num,
819 "Window Manager bug :%s : Action is not set",
820 errorDescription(WMError::NO_ENTRY));
824 // create json object
825 json_object *j = json_object_new_object();
826 json_object *jarray = json_object_new_array();
828 for(const auto& action: actions)
830 if(action.visible != TaskVisible::INVISIBLE)
832 json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
835 json_object_object_add(j, kKeyIds, jarray);
836 HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
838 int ret = afb_event_push(
839 this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
842 HMI_DEBUG("afb_event_push failed: %m");
846 void WindowManager::setTimer()
849 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
850 HMI_ERROR("Could't set time (clock_gettime() returns with error");
854 HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
855 if (g_timer_ev_src == nullptr)
857 // firsttime set into sd_event
858 int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
859 CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
862 HMI_ERROR("Could't set timer");
867 // update timer limitation after second time
868 sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
869 sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
873 void WindowManager::stopTimer()
875 unsigned req_num = g_app_list.currentRequestNumber();
876 HMI_SEQ_DEBUG(req_num, "Timer stop");
877 int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
880 HMI_SEQ_ERROR(req_num, "Timer stop failed");
884 void WindowManager::processNextRequest()
887 g_app_list.reqDump();
888 unsigned req_num = g_app_list.currentRequestNumber();
889 if (g_app_list.haveRequest())
891 HMI_SEQ_DEBUG(req_num, "Process next request");
892 WMError rc = checkPolicy(req_num);
893 if (rc != WMError::SUCCESS)
895 HMI_SEQ_ERROR(req_num, errorDescription(rc));
900 HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
904 const char* WindowManager::convertRoleOldToNew(char const *old_role)
906 const char *new_role = nullptr;
908 for (auto const &on : this->roleold2new)
910 std::regex regex = std::regex(on.first);
911 if (std::regex_match(old_role, regex))
913 // role is old. So convert to new.
914 new_role = on.second.c_str();
919 if (nullptr == new_role)
921 // role is new or fallback.
925 HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
930 int WindowManager::loadOldRoleDb()
932 std::string file_name(get_file_path("old_roles.db"));
935 json_object* json_obj;
936 int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
939 HMI_ERROR("Could not open old_role.db, so use default old_role information");
940 json_obj = json_tokener_parse(kDefaultOldRoleDb);
942 HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
945 json_object* json_cfg;
946 if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
948 HMI_ERROR("Parse Error!!");
952 int len = json_object_array_length(json_cfg);
953 HMI_DEBUG("json_cfg len:%d", len);
954 HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
956 for (int i=0; i<len; i++)
958 json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
960 const char* old_role = jh::getStringFromJson(json_tmp, "name");
961 if (nullptr == old_role)
963 HMI_ERROR("Parse Error!!");
967 const char* new_role = jh::getStringFromJson(json_tmp, "new");
968 if (nullptr == new_role)
970 HMI_ERROR("Parse Error!!");
974 this->roleold2new[old_role] = std::string(new_role);
978 for(auto itr = this->roleold2new.begin();
979 itr != this->roleold2new.end(); ++itr)
981 HMI_DEBUG(">>> role old:%s new:%s",
982 itr->first.c_str(), itr->second.c_str());
985 // Release json_object
986 json_object_put(json_obj);
991 const char* WindowManager::kDefaultOldRoleDb = "{ \
994 \"name\": \"HomeScreen\", \
995 \"new\": \"homescreen\" \
998 \"name\": \"Music\", \
1002 \"name\": \"MediaPlayer\", \
1003 \"new\": \"music\" \
1006 \"name\": \"Video\", \
1007 \"new\": \"video\" \
1010 \"name\": \"VideoPlayer\", \
1011 \"new\": \"video\" \
1014 \"name\": \"WebBrowser\", \
1015 \"new\": \"browser\" \
1018 \"name\": \"Radio\", \
1019 \"new\": \"radio\" \
1022 \"name\": \"Phone\", \
1023 \"new\": \"phone\" \
1026 \"name\": \"Navigation\", \
1030 \"name\": \"HVAC\", \
1034 \"name\": \"Settings\", \
1035 \"new\": \"settings\" \
1038 \"name\": \"Dashboard\", \
1039 \"new\": \"dashboard\" \
1042 \"name\": \"POI\", \
1046 \"name\": \"Mixer\", \
1047 \"new\": \"mixer\" \
1050 \"name\": \"Restriction\", \
1051 \"new\": \"restriction\" \
1054 \"name\": \"^OnScreen.*\", \
1055 \"new\": \"on_screen\" \