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.
21 #include "window_manager.hpp"
22 #include "json_helper.hpp"
23 #include "applist.hpp"
27 #include <systemd/sd-event.h>
30 #define WM_LASTMODE_PATH "/etc/lastmode.json"
34 using std::unordered_map;
39 static const uint64_t kTimeOut = 3ULL; /* 3s */
41 /* DrawingArea name used by "{layout}.{area}" */
42 const char kNameLayoutNormal[] = "normal";
43 const char kNameLayoutSplit[] = "split";
44 const char kNameAreaFull[] = "full";
45 const char kNameAreaMain[] = "main";
46 const char kNameAreaSub[] = "sub";
48 /* Key for json obejct */
49 const char kKeyDrawingName[] = "drawing_name";
50 const char kKeyDrawingArea[] = "drawing_area";
51 const char kKeyDrawingRect[] = "drawing_rect";
52 const char kKeyX[] = "x";
53 const char kKeyY[] = "y";
54 const char kKeyWidth[] = "width";
55 const char kKeyHeight[] = "height";
56 const char kKeyWidthPixel[] = "width_pixel";
57 const char kKeyHeightPixel[] = "height_pixel";
58 const char kKeyWidthMm[] = "width_mm";
59 const char kKeyHeightMm[] = "height_mm";
60 const char kKeyScale[] = "scale";
61 const char kKeyIds[] = "ids";
63 static const vector<string> kListEventName{
76 "lightstatusBrakeOff",
82 static const char kPathOldRolesConfigFile[] = "/etc/old_roles.json";
83 static sd_event_source *g_timer_ev_src = nullptr;
84 static sd_event_source *g_timer_endInit_src = nullptr;
85 static AppList g_app_list;
86 static WindowManager *g_context;
87 static bool testFlg = false;
88 static vector<string> white_list_area_size_change = {
94 AfbClosure(unsigned pid, unsigned ppid, unsigned surface)
95 : pid(pid), ppid(ppid), surface(surface) {}
96 ~AfbClosure() = default;
105 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
107 HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
108 reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
112 static int endInitTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
114 reinterpret_cast<wm::WindowManager *>(userdata)->sendHandshake();
118 static void onStateTransitioned(vector<WMAction> actions)
120 g_context->startTransitionWrapper(actions);
123 static void onError()
125 g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
128 static void onReceiveRemoteRequest(json_object *data)
130 g_context->processForRemoteRequest(data);
137 WindowManager::WindowManager()
141 this->subscribed = false;
143 const char *path = getenv("AFM_APP_INSTALL_DIR");
146 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
150 // TODO: ECU name should be decide by config file
151 // Get mode and decide ECU name
152 string ecu_name = this->wmcon.getEcuName();
154 this->lc = std::make_shared<LayerControl>(root, ecu_name);
156 HMI_DEBUG("Layer Controller initialized");
159 int WindowManager::init()
163 LayerControlCallbacks lmcb;
164 lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
165 this->surface_created(pid, surface);
167 lmcb.surfaceDestroyed = [&](unsigned surface){
168 this->surface_removed(surface);
171 err = this->lc->init(lmcb);
172 if (err == WMError::FAIL)
174 HMI_ERROR("Could not connect to weston");
178 // TODO: application requests by old role,
179 // so create role map (old, new)
180 // Load old_roles config file
181 this->loadOldRolesConfigFile();
183 // Initialize LowCanClient
184 this->lcc.initialize();
186 // Store my context for calling callback from PolicyManager
189 // Initialize PMWrapper
190 this->pmw.initialize(this->wmcon.getEcuName());
192 // Register callback to PolicyManager
193 this->pmw.registerCallback(onStateTransitioned, onError);
195 // Initialize WMConnection
196 this->wmcon.initialize();
198 // Register callback to WMConnection
199 this->wmcon.registerCallback(onReceiveRemoteRequest);
202 for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
204 map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str());
207 const struct rect css_bg = this->lc->getAreaSize("fullscreen");
208 Screen screen = this->lc->getScreenInfo();
209 rectangle dp_bg(screen.width(), screen.height());
211 dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
212 dp_bg.fit(screen.width(), screen.height());
213 dp_bg.center(screen.width(), screen.height());
214 HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
215 css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
217 double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
218 this->lc->setupArea(dp_bg, scale);
222 return 0; //init_layers();
225 void WindowManager::sendHandshake()
229 HMI_DEBUG("Check End Init");
231 if (this->subscribed && this->wmcon.getEndInit())
233 HMI_DEBUG("End Inited");
238 HMI_DEBUG("Not End Init");
239 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0)
241 HMI_ERROR("Could't set time (clock_gettime() returns with error");
245 uint64_t sleep = this->wmcon.getSleepTime();
246 uint64_t usec = (ts.tv_sec * 1000000000ULL) + ts.tv_nsec + (sleep * 1000000);
253 if (g_timer_endInit_src == nullptr)
255 int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_endInit_src,
256 CLOCK_BOOTTIME, usec, 1, endInitTimerHandler, this);
260 sd_event_source_set_time(g_timer_endInit_src, usec);
261 sd_event_source_set_enabled(g_timer_endInit_src, SD_EVENT_ONESHOT);
266 void WindowManager::setSubscribed(bool flg)
268 usleep(this->wmcon.getSleepTime() * 1000);
270 this->subscribed = flg;
273 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
275 // TODO: application requests by old role,
276 // so convert role old to new
277 const char *role = this->convertRoleOldToNew(drawing_name);
279 string s_appid = appid;
280 string s_role = role;
282 if(!g_app_list.contains(s_appid))
284 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
287 // register drawing_name as fallback and make it displayed.
288 l_id = this->lc->getNewLayerID("fallback", &l_name);
289 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
292 return Err<int>("Designated role does not match any role, fallback is disabled");
296 // TODO: remote layer size is fixed value
297 if ("Remote" == l_name)
299 this->lc->createNewRemoteLayer(l_id);
303 this->lc->createNewLayer(l_id);
306 // add client into the db
307 g_app_list.addClient(s_appid, l_id, s_role);
310 // generate surface ID for ivi-shell application
312 auto rname = this->id_alloc.lookup(string(role));
315 // name does not exist yet, allocate surface id...
316 auto id = int(this->id_alloc.generate_id(role));
317 this->tmp_surface2app[id] = {s_appid, 0};
320 HMI_NOTICE("WORK AROUND: add surface on request surface");
321 auto client = g_app_list.lookUpClient(s_appid);
322 client->addSurface(id);
325 // Set role map of (new, old)
326 this->rolenew2old[role] = string(drawing_name);
331 // Check currently registered drawing names if it is already there.
332 return Err<int>("Surface already present");
335 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
338 unsigned sid = std::stol(ivi_id);
340 HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
342 * IVI-shell doesn't send surface_size event via ivi-wm protocol
343 * if the application is using XDG surface.
344 * So WM has to set surface size with original size here
346 WMError ret = this->lc->setXDGSurfaceOriginSize(sid);
349 HMI_ERROR("%s", errorDescription(ret));
350 HMI_WARNING("The main user of this API is runXDG");
354 // TODO: application requests by old role,
355 // so convert role old to new
356 const char *role = this->convertRoleOldToNew(drawing_name);
357 string s_role = role;
358 string s_appid = appid;
361 if(!g_app_list.contains(s_appid))
363 // auto lid = this->layers.get_layer_id(string(role));
364 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
368 * register drawing_name as fallback and make it displayed.
370 l_id = this->lc->getNewLayerID("fallback", &l_name);
371 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
374 return "Designated role does not match any role, fallback is disabled";
378 // TODO: remote layer size is fixed value
379 if ("Remote" == l_name)
381 this->lc->createNewRemoteLayer(l_id);
385 this->lc->createNewLayer(l_id);
388 // add client into the db
389 g_app_list.addClient(s_appid, l_id, s_role);
392 auto rname = this->id_alloc.lookup(s_role);
395 return "Surface already present";
398 // register pair drawing_name and ivi_id
399 this->id_alloc.register_name_id(role, sid);
401 auto client = g_app_list.lookUpClient(s_appid);
402 client->addSurface(sid);
404 // Set role map of (new, old)
405 this->rolenew2old[role] = string(drawing_name);
410 bool WindowManager::api_set_role(char const *appid, char const *drawing_name)
414 // TODO: application requests by old role,
415 // so convert role old to new
416 const char *role = this->convertRoleOldToNew(drawing_name);
417 string s_role = role;
418 string s_appid = appid;
422 if(!g_app_list.contains(s_appid))
424 // auto lid = this->layers.get_layer_id(string(role));
425 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
429 * register drawing_name as fallback and make it displayed.
431 l_id = this->lc->getNewLayerID("fallback", &l_name);
432 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
435 HMI_ERROR("Designated role does not match any role, fallback is disabled");
440 // TODO: remote layer size is fixed value
441 if ("Remote" == l_name)
443 this->lc->createNewRemoteLayer(l_id);
447 this->lc->createNewLayer(l_id);
450 // add client into the db
451 g_app_list.addClient(s_appid, l_id, s_role);
452 // Set role map of (new, old)
453 this->rolenew2old[role] = string(drawing_name);
456 // for(auto itr = this->tmp_surface2app.begin();
457 // itr != this->tmp_surface2app.end() ; ++itr)
459 for(auto& x : this->tmp_surface2app)
461 if(x.second.appid == s_appid)
463 unsigned surface = x.first;
464 auto client = g_app_list.lookUpClient(s_appid);
465 client->addSurface(surface);
466 this->tmp_surface2app.erase(surface);
467 this->id_alloc.register_name_id(s_role, surface);
473 // search floating surfaceID from pid if pid is designated.
474 wm_err = g_app_list.popFloatingSurface(pid, &surface);
477 // get floating surface with appid. If WM queries appid from pid,
478 // WM can bind surface and role with appid(not implemented yet)
479 //wm_err = g_app_list.popFloatingSurface(id);
481 if(wm_err != WMError::SUCCESS){
482 HMI_ERROR("No floating surface for app: %s", id.c_str());
483 g_app_list.addFloatingClient(id, lid, role);
484 HMI_NOTICE("%s : Waiting for surface creation", id.c_str());
489 if (g_app_list.contains(id))
491 HMI_INFO("Add role: %s with surface: %d. Client %s has multi surfaces.",
492 role.c_str(), surface, id.c_str());
493 auto client = g_app_list.lookUpClient(id);
494 client->appendRole(role);
497 HMI_INFO("Create new client: %s, surface: %d into layer: %d with role: %s",
498 id.c_str(), surface, lid, role.c_str());
499 g_app_list.addClient(id, lid, role);
502 // register pair drawing_name and ivi_id
507 void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
508 char const *drawing_area, const reply_func &reply)
510 // TODO: application requests by old role,
511 // so convert role old to new
512 const char *c_role = this->convertRoleOldToNew(drawing_name);
515 string role = c_role;
516 string area = drawing_area;
518 if(!g_app_list.contains(id))
520 reply("app doesn't request 'requestSurface' or 'setRole' yet");
523 auto client = g_app_list.lookUpClient(id);
525 // unsigned srfc = client->surfaceID(role);
526 // unsigned layer = client->layerID();
528 // g_app_list.removeFloatingSurface(client->surfaceID());
529 // g_app_list.removeFloatingSurface(client);i
530 unsigned layer = client->layerID();
533 //TODO Deactivate remote viewing app for remote view change to local view.
534 if(this->lc->hasRemoteLayer(layer) != "" && this->wmcon.getAppIdToEcuName(appid) != "")
536 HMI_DEBUG("Deactivate remote App %s", drawing_name);
537 std::string tmp_area = this->wmcon.getAppIdToEcuName(appid) + ".split.sub";
538 HMI_DEBUG("Deactivate area name: %s", tmp_area.c_str());
539 this->wmcon.sendRequest("deactivateWindow", appid, drawing_name, tmp_area.c_str());
541 unsigned req_num = g_app_list.currentRequestNumber();
542 const char *c_role = this->convertRoleOldToNew(drawing_name);
543 bool end_draw_finished = true;
550 TaskVisible::REMOTE_INVISIBLE,
552 TaskCarState::NO_TASK
555 this->lc->visibilityChange(act);
556 this->lc->renderLayers();
558 this->emit_invisible(role);
559 this->emit_deactivated(role);
563 Task task = Task::TASK_ALLOCATE;
564 unsigned req_num = 0;
565 WMError ret = WMError::UNKNOWN;
567 ret = this->setRequest(id, role, area, task, &req_num);
569 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
570 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
572 if(ret != WMError::SUCCESS)
574 HMI_ERROR(errorDescription(ret));
575 reply("Failed to set request");
579 this->wmcon.setAppIdToEcuName(id, this->wmcon.getEcuName());
582 if (req_num != g_app_list.currentRequestNumber())
584 // Add request, then invoked after the previous task is finished
585 HMI_SEQ_DEBUG(req_num, "request is accepted");
592 ret = this->checkPolicy(req_num);
594 if (ret != WMError::SUCCESS)
597 HMI_SEQ_ERROR(req_num, errorDescription(ret));
598 g_app_list.removeRequest(req_num);
599 this->processNextRequest();
603 void WindowManager::api_activate_surface_for_slave(
604 char const *appid, char const *drawing_name,
605 char const *drawing_area, const reply_func &reply)
607 // TODO: application requests by old role,
608 // so convert role old to new
609 const char *c_role = this->convertRoleOldToNew(drawing_name);
612 string role = c_role;
613 string area = drawing_area;
615 if(!g_app_list.contains(id))
617 // Request surface of app in slave to register app information
618 this->api_request_surface(appid, drawing_name);
620 // Set role of app in slave to register app information
621 this->api_set_role(appid, drawing_name);
623 auto client = g_app_list.lookUpClient(id);
625 // unsigned srfc = client->surfaceID(role);
626 // unsigned layer = client->layerID();
628 // g_app_list.removeFloatingSurface(client->surfaceID());
629 // g_app_list.removeFloatingSurface(client);
631 Task task = Task::TASK_ALLOCATE;
632 unsigned req_num = 0;
633 WMError ret = WMError::UNKNOWN;
635 ret = this->setRequestForSlave(id, role, area, task, &req_num);
637 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
638 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
640 if(ret != WMError::SUCCESS)
642 HMI_ERROR(errorDescription(ret));
643 reply("Failed to set request");
647 this->wmcon.setAppIdToReceivedEcuName(id);
650 if (req_num != g_app_list.currentRequestNumber())
652 // Add request, then invoked after the previous task is finished
653 HMI_SEQ_DEBUG(req_num, "request is accepted");
660 ret = this->checkPolicyForSlave(req_num);
662 if (ret != WMError::SUCCESS)
665 HMI_SEQ_ERROR(req_num, errorDescription(ret));
666 g_app_list.removeRequest(req_num);
667 this->processNextRequest();
671 void WindowManager::api_activate_surface_to_master(
672 char const *appid, char const *drawing_name,
673 char const *drawing_area, const reply_func &reply)
675 // TODO: application requests by old role,
676 // so convert role old to new
677 const char *c_role = this->convertRoleOldToNew(drawing_name);
680 string role = c_role;
681 string area = drawing_area;
683 if(!g_app_list.contains(id))
685 reply("app doesn't request 'requestSurface' or 'setRole' yet");
688 auto client = g_app_list.lookUpClient(id);
690 // unsigned srfc = client->surfaceID(role);
691 // unsigned layer = client->layerID();
693 // g_app_list.removeFloatingSurface(client->surfaceID());
694 // g_app_list.removeFloatingSurface(client);
696 unsigned layer = client->layerID();
698 //TODO Deactivate remote viewing app for remote view change to local view.
699 if(this->lc->hasRemoteLayer(layer) != "" && this->wmcon.getAppIdToEcuName(appid) != "")
701 HMI_DEBUG("Deactivate remote App %s", drawing_name);
702 std::string tmp_area = this->wmcon.getAppIdToEcuName(appid) + ".split.sub";
703 HMI_DEBUG("Deactivate area name: %s", tmp_area.c_str());
704 this->wmcon.sendRequest("deactivateWindow", appid, drawing_name, tmp_area.c_str());
706 unsigned req_num = g_app_list.currentRequestNumber();
707 const char *c_role = this->convertRoleOldToNew(drawing_name);
708 bool end_draw_finished = true;
715 TaskVisible::REMOTE_INVISIBLE,
717 TaskCarState::NO_TASK
720 this->lc->renderLayers();
721 this->lc->visibilityChange(act);
723 this->emit_invisible(role);
724 this->emit_deactivated(role);
727 Task task = Task::TASK_ALLOCATE;
728 unsigned req_num = 0;
729 WMError ret = WMError::UNKNOWN;
731 ret = this->setRequest(id, role, area, task, &req_num);
733 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
734 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
736 if(ret != WMError::SUCCESS)
738 HMI_ERROR(errorDescription(ret));
739 reply("Failed to set request");
743 std::string ecu_name;
744 ecu_name = this->wmcon.getAreaToEcuName(area.c_str());
746 this->wmcon.setAppIdToEcuName(id, ecu_name);
749 if (req_num != g_app_list.currentRequestNumber())
751 // Add request, then invoked after the previous task is finished
752 HMI_SEQ_DEBUG(req_num, "request is accepted");
759 int i_ret = this->wmcon.sendRequest("activateWindow", appid,
760 drawing_name, drawing_area);
764 HMI_SEQ_ERROR(req_num, errorDescription(ret));
765 g_app_list.removeRequest(req_num);
766 this->processNextRequest();
772 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
773 const reply_func &reply)
775 // TODO: application requests by old role,
776 // so convert role old to new
777 const char *c_role = this->convertRoleOldToNew(drawing_name);
783 string role = c_role;
784 string area = ""; //drawing_area;
785 Task task = Task::TASK_RELEASE;
786 unsigned req_num = 0;
787 WMError ret = WMError::UNKNOWN;
789 ret = this->setRequest(id, role, area, task, &req_num);
791 if (ret != WMError::SUCCESS)
793 HMI_ERROR(errorDescription(ret));
794 reply("Failed to set request");
799 if (req_num != g_app_list.currentRequestNumber())
801 // Add request, then invoked after the previous task is finished
802 HMI_SEQ_DEBUG(req_num, "request is accepted");
809 ret = this->checkPolicy(req_num);
811 if (ret != WMError::SUCCESS)
814 HMI_SEQ_ERROR(req_num, errorDescription(ret));
815 g_app_list.removeRequest(req_num);
816 this->processNextRequest();
820 void WindowManager::api_deactivate_surface_for_slave(char const *appid, char const *drawing_name,
821 const reply_func &reply)
823 // TODO: application requests by old role,
824 // so convert role old to new
825 const char *c_role = this->convertRoleOldToNew(drawing_name);
831 string role = c_role;
832 string area = "";//drawing_area;
833 Task task = Task::TASK_RELEASE;
834 unsigned req_num = 0;
835 WMError ret = WMError::UNKNOWN;
837 ret = this->setRequest(id, role, area, task, &req_num);
839 if (ret != WMError::SUCCESS)
841 HMI_ERROR(errorDescription(ret));
842 reply("Failed to set request");
847 if (req_num != g_app_list.currentRequestNumber())
849 // Add request, then invoked after the previous task is finished
850 HMI_SEQ_DEBUG(req_num, "request is accepted");
857 ret = this->checkPolicyForSlave(req_num);
859 if (ret != WMError::SUCCESS)
862 HMI_SEQ_ERROR(req_num, errorDescription(ret));
863 g_app_list.removeRequest(req_num);
864 this->processNextRequest();
868 void WindowManager::api_deactivate_surface_to_master(char const *appid, char const *drawing_name,
869 const reply_func &reply)
871 // TODO: application requests by old role,
872 // so convert role old to new
873 const char *c_role = this->convertRoleOldToNew(drawing_name);
879 string role = c_role;
880 string area = "";//drawing_area;
881 Task task = Task::TASK_RELEASE;
882 unsigned req_num = 0;
883 WMError ret = WMError::UNKNOWN;
885 ret = this->setRequest(id, role, area, task, &req_num);
887 if (ret != WMError::SUCCESS)
889 HMI_ERROR(errorDescription(ret));
890 reply("Failed to set request");
895 if (req_num != g_app_list.currentRequestNumber())
897 // Add request, then invoked after the previous task is finished
898 HMI_SEQ_DEBUG(req_num, "request is accepted");
905 int i_ret = this->wmcon.sendRequest("deactivateWindow", appid,
910 HMI_SEQ_ERROR(req_num, errorDescription(ret));
911 g_app_list.removeRequest(req_num);
912 this->processNextRequest();
918 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
920 // TODO: application requests by old role,
921 // so convert role old to new
922 const char *c_role = this->convertRoleOldToNew(drawing_name);
925 string role = c_role;
926 unsigned current_req = g_app_list.currentRequestNumber();
927 bool result = g_app_list.setEndDrawFinished(current_req, id, role);
931 HMI_ERROR("%s is not in transition state", id.c_str());
935 if (g_app_list.endDrawFullfilled(current_req))
937 // do task for endDraw
939 WMError ret = this->doEndDraw(current_req);
941 if(ret != WMError::SUCCESS)
943 //this->emit_error();
945 // Undo state of PolicyManager
946 this->pmw.undoState();
947 this->lc->undoUpdate();
949 this->emitScreenUpdated(current_req);
950 HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
952 this->saveLastModeData(current_req);
954 g_app_list.removeRequest(current_req);
956 this->processNextRequest();
960 HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
965 int WindowManager::api_subscribe(afb_req req, int event_id)
967 struct afb_event event = this->map_afb_event[kListEventName[event_id]];
968 return afb_req_subscribe(req, event);
971 void WindowManager::api_handshake()
973 this->send_event(kListEventName[Event_Handshake]);
976 void WindowManager::api_enddraw_for_remote(char const *appid, char const *drawing_name)
978 int ret = this->wmcon.sendRequest("endDraw", appid, drawing_name, "");
983 this->pmw.undoState();
984 this->lc->undoUpdate();
986 unsigned current_req = g_app_list.currentRequestNumber();
987 g_app_list.removeRequest(current_req);
988 this->processNextRequest();
993 this->api_enddraw(appid, drawing_name);
996 bool WindowManager::api_client_set_render_order(char const* appid, const vector<string>& render_order)
1000 auto client = g_app_list.lookUpClient(id);
1003 client->setRenderOrder(render_order);
1008 string WindowManager::api_client_attach_service_surface
1009 (const char* appid, const char* dest, const char* service_surface)
1011 string uuid, s_dest = dest;
1012 auto client = g_app_list.lookUpClient(s_dest);
1015 HMI_ERROR("Failed to look up destination [%s]", dest);
1018 uuid = client->attachTmpServiceSurface(appid, service_surface);
1019 this->tmp_services.emplace_back(TmpService{appid, dest, service_surface, uuid});
1023 json_object* WindowManager::api_get_area_list()
1025 json_object* ret = json_object_new_object();
1026 json_object* jarray = json_object_new_array();
1027 unordered_map<string, struct rect> area2size = this->lc->getAreaList();
1028 for(const auto& area : area2size)
1030 json_object* j = json_object_new_object();
1031 json_object_object_add(j, "name", json_object_new_string(area.first.c_str()));
1032 json_object* jrect = json_object_new_object();
1033 json_object_object_add(jrect, "x", json_object_new_int(area.second.x));
1034 json_object_object_add(jrect, "y", json_object_new_int(area.second.y));
1035 json_object_object_add(jrect, "w", json_object_new_int(area.second.w));
1036 json_object_object_add(jrect, "h", json_object_new_int(area.second.h));
1037 json_object_object_add(j, "rect", jrect);
1038 json_object_array_add(jarray, j);
1040 json_object_object_add(ret, "areas", jarray);
1041 HMI_DEBUG("area_list: %s", json_object_get_string(ret));
1045 void WindowManager::api_change_area_size(ChangeAreaReq &areas)
1049 auto client = g_app_list.lookUpClient(areas.appname);
1051 if(client == nullptr)
1053 HMI_ERROR("Call register your role with setRole or requestSurface");
1056 if(std::find(white_list_area_size_change.begin(),
1057 white_list_area_size_change.end(), client->role()) == white_list_area_size_change.end())
1059 HMI_ERROR("Application %s which has the role %s is not allowed to change area size", client->appID().c_str(), client->role().c_str());
1064 ret = this->lc->updateAreaList(areas);
1065 if(ret != WMError::SUCCESS)
1067 HMI_ERROR("%d : %s", ret, errorDescription(ret));
1070 ret = this->lc->getUpdateAreaList(&areas);
1072 if(ret != WMError::SUCCESS)
1074 HMI_ERROR("%d : %s", ret, errorDescription(ret));
1081 ret = this->setRequest(client->appID(), client->role(), "-", Task::TASK_CHANGE_AREA, &req_num); // area is null
1082 if(ret != WMError::SUCCESS)
1084 HMI_SEQ_ERROR(req_num, "%d : %s", ret, errorDescription(ret));
1087 for(const auto &update: areas.update_app2area)
1090 auto client = g_app_list.lookUpClient(update.first);
1091 if(client == nullptr)
1093 HMI_SEQ_ERROR(req_num, "%s : %s", update.first.c_str(), errorDescription(ret));
1094 g_app_list.removeRequest(req_num);
1095 this->processNextRequest();
1098 ret = g_app_list.setAction(req_num, client, client->role(), update.second, TaskVisible::VISIBLE);
1099 if(ret != WMError::SUCCESS)
1101 HMI_SEQ_ERROR(req_num, "Failed to set request");
1105 HMI_SEQ_INFO(req_num, "Area change request");
1106 g_app_list.reqDump();
1108 // Request change size to applications
1109 for(const auto &action : g_app_list.getActions(req_num, &found))
1111 string old_role = this->rolenew2old[action.role];
1112 this->emit_syncdraw(old_role, action.area);
1116 result<json_object *> WindowManager::api_get_display_info()
1118 Screen screen = this->lc->getScreenInfo();
1120 json_object *object = json_object_new_object();
1121 json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
1122 json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
1124 json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
1125 json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
1126 json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
1128 return Ok<json_object *>(object);
1131 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
1133 HMI_DEBUG("called");
1135 // TODO: application requests by old role,
1136 // so convert role old to new
1137 const char *role = this->convertRoleOldToNew(drawing_name);
1139 // Check drawing name, surface/layer id
1140 auto const &surface_id = this->id_alloc.lookup(role);
1143 return Err<json_object *>("Surface does not exist");
1146 // Set area rectangle
1147 rect area_info = this->area_info[*surface_id];
1148 json_object *object = json_object_new_object();
1149 json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
1150 json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
1151 json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
1152 json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
1154 return Ok<json_object *>(object);
1157 result<json_object *> WindowManager::api_get_car_info(char const *label)
1159 json_object *j_in = nullptr;
1160 json_object *j_out = nullptr;
1162 if (0 == strcmp("parking_brake_status", label))
1164 // Get parking brake status
1165 json_bool val = (this->crr_car_info.parking_brake_stt) ? TRUE : FALSE;
1166 j_in = json_object_new_boolean(val);
1168 else if (0 == strcmp("accelerator.pedal.position", label))
1170 // Get accelerator pedal position
1171 double val = this->crr_car_info.accel_pedal_pos;
1172 j_in = json_object_new_double(val);
1174 else if (0 == strcmp("car_state", label))
1176 // Get running state
1177 const char* val = (this->crr_car_info.running_stt) ? "run" : "stop";
1178 j_in = json_object_new_string(val);
1180 else if (0 == strcmp("lightstatus.brake", label)) {
1181 // Get lightstatus brake status
1182 json_bool val = (this->crr_car_info.lightstatus_brake_stt) ? TRUE : FALSE;
1183 j_in = json_object_new_boolean(val);
1187 return Err<json_object *>("Car info does not exist");
1190 // Create output object
1191 j_out = json_object_new_object();
1192 json_object_object_add(j_out, "value", j_in);
1194 return Ok<json_object *>(j_out);
1197 void WindowManager::send_event(const string& evname)
1199 HMI_DEBUG("%s: %s", __func__, evname.c_str());
1201 int ret = afb_event_push(this->map_afb_event[evname], nullptr);
1204 HMI_DEBUG("afb_event_push: %m");
1208 void WindowManager::send_event(const string& evname, const string& role)
1210 HMI_DEBUG("%s: %s(%s)", __func__, evname.c_str(), role.c_str());
1212 json_object *j = json_object_new_object();
1213 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
1215 int ret = afb_event_push(this->map_afb_event[evname], j);
1218 HMI_DEBUG("afb_event_push failed: %m");
1222 void WindowManager::send_event(const string& evname, const string& role, const string& area,
1223 int x, int y, int w, int h)
1225 HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
1226 __func__, evname.c_str(), role.c_str(), area.c_str(), x, y, w, h);
1228 json_object *j_rect = json_object_new_object();
1229 json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
1230 json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
1231 json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
1232 json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
1234 json_object *j = json_object_new_object();
1235 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
1236 json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
1237 json_object_object_add(j, kKeyDrawingRect, j_rect);
1239 int ret = afb_event_push(this->map_afb_event[evname], j);
1242 HMI_DEBUG("afb_event_push failed: %m");
1246 string WindowManager::searchApp(unsigned pid, unsigned ppid, unsigned surface, json_object* resp)
1248 // retrieve appid from pid from application manager
1250 // check appid then add it to the client
1251 HMI_INFO("Runners:%s", json_object_get_string(resp));
1252 int size = json_object_array_length(resp);
1253 HMI_INFO("pid %d, ppid %d, surface %d",pid, ppid, surface);
1254 for(int i = 0; i < size; i++)
1256 json_object *j = json_object_array_get_idx(resp, i);
1257 int runid = jh::getIntFromJson(j, "runid");
1258 const char* id = jh::getStringFromJson(j, "id");
1259 HMI_DEBUG("Appid %s, runid %d", id, runid);
1260 if(id && (runid == ppid))
1263 s_id.erase(s_id.find('@'));
1265 HMI_INFO("App found %s", appid.c_str());
1271 HMI_WARNING("Failed to retrieve id");
1276 void WindowManager::storeSurface(const string& appid, unsigned ppid, unsigned surface)
1278 auto elem = std::find_if(this->tmp_services.begin(), this->tmp_services.end(),
1279 [&appid](TmpService& ts){
1280 return (ts.dest == appid );
1283 this->lc->setXDGSurfaceOriginSize(surface);
1284 if(elem != this->tmp_services.end())
1287 auto client = g_app_list.lookUpClient(elem->dest);
1288 if(client == nullptr)
1292 HMI_INFO("Attach surface %d (service %s) to app %s", surface, elem->service.c_str(), elem->dest.c_str());
1293 client->attachServiceSurface(elem->service, surface);
1298 auto client = g_app_list.lookUpClient(appid);
1299 if(client != nullptr)
1301 client->addSurface(surface);
1302 this->id_alloc.register_name_id(client->role(), surface);
1306 // Store tmp surface and appid for application
1307 // who requests setRole after creating shell surface
1308 this->tmp_surface2app.emplace(surface, TmpClient{appid, ppid});
1316 void WindowManager::surface_created(unsigned pid, unsigned surface_id)
1319 if(this->tmp_surface2app.count(surface_id) != 0)
1321 string appid = this->tmp_surface2app[surface_id].appid;
1322 auto client = g_app_list.lookUpClient(appid);
1323 if(client != nullptr)
1325 WMError ret = client->addSurface(surface_id);
1326 HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
1327 if(ret != WMError::SUCCESS)
1329 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
1332 this->tmp_surface2app.erase(surface_id);
1336 HMI_NOTICE("Unknown surface %d", surface_id);
1338 std::ostringstream os;
1340 string path = "/proc/" + os.str() + "/stat";
1341 std::ifstream ifs(path.c_str());
1344 if(!ifs.fail() && std::getline(ifs, str))
1346 std::sscanf(str.data(), "%*d %*s %*c %d", &ppid);
1347 HMI_INFO("Retrieve ppid %d", ppid);
1351 HMI_ERROR("Failed to open /proc/%d/stat", pid);
1352 HMI_ERROR("File system may be different");
1355 struct AfbClosure* c = new struct AfbClosure(pid, ppid, surface_id);
1356 // search pid from surfaceID
1357 afb_service_call("afm-main", "runners", json_object_new_object(),
1358 [](void* closure, int stat, json_object* resp){
1359 HMI_DEBUG("check %s", json_object_get_string(resp));
1360 struct AfbClosure* c = static_cast<struct AfbClosure*>(closure);
1364 HMI_ERROR("Failed to call runners");
1369 json_object_object_get_ex(resp, "response", &j);
1370 string appid = g_context->searchApp(c->pid, c->ppid, c->surface, j);
1373 g_context->storeSurface(appid, c->ppid, c->surface);
1376 json_object_put(resp);
1382 void WindowManager::surface_removed(unsigned surface_id)
1384 HMI_DEBUG("Delete surface_id %u", surface_id);
1385 this->id_alloc.remove_id(surface_id);
1386 g_app_list.removeSurface(surface_id);
1389 void WindowManager::removeClient(const string &appid)
1391 HMI_DEBUG("Remove clinet %s from list", appid.c_str());
1392 auto client = g_app_list.lookUpClient(appid);
1393 this->lc->appTerminated(client);
1394 g_app_list.removeClient(appid);
1397 void WindowManager::exceptionProcessForTransition()
1399 unsigned req_num = g_app_list.currentRequestNumber();
1400 HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
1401 g_app_list.removeRequest(req_num);
1402 HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
1403 this->processNextRequest();
1406 void WindowManager::analyzeReceivedEvent(const char *event, struct json_object *object)
1408 HMI_DEBUG("event:%s", event);
1410 // If receive low can signal
1411 if (strstr(event, "low-can"))
1413 // Analyze low can signal
1414 const char *signal_name = this->lcc.analyzeCanSignal(object);
1416 // Create task for car state and input it to PolicyManager
1417 Task task = this->convertCanSignalToCarStateTask(signal_name);
1418 if (Task::TASK_INVALID != task)
1420 this->inputCarStateTask(task);
1425 void WindowManager::timerHandler()
1427 unsigned req_num = g_app_list.currentRequestNumber();
1428 HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
1429 g_app_list.reqDump();
1430 g_app_list.removeRequest(req_num);
1431 this->processNextRequest();
1434 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
1436 WMError ret = WMError::UNKNOWN;
1437 // req_num is guaranteed by Window Manager
1438 unsigned req_num = g_app_list.currentRequestNumber();
1439 Task task = Task::TASK_INVALID;
1441 if (actions.empty())
1443 if (g_app_list.haveRequest())
1445 HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
1446 goto proc_remove_request;
1450 HMI_SEQ_DEBUG(req_num, "There is no request");
1455 // Check weather there is the no request task
1456 // [The no request task]
1457 // - TaskCarState::RESTRICTION_MODE_OFF
1458 // - TaskCarState::RESTRICTION_MODE_ON
1459 for (const auto &act : actions)
1461 if (TaskCarState::RESTRICTION_MODE_OFF == act.car_state)
1463 task = Task::TASK_RESTRICTION_MODE_OFF;
1466 else if (TaskCarState::RESTRICTION_MODE_ON == act.car_state)
1468 task = Task::TASK_RESTRICTION_MODE_ON;
1473 // If there is the request-less task, set request here
1474 if (Task::TASK_INVALID != task) {
1476 ret = this->setRequest(task, &req_num);
1478 if(ret != WMError::SUCCESS)
1484 for (auto &act : actions)
1489 auto const &surface_id = this->id_alloc.lookup(act.role.c_str());
1490 if(surface_id == nullopt)
1492 HMI_SEQ_DEBUG(req_num, "There is not surface id for role:%s", act.role.c_str());
1496 string appid = g_app_list.getAppID(*surface_id, &found);
1499 if (TaskVisible::INVISIBLE == act.visible)
1501 HMI_SEQ_DEBUG(req_num, "role:%s is killed, so do not set this action", act.role.c_str());
1506 HMI_SEQ_ERROR(req_num, "appid of role:%s which is visible is not found", act.role.c_str());
1507 ret = WMError::FAIL;
1511 auto client = g_app_list.lookUpClient(appid);
1512 act.req_num = req_num;
1513 act.client = client;
1515 std::string appToEcuName = this->wmcon.getAppIdToEcuName(appid);
1517 if (this->wmcon.isRemoteEcu(appid))
1519 if (TaskVisible::VISIBLE == act.visible)
1521 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_VISIBLE");
1522 act.visible = TaskVisible::REQ_REMOTE_VISIBLE;
1526 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_INVISIBLE");
1527 act.visible = TaskVisible::REQ_REMOTE_INVISIBLE;
1532 ret = g_app_list.setAction(req_num, act);
1533 if (ret != WMError::SUCCESS)
1535 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1540 HMI_SEQ_DEBUG(req_num, "Start transition.");
1541 ret = this->startTransition(req_num);
1542 if (ret != WMError::SUCCESS)
1544 if (ret == WMError::NO_LAYOUT_CHANGE)
1546 goto proc_remove_request;
1550 HMI_SEQ_ERROR(req_num, "Transition state is failed");
1558 //this->emit_error()
1559 HMI_SEQ_ERROR(req_num, errorDescription(ret));
1560 this->pmw.undoState();
1562 proc_remove_request:
1563 g_app_list.removeRequest(req_num);
1564 this->processNextRequest();
1567 void WindowManager::processError(WMError error)
1569 unsigned req_num = g_app_list.currentRequestNumber();
1571 //this->emit_error()
1572 HMI_SEQ_ERROR(req_num, errorDescription(error));
1573 g_app_list.removeRequest(req_num);
1574 this->processNextRequest();
1577 void WindowManager::processForRemoteRequest(json_object *data)
1579 const char *req = jh::getStringFromJson(data, "req");
1580 const char *appid = jh::getStringFromJson(data, "appid");
1581 const char *drawing_name = jh::getStringFromJson(data, "drawing_name");
1582 const char *drawing_area = jh::getStringFromJson(data, "drawing_area");
1583 string request = req;
1584 string role = drawing_name;
1585 string area = drawing_area;
1587 if (!req || !drawing_name)
1589 HMI_ERROR("Parse Error!!");
1593 if (this->wmcon.getAreaToEcuName(drawing_area) == this->wmcon.getEcuName())
1597 HMI_ERROR("Parse Error!!");
1601 auto reply = [](const char *errmsg) {
1602 if (errmsg != nullptr)
1609 if ("activateWindow" == request)
1613 HMI_ERROR("Parse Error!!");
1617 this->api_activate_surface_for_slave(
1618 appid, drawing_name, drawing_area, reply);
1620 else if ("deactivateWindow" == request)
1622 this->api_deactivate_surface_for_slave(
1623 appid, drawing_name, reply);
1625 else if ("endDraw" == request)
1627 this->api_enddraw(appid, drawing_name);
1632 if ("syncDraw" == request)
1636 if (!appid || !drawing_area)
1638 HMI_ERROR("Parse Error!!");
1642 unsigned req_num = g_app_list.currentRequestNumber();
1643 auto client = g_app_list.lookUpClient(appid);
1645 // TODO: application requests by old role,
1646 // so convert role old to new
1647 const char *c_role = this->convertRoleOldToNew(drawing_name);
1650 bool end_draw_finished = false;
1657 TaskVisible::REMOTE_VISIBLE,
1659 TaskCarState::NO_TASK
1663 WMError ret = g_app_list.setAction(req_num, act);
1664 if (ret != WMError::SUCCESS)
1666 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1670 this->emit_syncdraw(role, area);
1671 this->wmcon.startSyncDrawForRemote(appid);
1674 else if ("activated" == request)
1676 this->emit_visible(role);
1677 this->emit_activated(area);
1679 else if ("deactivated" == request)
1683 if (!appid || !drawing_area)
1685 HMI_ERROR("Parse Error!!");
1689 unsigned req_num = g_app_list.currentRequestNumber();
1690 auto client = g_app_list.lookUpClient(appid);
1692 // TODO: application requests by old role,
1693 // so convert role old to new
1694 const char *c_role = this->convertRoleOldToNew(drawing_name);
1696 if(!this->wmcon.isRemoteEcu(appid))
1698 HMI_DEBUG("Deactivated");
1703 bool end_draw_finished = true;
1710 TaskVisible::REMOTE_INVISIBLE,
1712 TaskCarState::NO_TASK
1715 this->lc->visibilityChange(act);
1716 this->lc->renderLayers();
1718 this->emit_invisible(role);
1719 this->emit_deactivated(role);
1723 else if ("flushDraw" == request)
1725 this->emit_flushdraw(role);
1731 ******* Private Functions *******
1734 void WindowManager::emit_activated(const string& role)
1736 this->send_event(kListEventName[Event_Active], role);
1739 void WindowManager::emit_deactivated(const string& role)
1741 this->send_event(kListEventName[Event_Inactive], role);
1744 void WindowManager::emit_syncdraw(const string& role, char const *area, int x, int y, int w, int h)
1746 this->send_event(kListEventName[Event_SyncDraw], role, area, x, y, w, h);
1749 void WindowManager::emit_syncdraw(const string &role, const string &area)
1751 struct rect rect = this->lc->getAreaSize(area);
1752 this->send_event(kListEventName[Event_SyncDraw],
1753 role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
1756 void WindowManager::emit_flushdraw(const string& role)
1758 this->send_event(kListEventName[Event_FlushDraw], role);
1761 void WindowManager::emit_visible(const string& role, bool is_visible)
1763 this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], role);
1766 void WindowManager::emit_invisible(const string& role)
1768 return emit_visible(role, false);
1771 void WindowManager::emit_visible(const string& role) { return emit_visible(role, true); }
1773 void WindowManager::emitHeadlampOff()
1775 // Send HeadlampOff event for all application
1776 this->send_event(kListEventName[Event_HeadlampOff]);
1779 void WindowManager::emitHeadlampOn()
1781 // Send HeadlampOn event for all application
1782 this->send_event(kListEventName[Event_HeadlampOn]);
1785 void WindowManager::emitParkingBrakeOff()
1787 // Send ParkingBrakeOff event for all application
1788 this->send_event(kListEventName[Event_ParkingBrakeOff]);
1791 void WindowManager::emitParkingBrakeOn()
1793 // Send ParkingBrakeOn event for all application
1794 this->send_event(kListEventName[Event_ParkingBrakeOn]);
1797 void WindowManager::emitLightstatusBrakeOff()
1799 // Send LightstatusBrakeOff event for all application
1800 this->send_event(kListEventName[Event_LightstatusBrakeOff]);
1803 void WindowManager::emitLightstatusBrakeOn()
1805 // Send LightstatusBrakeOn event for all application
1806 this->send_event(kListEventName[Event_LightstatusBrakeOn]);
1809 void WindowManager::emitCarStop()
1811 // Send CarStop event for all application
1812 this->send_event(kListEventName[Event_CarStop]);
1815 void WindowManager::emitCarRun()
1817 // Send CarRun event for all application
1818 this->send_event(kListEventName[Event_CarRun]);
1821 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
1822 Task task, unsigned* req_num)
1824 if (!g_app_list.contains(appid))
1826 return WMError::NOT_REGISTERED;
1829 auto client = g_app_list.lookUpClient(appid);
1834 unsigned current = g_app_list.currentRequestNumber();
1835 unsigned requested_num = g_app_list.getRequestNumber(appid);
1836 if (requested_num != 0)
1838 HMI_SEQ_INFO(requested_num,
1839 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1840 return REQ_REJECTED;
1843 WMRequest req = WMRequest(appid, role, area, task);
1844 unsigned new_req = g_app_list.addRequest(req);
1846 g_app_list.reqDump();
1848 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1850 return WMError::SUCCESS;
1853 WMError WindowManager::setRequest(Task task, unsigned* req_num)
1858 unsigned current = g_app_list.currentRequestNumber();
1860 WMRequest req = WMRequest(task);
1861 unsigned new_req = g_app_list.addRequest(req);
1863 g_app_list.reqDump();
1865 HMI_SEQ_DEBUG(current, "start sequence for task:%d", task);
1867 return WMError::SUCCESS;
1870 WMError WindowManager::setRequestForSlave(const string& appid, const string &role, const string &area,
1871 Task task, unsigned* req_num)
1876 unsigned current = g_app_list.currentRequestNumber();
1877 unsigned requested_num = g_app_list.getRequestNumber(appid);
1878 if (requested_num != 0)
1880 HMI_SEQ_INFO(requested_num,
1881 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1882 return REQ_REJECTED;
1885 WMRequest req = WMRequest(appid, role, area, task);
1886 unsigned new_req = g_app_list.addRequest(req);
1888 g_app_list.reqDump();
1890 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1892 return WMError::SUCCESS;
1895 WMError WindowManager::checkPolicy(unsigned req_num)
1900 // get current trigger
1902 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1903 auto trigger = g_app_list.getRequest(req_num, &found);
1906 ret = WMError::NO_ENTRY;
1909 string req_area = trigger.area;
1911 if (trigger.task == Task::TASK_ALLOCATE)
1913 const char *msg = this->check_surface_exist(trigger.role.c_str());
1917 HMI_SEQ_ERROR(req_num, msg);
1922 // Input event data to PolicyManager
1923 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1925 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1929 // Execute state transition of PolicyManager
1930 if (0 > this->pmw.executeStateTransition())
1932 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1936 ret = WMError::SUCCESS;
1938 g_app_list.reqDump();
1943 WMError WindowManager::checkPolicyForSlave(unsigned req_num)
1948 // get current trigger
1950 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1951 auto trigger = g_app_list.getRequest(req_num, &found);
1954 ret = WMError::NO_ENTRY;
1957 string req_area = trigger.area;
1959 // Input event data to PolicyManager
1960 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1962 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1966 // Execute state transition of PolicyManager
1967 if (0 > this->pmw.executeStateTransition())
1969 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1973 ret = WMError::SUCCESS;
1975 g_app_list.reqDump();
1980 WMError WindowManager::startTransition(unsigned req_num)
1982 bool sync_draw_happen = false;
1984 WMError ret = WMError::SUCCESS;
1985 auto actions = g_app_list.getActions(req_num, &found);
1988 ret = WMError::NO_ENTRY;
1989 HMI_SEQ_ERROR(req_num,
1990 "Window Manager bug :%s : Action is not set", errorDescription(ret));
1994 g_app_list.reqDump();
1995 for (const auto &action : actions)
1997 // TODO: application requests by old role,
1998 // so convert role new to old for emitting event
1999 string old_role = this->rolenew2old[action.role];
2001 if (action.visible == TaskVisible::VISIBLE)
2003 sync_draw_happen = true;
2005 this->emit_syncdraw(old_role, action.area);
2006 /* TODO: emit event for app not subscriber
2007 if(g_app_list.contains(y.appid))
2008 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
2010 else if(action.visible == TaskVisible::REQ_REMOTE_VISIBLE)
2012 // If this action is for slave, send to slave
2013 this->wmcon.sendRequest("syncDraw", action.client->appID().c_str(),
2014 old_role.c_str(), action.area.c_str());
2016 else if (action.car_state != TaskCarState::NO_TASK)
2018 this->transitionCarState(action.car_state);
2022 if (sync_draw_happen)
2028 // deactivate only, no syncDraw
2029 // Make it deactivate here
2030 for (const auto &x : actions)
2032 this->lc->visibilityChange(x);
2033 string old_role = this->rolenew2old[x.role];
2035 if (x.visible == TaskVisible::INVISIBLE)
2037 emit_deactivated(old_role);
2039 else if (x.visible == TaskVisible::REQ_REMOTE_INVISIBLE)
2041 // If this action is for slave, send to slave
2042 int i_ret = this->wmcon.sendRequest("deactivated", x.client->appID().c_str(),
2043 old_role.c_str(), "");
2046 ret = WMError::FAIL;
2050 /* if (g_app_list.contains(x.appid))
2052 auto client = g_app_list.lookUpClient(x.appid);
2053 //this->deactivate(client->surfaceID(x.role));
2056 this->lc->renderLayers();
2057 ret = WMError::NO_LAYOUT_CHANGE;
2062 void WindowManager::transitionCarState(TaskCarState task)
2064 if (TaskCarState::PARKING_BRAKE_OFF == task)
2066 this->crr_car_info.parking_brake_stt = false;
2067 this->emitParkingBrakeOff();
2069 else if (TaskCarState::PARKING_BRAKE_ON == task)
2071 this->crr_car_info.parking_brake_stt = true;
2072 this->emitParkingBrakeOn();
2074 else if (TaskCarState::ACCEL_PEDAL_OFF == task)
2076 this->crr_car_info.accel_pedal_stt = false;
2078 else if (TaskCarState::ACCEL_PEDAL_ON == task)
2080 this->crr_car_info.accel_pedal_stt = true;
2082 else if (TaskCarState::HEDLAMP_OFF == task)
2084 this->crr_car_info.headlamp_stt = false;
2085 this->emitHeadlampOff();
2087 else if (TaskCarState::HEDLAMP_ON == task)
2089 this->crr_car_info.headlamp_stt = true;
2090 this->emitHeadlampOn();
2092 else if (TaskCarState::LIGHTSTATUS_BRAKE_OFF == task)
2094 this->crr_car_info.lightstatus_brake_stt = false;
2095 this->emitLightstatusBrakeOff();
2097 else if (TaskCarState::LIGHTSTATUS_BRAKE_ON == task)
2099 this->crr_car_info.lightstatus_brake_stt = true;
2100 this->emitLightstatusBrakeOn();
2102 else if (TaskCarState::CAR_STOP == task)
2104 this->crr_car_info.running_stt = false;
2105 this->emitCarStop();
2107 else if (TaskCarState::CAR_RUN == task)
2109 this->crr_car_info.running_stt = true;
2114 WMError WindowManager::doEndDraw(unsigned req_num)
2118 bool trigger_homescreen = false;
2119 auto actions = g_app_list.getActions(req_num, &found);
2120 WMError ret = WMError::SUCCESS;
2123 ret = WMError::NO_ENTRY;
2126 auto trigger = g_app_list.getRequest(req_num, &found);
2127 HMI_SEQ_INFO(req_num, "trigger.role = %s", trigger.role.c_str());
2129 if(trigger.role == "homescreen")
2131 trigger_homescreen = true;
2134 HMI_SEQ_INFO(req_num, "do endDraw");
2136 // layout change and make it visible
2137 for (const auto &act : actions)
2139 if(act.visible != TaskVisible::NO_CHANGE)
2142 ret = this->lc->layoutChange(act);
2143 if(ret != WMError::SUCCESS)
2145 HMI_SEQ_WARNING(req_num,
2146 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
2150 if(trigger_homescreen && (act.visible == TaskVisible::INVISIBLE))
2152 HMI_SEQ_NOTICE(req_num, "don't change visible if homescreen role is trigger");
2156 ret = this->lc->visibilityChange(act);
2159 // Emit active/deactive event
2160 string old_role = this->rolenew2old[act.role];
2163 case TaskVisible::VISIBLE :
2164 emit_visible(old_role);
2165 emit_activated(old_role);
2167 case TaskVisible::REQ_REMOTE_VISIBLE :
2169 // If this action is for slave, send to slave
2170 int i_ret = this->wmcon.sendRequest("activated", "", old_role.c_str(), "");
2173 ret = WMError::FAIL;
2177 case TaskVisible::INVISIBLE :
2178 if(!trigger_homescreen)
2180 emit_invisible(old_role);
2181 emit_deactivated(old_role);
2185 // TaskVisible::REMOTE_VISIBLE, TaskVisible::REMOTE_INVISIBLE is this case
2186 // If this action is for slave, send to slave
2190 if (ret != WMError::SUCCESS)
2192 HMI_SEQ_WARNING(req_num,
2193 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
2196 HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
2199 this->lc->renderLayers();
2201 HMI_SEQ_INFO(req_num, "emit flushDraw");
2203 for(const auto &act_flush : actions)
2205 // TODO: application requests by old role,
2206 // so convert role new to old for emitting event
2207 string old_role = this->rolenew2old[act_flush.role];
2209 if(act_flush.visible == TaskVisible::VISIBLE)
2211 this->emit_flushdraw(old_role);
2213 else if(act_flush.visible == TaskVisible::REQ_REMOTE_VISIBLE)
2215 // If this action is for slave, send to slave
2216 this->wmcon.sendRequest("flushDraw", "", old_role.c_str(), "");
2223 void WindowManager::emitScreenUpdated(unsigned req_num)
2226 HMI_SEQ_DEBUG(req_num, "emit screen updated");
2228 auto actions = g_app_list.getActions(req_num, &found);
2232 HMI_SEQ_ERROR(req_num,
2233 "Window Manager bug :%s : Action is not set",
2234 errorDescription(WMError::NO_ENTRY));
2239 // create json object
2240 json_object *j = json_object_new_object();
2241 json_object *jarray = json_object_new_array();
2243 for(const auto& action: actions)
2245 if((action.visible == TaskVisible::VISIBLE) ||
2246 (action.visible == TaskVisible::REMOTE_VISIBLE))
2248 json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
2251 json_object_object_add(j, kKeyIds, jarray);
2252 HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
2254 int ret = afb_event_push(
2255 this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
2258 HMI_DEBUG("afb_event_push failed: %m");
2262 void WindowManager::setTimer()
2265 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
2266 HMI_ERROR("Could't set time (clock_gettime() returns with error");
2270 HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
2271 if (g_timer_ev_src == nullptr)
2273 // firsttime set into sd_event
2274 int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
2275 CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
2278 HMI_ERROR("Could't set timer");
2283 // update timer limitation after second time
2284 sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
2285 sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
2289 void WindowManager::stopTimer()
2291 unsigned req_num = g_app_list.currentRequestNumber();
2292 HMI_SEQ_DEBUG(req_num, "Timer stop");
2293 int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
2296 HMI_SEQ_ERROR(req_num, "Timer stop failed");
2300 void WindowManager::processNextRequest()
2303 g_app_list.reqDump();
2304 unsigned req_num = g_app_list.currentRequestNumber();
2305 if (g_app_list.haveRequest())
2307 HMI_SEQ_DEBUG(req_num, "Process next request");
2308 WMError rc = checkPolicy(req_num);
2309 if (rc != WMError::SUCCESS)
2311 HMI_SEQ_ERROR(req_num, errorDescription(rc));
2316 HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
2320 const char* WindowManager::convertRoleOldToNew(char const *old_role)
2322 const char *new_role = nullptr;
2324 for (auto const &on : this->roleold2new)
2326 std::regex regex = std::regex(on.first);
2327 if (std::regex_match(old_role, regex))
2329 // role is old. So convert to new.
2330 new_role = on.second.c_str();
2335 if (nullptr == new_role)
2337 // role is new or fallback.
2338 new_role = old_role;
2341 HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
2346 int WindowManager::loadOldRolesConfigFile()
2348 // Get afm application installed dir
2349 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
2350 HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
2353 if (!afm_app_install_dir)
2355 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
2359 file_name = string(afm_app_install_dir) + string(kPathOldRolesConfigFile);
2362 // Load old_rolea config file
2363 json_object* json_obj;
2364 int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
2367 HMI_ERROR("Could not open %s, so use default old_roles information", kPathOldRolesConfigFile);
2368 json_obj = json_tokener_parse(kDefaultOldRolesConfig);
2370 HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
2373 json_object* json_cfg;
2374 if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
2376 HMI_ERROR("Parse Error!!");
2380 int len = json_object_array_length(json_cfg);
2381 HMI_DEBUG("json_cfg len:%d", len);
2382 HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
2384 for (int i=0; i<len; i++)
2386 json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
2388 const char* old_role = jh::getStringFromJson(json_tmp, "name");
2389 if (nullptr == old_role)
2391 HMI_ERROR("Parse Error!!");
2395 const char* new_role = jh::getStringFromJson(json_tmp, "new");
2396 if (nullptr == new_role)
2398 HMI_ERROR("Parse Error!!");
2402 this->roleold2new[old_role] = string(new_role);
2406 for(auto itr = this->roleold2new.begin();
2407 itr != this->roleold2new.end(); ++itr)
2409 HMI_DEBUG(">>> role old:%s new:%s",
2410 itr->first.c_str(), itr->second.c_str());
2413 // Release json_object
2414 json_object_put(json_obj);
2419 int WindowManager::saveLastModeData(unsigned req_num)
2422 auto actions = g_app_list.getActions(req_num, &found);
2424 HMI_DEBUG("Save LastMode data");
2428 HMI_DEBUG("Not Found Entry");
2432 json_object *j_obj = json_object_new_object();
2433 json_object *j_array = json_object_new_array();
2435 for (const auto &act : actions)
2437 if (act.visible == TaskVisible::VISIBLE)
2439 unsigned layer = act.client->layerID();
2440 unsigned surface = act.client->surfaceID();
2442 t_ilm_bool visibility;
2444 ilm_layerGetVisibility(layer, &visibility);
2446 if (visibility == ILM_FALSE)
2451 ilmSurfaceProperties sp;
2452 ilm_getPropertiesOfSurface(surface, &sp);
2454 json_object *j_array_obj = json_object_new_object();
2455 json_object_object_add(j_array_obj, "role", json_object_new_string(act.role.c_str()));
2456 json_object_object_add(j_array_obj, "visible",
2457 json_object_new_string((visibility ? "true" : "false")));
2458 json_object_object_add(j_array_obj, "area", json_object_new_string(act.area.c_str()));
2459 json_object_object_add(j_array_obj, "destX", json_object_new_int(sp.destX));
2460 json_object_object_add(j_array_obj, "destY", json_object_new_int(sp.destY));
2461 json_object_object_add(j_array_obj, "destWidth", json_object_new_int(sp.destWidth));
2462 json_object_object_add(j_array_obj, "destHeight", json_object_new_int(sp.destHeight));
2463 json_object_object_add(j_array_obj, "sourceX", json_object_new_int(sp.sourceX));
2464 json_object_object_add(j_array_obj, "sourceY", json_object_new_int(sp.sourceY));
2465 json_object_object_add(j_array_obj, "sourceWidth", json_object_new_int(sp.sourceWidth));
2466 json_object_object_add(j_array_obj, "sourceHeight", json_object_new_int(sp.sourceHeight));
2468 json_object_array_add(j_array, j_array_obj);
2472 json_object_object_add(j_obj, "LastModeData", j_array);
2474 const char *buf = json_object_to_json_string(j_obj);
2476 std::string root = getenv("AFM_APP_INSTALL_DIR");
2477 std::string lastmode_path = root + WM_LASTMODE_PATH;
2479 FILE *fp = fopen(lastmode_path.c_str(), "wb");
2482 HMI_ERROR("Could not open file");
2486 int len = strlen(buf);
2487 fwrite(buf, len, 1, fp);
2491 json_object_put(j_obj);
2496 Task WindowManager::convertCanSignalToCarStateTask(const char *signal_name)
2498 wm::LowCanClient *lcc = &(this->lcc);
2499 Task task = Task::TASK_INVALID;
2501 // If car info is updated, set car state change event
2502 if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoParkingBrake]))
2504 HMI_DEBUG("Parking Brake state is changed");
2506 if (lcc->getCurrentParkingBrakeState())
2508 task = wm::Task::TASK_PARKING_BRAKE_ON;
2512 task = wm::Task::TASK_PARKING_BRAKE_OFF;
2515 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoAccelPedalPos]))
2517 // Update accel pedal position
2518 this->crr_car_info.accel_pedal_pos = lcc->getCurrentAccelPedalPosition();
2520 if (lcc->isChangedAccelPedalState())
2522 HMI_DEBUG("Accelerator Pedal state is changed");
2524 if (lcc->getCurrentAccelPedalState())
2526 task = wm::Task::TASK_ACCEL_PEDAL_ON;
2530 task = wm::Task::TASK_ACCEL_PEDAL_OFF;
2534 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoHeadlame]))
2536 HMI_DEBUG("Headlamp state is changed");
2538 if (lcc->getCurrentHeadlampState())
2540 task = wm::Task::TASK_HEDLAMP_ON;
2544 task = wm::Task::TASK_HEDLAMP_OFF;
2547 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoLightstatusBrake]))
2549 HMI_DEBUG("Lightstatus Brake state is changed");
2551 if (lcc->getCurrentLightstatusBrakeState())
2553 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_ON;
2557 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_OFF;
2563 void WindowManager::inputCarStateTask(Task task)
2565 unsigned req_num = 0;
2566 WMError ret = WMError::UNKNOWN;
2568 ret = this->setRequest(task, &req_num);
2570 if(ret != WMError::SUCCESS)
2572 HMI_ERROR(errorDescription(ret));
2576 if (req_num != g_app_list.currentRequestNumber())
2578 // Add request, then invoked after the previous task is finished
2579 HMI_SEQ_DEBUG(req_num, "request is accepted");
2586 ret = this->checkPolicy(req_num);
2588 if (ret != WMError::SUCCESS)
2590 //this->emit_error()
2591 HMI_SEQ_ERROR(req_num, errorDescription(ret));
2592 g_app_list.removeRequest(req_num);
2593 this->processNextRequest();
2597 const char *WindowManager::check_surface_exist(const char *drawing_name)
2599 auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
2602 return "Surface does not exist";
2605 /* if (!this->controller->surface_exists(*surface_id))
2607 return "Surface does not exist in controller!";
2610 /* auto layer_id = this->layers.get_layer_id(*surface_id);
2614 return "Surface is not on any layer!";
2617 HMI_DEBUG("surface %d is detected", *surface_id);
2621 const char* WindowManager::kDefaultOldRolesConfig = "{ \
2624 \"name\": \"HomeScreen\", \
2625 \"new\": \"homescreen\" \
2628 \"name\": \"Music\", \
2629 \"new\": \"music\" \
2632 \"name\": \"MediaPlayer\", \
2633 \"new\": \"music\" \
2636 \"name\": \"Video\", \
2637 \"new\": \"video\" \
2640 \"name\": \"VideoPlayer\", \
2641 \"new\": \"video\" \
2644 \"name\": \"WebBrowser\", \
2645 \"new\": \"browser\" \
2648 \"name\": \"Radio\", \
2649 \"new\": \"radio\" \
2652 \"name\": \"Phone\", \
2653 \"new\": \"phone\" \
2656 \"name\": \"Navigation\", \
2660 \"name\": \"HVAC\", \
2664 \"name\": \"Settings\", \
2665 \"new\": \"settings\" \
2668 \"name\": \"Dashboard\", \
2669 \"new\": \"dashboard\" \
2672 \"name\": \"POI\", \
2676 \"name\": \"Mixer\", \
2677 \"new\": \"mixer\" \
2680 \"name\": \"Restriction\", \
2681 \"new\": \"restriction\" \
2684 \"name\": \"^OnScreen.*\", \
2685 \"new\": \"on_screen\" \