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();
532 //TODO Deactivate remote viewing app for remote view change to local view.
533 if(this->lc->hasRemoteLayer(layer) != "" && this->wmcon.getAppIdToEcuName(appid) != "")
535 HMI_DEBUG("Deactivate remote App %s", drawing_name);
536 std::string tmp_area = this->wmcon.getAppIdToEcuName(appid) + ".split.sub";
537 HMI_DEBUG("Deactivate area name: %s", tmp_area.c_str());
538 this->wmcon.sendRequest("deactivateWindow", appid, drawing_name, tmp_area.c_str());
540 unsigned req_num = g_app_list.currentRequestNumber();
541 const char *c_role = this->convertRoleOldToNew(drawing_name);
542 bool end_draw_finished = true;
549 TaskVisible::REMOTE_INVISIBLE,
551 TaskCarState::NO_TASK
554 this->lc->visibilityChange(act);
555 this->lc->renderLayers();
557 this->emit_invisible(role);
558 this->emit_deactivated(role);
561 Task task = Task::TASK_ALLOCATE;
562 unsigned req_num = 0;
563 WMError ret = WMError::UNKNOWN;
565 ret = this->setRequest(id, role, area, task, &req_num);
567 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
568 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
570 if(ret != WMError::SUCCESS)
572 HMI_ERROR(errorDescription(ret));
573 reply("Failed to set request");
577 this->wmcon.setAppIdToEcuName(id, this->wmcon.getEcuName());
580 if (req_num != g_app_list.currentRequestNumber())
582 // Add request, then invoked after the previous task is finished
583 HMI_SEQ_DEBUG(req_num, "request is accepted");
590 ret = this->checkPolicy(req_num);
592 if (ret != WMError::SUCCESS)
595 HMI_SEQ_ERROR(req_num, errorDescription(ret));
596 g_app_list.removeRequest(req_num);
597 this->processNextRequest();
601 void WindowManager::api_activate_surface_for_slave(
602 char const *appid, char const *drawing_name,
603 char const *drawing_area, const reply_func &reply)
605 // TODO: application requests by old role,
606 // so convert role old to new
607 const char *c_role = this->convertRoleOldToNew(drawing_name);
610 string role = c_role;
611 string area = drawing_area;
613 if(!g_app_list.contains(id))
615 // Request surface of app in slave to register app information
616 this->api_request_surface(appid, drawing_name);
618 // Set role of app in slave to register app information
619 this->api_set_role(appid, drawing_name);
621 auto client = g_app_list.lookUpClient(id);
623 // unsigned srfc = client->surfaceID(role);
624 // unsigned layer = client->layerID();
626 // g_app_list.removeFloatingSurface(client->surfaceID());
627 // g_app_list.removeFloatingSurface(client);
629 Task task = Task::TASK_ALLOCATE;
630 unsigned req_num = 0;
631 WMError ret = WMError::UNKNOWN;
633 ret = this->setRequestForSlave(id, role, area, task, &req_num);
635 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
636 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
638 if(ret != WMError::SUCCESS)
640 HMI_ERROR(errorDescription(ret));
641 reply("Failed to set request");
645 this->wmcon.setAppIdToReceivedEcuName(id);
648 if (req_num != g_app_list.currentRequestNumber())
650 // Add request, then invoked after the previous task is finished
651 HMI_SEQ_DEBUG(req_num, "request is accepted");
658 ret = this->checkPolicyForSlave(req_num);
660 if (ret != WMError::SUCCESS)
663 HMI_SEQ_ERROR(req_num, errorDescription(ret));
664 g_app_list.removeRequest(req_num);
665 this->processNextRequest();
669 void WindowManager::api_activate_surface_to_master(
670 char const *appid, char const *drawing_name,
671 char const *drawing_area, const reply_func &reply)
673 // TODO: application requests by old role,
674 // so convert role old to new
675 const char *c_role = this->convertRoleOldToNew(drawing_name);
678 string role = c_role;
679 string area = drawing_area;
681 if(!g_app_list.contains(id))
683 reply("app doesn't request 'requestSurface' or 'setRole' yet");
686 auto client = g_app_list.lookUpClient(id);
688 // unsigned srfc = client->surfaceID(role);
689 // unsigned layer = client->layerID();
691 // g_app_list.removeFloatingSurface(client->surfaceID());
692 // g_app_list.removeFloatingSurface(client);
694 unsigned layer = client->layerID();
696 //TODO Deactivate remote viewing app for remote view change to local view.
697 if(this->lc->hasRemoteLayer(layer) != "" && this->wmcon.getAppIdToEcuName(appid) != "")
699 HMI_DEBUG("Deactivate remote App %s", drawing_name);
700 std::string tmp_area = this->wmcon.getAppIdToEcuName(appid) + ".split.sub";
701 HMI_DEBUG("Deactivate area name: %s", tmp_area.c_str());
702 this->wmcon.sendRequest("deactivateWindow", appid, drawing_name, tmp_area.c_str());
704 unsigned req_num = g_app_list.currentRequestNumber();
705 const char *c_role = this->convertRoleOldToNew(drawing_name);
706 bool end_draw_finished = true;
713 TaskVisible::REMOTE_INVISIBLE,
715 TaskCarState::NO_TASK
718 this->lc->renderLayers();
719 this->lc->visibilityChange(act);
721 this->emit_invisible(role);
722 this->emit_deactivated(role);
725 Task task = Task::TASK_ALLOCATE;
726 unsigned req_num = 0;
727 WMError ret = WMError::UNKNOWN;
729 ret = this->setRequest(id, role, area, task, &req_num);
731 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
732 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
734 if(ret != WMError::SUCCESS)
736 HMI_ERROR(errorDescription(ret));
737 reply("Failed to set request");
741 std::string ecu_name;
742 ecu_name = this->wmcon.getAreaToEcuName(area.c_str());
744 this->wmcon.setAppIdToEcuName(id, ecu_name);
747 if (req_num != g_app_list.currentRequestNumber())
749 // Add request, then invoked after the previous task is finished
750 HMI_SEQ_DEBUG(req_num, "request is accepted");
757 int i_ret = this->wmcon.sendRequest("activateWindow", appid,
758 drawing_name, drawing_area);
762 HMI_SEQ_ERROR(req_num, errorDescription(ret));
763 g_app_list.removeRequest(req_num);
764 this->processNextRequest();
770 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
771 const reply_func &reply)
773 // TODO: application requests by old role,
774 // so convert role old to new
775 const char *c_role = this->convertRoleOldToNew(drawing_name);
781 string role = c_role;
782 string area = ""; //drawing_area;
783 Task task = Task::TASK_RELEASE;
784 unsigned req_num = 0;
785 WMError ret = WMError::UNKNOWN;
787 ret = this->setRequest(id, role, area, task, &req_num);
789 if (ret != WMError::SUCCESS)
791 HMI_ERROR(errorDescription(ret));
792 reply("Failed to set request");
797 if (req_num != g_app_list.currentRequestNumber())
799 // Add request, then invoked after the previous task is finished
800 HMI_SEQ_DEBUG(req_num, "request is accepted");
807 ret = this->checkPolicy(req_num);
809 if (ret != WMError::SUCCESS)
812 HMI_SEQ_ERROR(req_num, errorDescription(ret));
813 g_app_list.removeRequest(req_num);
814 this->processNextRequest();
818 void WindowManager::api_deactivate_surface_for_slave(char const *appid, char const *drawing_name,
819 const reply_func &reply)
821 // TODO: application requests by old role,
822 // so convert role old to new
823 const char *c_role = this->convertRoleOldToNew(drawing_name);
829 string role = c_role;
830 string area = "";//drawing_area;
831 Task task = Task::TASK_RELEASE;
832 unsigned req_num = 0;
833 WMError ret = WMError::UNKNOWN;
835 ret = this->setRequest(id, role, area, task, &req_num);
837 if (ret != WMError::SUCCESS)
839 HMI_ERROR(errorDescription(ret));
840 reply("Failed to set request");
845 if (req_num != g_app_list.currentRequestNumber())
847 // Add request, then invoked after the previous task is finished
848 HMI_SEQ_DEBUG(req_num, "request is accepted");
855 ret = this->checkPolicyForSlave(req_num);
857 if (ret != WMError::SUCCESS)
860 HMI_SEQ_ERROR(req_num, errorDescription(ret));
861 g_app_list.removeRequest(req_num);
862 this->processNextRequest();
866 void WindowManager::api_deactivate_surface_to_master(char const *appid, char const *drawing_name,
867 const reply_func &reply)
869 // TODO: application requests by old role,
870 // so convert role old to new
871 const char *c_role = this->convertRoleOldToNew(drawing_name);
877 string role = c_role;
878 string area = "";//drawing_area;
879 Task task = Task::TASK_RELEASE;
880 unsigned req_num = 0;
881 WMError ret = WMError::UNKNOWN;
883 ret = this->setRequest(id, role, area, task, &req_num);
885 if (ret != WMError::SUCCESS)
887 HMI_ERROR(errorDescription(ret));
888 reply("Failed to set request");
893 if (req_num != g_app_list.currentRequestNumber())
895 // Add request, then invoked after the previous task is finished
896 HMI_SEQ_DEBUG(req_num, "request is accepted");
903 int i_ret = this->wmcon.sendRequest("deactivateWindow", appid,
908 HMI_SEQ_ERROR(req_num, errorDescription(ret));
909 g_app_list.removeRequest(req_num);
910 this->processNextRequest();
916 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
918 // TODO: application requests by old role,
919 // so convert role old to new
920 const char *c_role = this->convertRoleOldToNew(drawing_name);
923 string role = c_role;
924 unsigned current_req = g_app_list.currentRequestNumber();
925 bool result = g_app_list.setEndDrawFinished(current_req, id, role);
929 HMI_ERROR("%s is not in transition state", id.c_str());
933 if (g_app_list.endDrawFullfilled(current_req))
935 // do task for endDraw
937 WMError ret = this->doEndDraw(current_req);
939 if(ret != WMError::SUCCESS)
941 //this->emit_error();
943 // Undo state of PolicyManager
944 this->pmw.undoState();
945 this->lc->undoUpdate();
947 this->emitScreenUpdated(current_req);
948 HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
950 this->saveLastModeData(current_req);
952 g_app_list.removeRequest(current_req);
954 this->processNextRequest();
958 HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
963 int WindowManager::api_subscribe(afb_req req, int event_id)
965 struct afb_event event = this->map_afb_event[kListEventName[event_id]];
966 return afb_req_subscribe(req, event);
969 void WindowManager::api_handshake()
971 this->send_event(kListEventName[Event_Handshake]);
974 void WindowManager::api_enddraw_for_remote(char const *appid, char const *drawing_name)
976 int ret = this->wmcon.sendRequest("endDraw", appid, drawing_name, "");
981 this->pmw.undoState();
982 this->lc->undoUpdate();
984 unsigned current_req = g_app_list.currentRequestNumber();
985 g_app_list.removeRequest(current_req);
986 this->processNextRequest();
991 this->api_enddraw(appid, drawing_name);
994 bool WindowManager::api_client_set_render_order(char const* appid, const vector<string>& render_order)
998 auto client = g_app_list.lookUpClient(id);
1001 client->setRenderOrder(render_order);
1006 string WindowManager::api_client_attach_service_surface
1007 (const char* appid, const char* dest, const char* service_surface)
1009 string uuid, s_dest = dest;
1010 auto client = g_app_list.lookUpClient(s_dest);
1013 HMI_ERROR("Failed to look up destination [%s]", dest);
1016 uuid = client->attachTmpServiceSurface(appid, service_surface);
1017 this->tmp_services.emplace_back(TmpService{appid, dest, service_surface, uuid});
1021 json_object* WindowManager::api_get_area_list()
1023 json_object* ret = json_object_new_object();
1024 json_object* jarray = json_object_new_array();
1025 unordered_map<string, struct rect> area2size = this->lc->getAreaList();
1026 for(const auto& area : area2size)
1028 json_object* j = json_object_new_object();
1029 json_object_object_add(j, "name", json_object_new_string(area.first.c_str()));
1030 json_object* jrect = json_object_new_object();
1031 json_object_object_add(jrect, "x", json_object_new_int(area.second.x));
1032 json_object_object_add(jrect, "y", json_object_new_int(area.second.y));
1033 json_object_object_add(jrect, "w", json_object_new_int(area.second.w));
1034 json_object_object_add(jrect, "h", json_object_new_int(area.second.h));
1035 json_object_object_add(j, "rect", jrect);
1036 json_object_array_add(jarray, j);
1038 json_object_object_add(ret, "areas", jarray);
1039 HMI_DEBUG("area_list: %s", json_object_get_string(ret));
1043 void WindowManager::api_change_area_size(ChangeAreaReq &areas)
1047 auto client = g_app_list.lookUpClient(areas.appname);
1049 if(client == nullptr)
1051 HMI_ERROR("Call register your role with setRole or requestSurface");
1054 if(std::find(white_list_area_size_change.begin(),
1055 white_list_area_size_change.end(), client->role()) == white_list_area_size_change.end())
1057 HMI_ERROR("Application %s which has the role %s is not allowed to change area size", client->appID().c_str(), client->role().c_str());
1062 ret = this->lc->updateAreaList(areas);
1063 if(ret != WMError::SUCCESS)
1065 HMI_ERROR("%d : %s", ret, errorDescription(ret));
1068 ret = this->lc->getUpdateAreaList(&areas);
1070 if(ret != WMError::SUCCESS)
1072 HMI_ERROR("%d : %s", ret, errorDescription(ret));
1079 ret = this->setRequest(client->appID(), client->role(), "-", Task::TASK_CHANGE_AREA, &req_num); // area is null
1080 if(ret != WMError::SUCCESS)
1082 HMI_SEQ_ERROR(req_num, "%d : %s", ret, errorDescription(ret));
1085 for(const auto &update: areas.update_app2area)
1088 auto client = g_app_list.lookUpClient(update.first);
1089 if(client == nullptr)
1091 HMI_SEQ_ERROR(req_num, "%s : %s", update.first.c_str(), errorDescription(ret));
1092 g_app_list.removeRequest(req_num);
1093 this->processNextRequest();
1096 ret = g_app_list.setAction(req_num, client, client->role(), update.second, TaskVisible::VISIBLE);
1097 if(ret != WMError::SUCCESS)
1099 HMI_SEQ_ERROR(req_num, "Failed to set request");
1103 HMI_SEQ_INFO(req_num, "Area change request");
1104 g_app_list.reqDump();
1106 // Request change size to applications
1107 for(const auto &action : g_app_list.getActions(req_num, &found))
1109 string old_role = this->rolenew2old[action.role];
1110 this->emit_syncdraw(old_role, action.area);
1114 result<json_object *> WindowManager::api_get_display_info()
1116 Screen screen = this->lc->getScreenInfo();
1118 json_object *object = json_object_new_object();
1119 json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
1120 json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
1122 json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
1123 json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
1124 json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
1126 return Ok<json_object *>(object);
1129 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
1131 HMI_DEBUG("called");
1133 // TODO: application requests by old role,
1134 // so convert role old to new
1135 const char *role = this->convertRoleOldToNew(drawing_name);
1137 // Check drawing name, surface/layer id
1138 auto const &surface_id = this->id_alloc.lookup(role);
1141 return Err<json_object *>("Surface does not exist");
1144 // Set area rectangle
1145 rect area_info = this->area_info[*surface_id];
1146 json_object *object = json_object_new_object();
1147 json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
1148 json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
1149 json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
1150 json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
1152 return Ok<json_object *>(object);
1155 result<json_object *> WindowManager::api_get_car_info(char const *label)
1157 json_object *j_in = nullptr;
1158 json_object *j_out = nullptr;
1160 if (0 == strcmp("parking_brake_status", label))
1162 // Get parking brake status
1163 json_bool val = (this->crr_car_info.parking_brake_stt) ? TRUE : FALSE;
1164 j_in = json_object_new_boolean(val);
1166 else if (0 == strcmp("accelerator.pedal.position", label))
1168 // Get accelerator pedal position
1169 double val = this->crr_car_info.accel_pedal_pos;
1170 j_in = json_object_new_double(val);
1172 else if (0 == strcmp("car_state", label))
1174 // Get running state
1175 const char* val = (this->crr_car_info.running_stt) ? "run" : "stop";
1176 j_in = json_object_new_string(val);
1178 else if (0 == strcmp("lightstatus.brake", label)) {
1179 // Get lightstatus brake status
1180 json_bool val = (this->crr_car_info.lightstatus_brake_stt) ? TRUE : FALSE;
1181 j_in = json_object_new_boolean(val);
1185 return Err<json_object *>("Car info does not exist");
1188 // Create output object
1189 j_out = json_object_new_object();
1190 json_object_object_add(j_out, "value", j_in);
1192 return Ok<json_object *>(j_out);
1195 void WindowManager::send_event(const string& evname)
1197 HMI_DEBUG("%s: %s", __func__, evname.c_str());
1199 int ret = afb_event_push(this->map_afb_event[evname], nullptr);
1202 HMI_DEBUG("afb_event_push: %m");
1206 void WindowManager::send_event(const string& evname, const string& role)
1208 HMI_DEBUG("%s: %s(%s)", __func__, evname.c_str(), role.c_str());
1210 json_object *j = json_object_new_object();
1211 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
1213 int ret = afb_event_push(this->map_afb_event[evname], j);
1216 HMI_DEBUG("afb_event_push failed: %m");
1220 void WindowManager::send_event(const string& evname, const string& role, const string& area,
1221 int x, int y, int w, int h)
1223 HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
1224 __func__, evname.c_str(), role.c_str(), area.c_str(), x, y, w, h);
1226 json_object *j_rect = json_object_new_object();
1227 json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
1228 json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
1229 json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
1230 json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
1232 json_object *j = json_object_new_object();
1233 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
1234 json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
1235 json_object_object_add(j, kKeyDrawingRect, j_rect);
1237 int ret = afb_event_push(this->map_afb_event[evname], j);
1240 HMI_DEBUG("afb_event_push failed: %m");
1244 string WindowManager::searchApp(unsigned pid, unsigned ppid, unsigned surface, json_object* resp)
1246 // retrieve appid from pid from application manager
1248 // check appid then add it to the client
1249 HMI_INFO("Runners:%s", json_object_get_string(resp));
1250 int size = json_object_array_length(resp);
1251 HMI_INFO("pid %d, ppid %d, surface %d",pid, ppid, surface);
1252 for(int i = 0; i < size; i++)
1254 json_object *j = json_object_array_get_idx(resp, i);
1255 int runid = jh::getIntFromJson(j, "runid");
1256 const char* id = jh::getStringFromJson(j, "id");
1257 HMI_DEBUG("Appid %s, runid %d", id, runid);
1258 if(id && (runid == ppid))
1261 s_id.erase(s_id.find('@'));
1263 HMI_INFO("App found %s", appid.c_str());
1269 HMI_WARNING("Failed to retrieve id");
1274 void WindowManager::storeSurface(const string& appid, unsigned ppid, unsigned surface)
1276 auto elem = std::find_if(this->tmp_services.begin(), this->tmp_services.end(),
1277 [&appid](TmpService& ts){
1278 return (ts.dest == appid );
1281 this->lc->setXDGSurfaceOriginSize(surface);
1282 if(elem != this->tmp_services.end())
1285 auto client = g_app_list.lookUpClient(elem->dest);
1286 if(client == nullptr)
1290 HMI_INFO("Attach surface %d (service %s) to app %s", surface, elem->service.c_str(), elem->dest.c_str());
1291 client->attachServiceSurface(elem->service, surface);
1296 auto client = g_app_list.lookUpClient(appid);
1297 if(client != nullptr)
1299 client->addSurface(surface);
1300 this->id_alloc.register_name_id(client->role(), surface);
1304 // Store tmp surface and appid for application
1305 // who requests setRole after creating shell surface
1306 this->tmp_surface2app.emplace(surface, TmpClient{appid, ppid});
1314 void WindowManager::surface_created(unsigned pid, unsigned surface_id)
1317 if(this->tmp_surface2app.count(surface_id) != 0)
1319 string appid = this->tmp_surface2app[surface_id].appid;
1320 auto client = g_app_list.lookUpClient(appid);
1321 if(client != nullptr)
1323 WMError ret = client->addSurface(surface_id);
1324 HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
1325 if(ret != WMError::SUCCESS)
1327 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
1330 this->tmp_surface2app.erase(surface_id);
1334 HMI_NOTICE("Unknown surface %d", surface_id);
1336 std::ostringstream os;
1338 string path = "/proc/" + os.str() + "/stat";
1339 std::ifstream ifs(path.c_str());
1342 if(!ifs.fail() && std::getline(ifs, str))
1344 std::sscanf(str.data(), "%*d %*s %*c %d", &ppid);
1345 HMI_INFO("Retrieve ppid %d", ppid);
1349 HMI_ERROR("Failed to open /proc/%d/stat", pid);
1350 HMI_ERROR("File system may be different");
1353 struct AfbClosure* c = new struct AfbClosure(pid, ppid, surface_id);
1354 // search pid from surfaceID
1355 afb_service_call("afm-main", "runners", json_object_new_object(),
1356 [](void* closure, int stat, json_object* resp){
1357 HMI_DEBUG("check %s", json_object_get_string(resp));
1358 struct AfbClosure* c = static_cast<struct AfbClosure*>(closure);
1362 HMI_ERROR("Failed to call runners");
1367 json_object_object_get_ex(resp, "response", &j);
1368 string appid = g_context->searchApp(c->pid, c->ppid, c->surface, j);
1371 g_context->storeSurface(appid, c->ppid, c->surface);
1374 json_object_put(resp);
1380 void WindowManager::surface_removed(unsigned surface_id)
1382 HMI_DEBUG("Delete surface_id %u", surface_id);
1383 this->id_alloc.remove_id(surface_id);
1384 g_app_list.removeSurface(surface_id);
1387 void WindowManager::removeClient(const string &appid)
1389 HMI_DEBUG("Remove clinet %s from list", appid.c_str());
1390 auto client = g_app_list.lookUpClient(appid);
1391 this->lc->appTerminated(client);
1392 g_app_list.removeClient(appid);
1395 void WindowManager::exceptionProcessForTransition()
1397 unsigned req_num = g_app_list.currentRequestNumber();
1398 HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
1399 g_app_list.removeRequest(req_num);
1400 HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
1401 this->processNextRequest();
1404 void WindowManager::analyzeReceivedEvent(const char *event, struct json_object *object)
1406 HMI_DEBUG("event:%s", event);
1408 // If receive low can signal
1409 if (strstr(event, "low-can"))
1411 // Analyze low can signal
1412 const char *signal_name = this->lcc.analyzeCanSignal(object);
1414 // Create task for car state and input it to PolicyManager
1415 Task task = this->convertCanSignalToCarStateTask(signal_name);
1416 if (Task::TASK_INVALID != task)
1418 this->inputCarStateTask(task);
1423 void WindowManager::timerHandler()
1425 unsigned req_num = g_app_list.currentRequestNumber();
1426 HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
1427 g_app_list.reqDump();
1428 g_app_list.removeRequest(req_num);
1429 this->processNextRequest();
1432 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
1434 WMError ret = WMError::UNKNOWN;
1435 // req_num is guaranteed by Window Manager
1436 unsigned req_num = g_app_list.currentRequestNumber();
1437 Task task = Task::TASK_INVALID;
1439 if (actions.empty())
1441 if (g_app_list.haveRequest())
1443 HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
1444 goto proc_remove_request;
1448 HMI_SEQ_DEBUG(req_num, "There is no request");
1453 // Check weather there is the no request task
1454 // [The no request task]
1455 // - TaskCarState::RESTRICTION_MODE_OFF
1456 // - TaskCarState::RESTRICTION_MODE_ON
1457 for (const auto &act : actions)
1459 if (TaskCarState::RESTRICTION_MODE_OFF == act.car_state)
1461 task = Task::TASK_RESTRICTION_MODE_OFF;
1464 else if (TaskCarState::RESTRICTION_MODE_ON == act.car_state)
1466 task = Task::TASK_RESTRICTION_MODE_ON;
1471 // If there is the request-less task, set request here
1472 if (Task::TASK_INVALID != task) {
1474 ret = this->setRequest(task, &req_num);
1476 if(ret != WMError::SUCCESS)
1482 for (auto &act : actions)
1487 auto const &surface_id = this->id_alloc.lookup(act.role.c_str());
1488 if(surface_id == nullopt)
1490 HMI_SEQ_DEBUG(req_num, "There is not surface id for role:%s", act.role.c_str());
1494 string appid = g_app_list.getAppID(*surface_id, &found);
1497 if (TaskVisible::INVISIBLE == act.visible)
1499 HMI_SEQ_DEBUG(req_num, "role:%s is killed, so do not set this action", act.role.c_str());
1504 HMI_SEQ_ERROR(req_num, "appid of role:%s which is visible is not found", act.role.c_str());
1505 ret = WMError::FAIL;
1509 auto client = g_app_list.lookUpClient(appid);
1510 act.req_num = req_num;
1511 act.client = client;
1513 std::string appToEcuName = this->wmcon.getAppIdToEcuName(appid);
1515 if (this->wmcon.isRemoteEcu(appid))
1517 if (TaskVisible::VISIBLE == act.visible)
1519 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_VISIBLE");
1520 act.visible = TaskVisible::REQ_REMOTE_VISIBLE;
1524 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_INVISIBLE");
1525 act.visible = TaskVisible::REQ_REMOTE_INVISIBLE;
1530 ret = g_app_list.setAction(req_num, act);
1531 if (ret != WMError::SUCCESS)
1533 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1538 HMI_SEQ_DEBUG(req_num, "Start transition.");
1539 ret = this->startTransition(req_num);
1540 if (ret != WMError::SUCCESS)
1542 if (ret == WMError::NO_LAYOUT_CHANGE)
1544 goto proc_remove_request;
1548 HMI_SEQ_ERROR(req_num, "Transition state is failed");
1556 //this->emit_error()
1557 HMI_SEQ_ERROR(req_num, errorDescription(ret));
1558 this->pmw.undoState();
1560 proc_remove_request:
1561 g_app_list.removeRequest(req_num);
1562 this->processNextRequest();
1565 void WindowManager::processError(WMError error)
1567 unsigned req_num = g_app_list.currentRequestNumber();
1569 //this->emit_error()
1570 HMI_SEQ_ERROR(req_num, errorDescription(error));
1571 g_app_list.removeRequest(req_num);
1572 this->processNextRequest();
1575 void WindowManager::processForRemoteRequest(json_object *data)
1577 const char *req = jh::getStringFromJson(data, "req");
1578 const char *appid = jh::getStringFromJson(data, "appid");
1579 const char *drawing_name = jh::getStringFromJson(data, "drawing_name");
1580 const char *drawing_area = jh::getStringFromJson(data, "drawing_area");
1581 string request = req;
1582 string role = drawing_name;
1583 string area = drawing_area;
1585 if (!req || !drawing_name)
1587 HMI_ERROR("Parse Error!!");
1591 if (this->wmcon.getAreaToEcuName(drawing_area) == this->wmcon.getEcuName())
1595 HMI_ERROR("Parse Error!!");
1599 auto reply = [](const char *errmsg) {
1600 if (errmsg != nullptr)
1607 if ("activateWindow" == request)
1611 HMI_ERROR("Parse Error!!");
1615 this->api_activate_surface_for_slave(
1616 appid, drawing_name, drawing_area, reply);
1618 else if ("deactivateWindow" == request)
1620 this->api_deactivate_surface_for_slave(
1621 appid, drawing_name, reply);
1623 else if ("endDraw" == request)
1625 this->api_enddraw(appid, drawing_name);
1630 if ("syncDraw" == request)
1634 if (!appid || !drawing_area)
1636 HMI_ERROR("Parse Error!!");
1640 unsigned req_num = g_app_list.currentRequestNumber();
1641 auto client = g_app_list.lookUpClient(appid);
1643 // TODO: application requests by old role,
1644 // so convert role old to new
1645 const char *c_role = this->convertRoleOldToNew(drawing_name);
1648 bool end_draw_finished = false;
1655 TaskVisible::REMOTE_VISIBLE,
1657 TaskCarState::NO_TASK
1661 WMError ret = g_app_list.setAction(req_num, act);
1662 if (ret != WMError::SUCCESS)
1664 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1668 this->emit_syncdraw(role, area);
1669 this->wmcon.startSyncDrawForRemote(appid);
1672 else if ("activated" == request)
1674 this->emit_visible(role);
1675 this->emit_activated(area);
1677 else if ("deactivated" == request)
1681 if (!appid || !drawing_area)
1683 HMI_ERROR("Parse Error!!");
1687 unsigned req_num = g_app_list.currentRequestNumber();
1688 auto client = g_app_list.lookUpClient(appid);
1690 // TODO: application requests by old role,
1691 // so convert role old to new
1692 const char *c_role = this->convertRoleOldToNew(drawing_name);
1694 if(!this->wmcon.isRemoteEcu(appid))
1696 HMI_DEBUG("Deactivated");
1701 bool end_draw_finished = true;
1708 TaskVisible::REMOTE_INVISIBLE,
1710 TaskCarState::NO_TASK
1713 this->lc->visibilityChange(act);
1714 this->lc->renderLayers();
1716 this->emit_invisible(role);
1717 this->emit_deactivated(role);
1721 else if ("flushDraw" == request)
1723 this->emit_flushdraw(role);
1729 ******* Private Functions *******
1732 void WindowManager::emit_activated(const string& role)
1734 this->send_event(kListEventName[Event_Active], role);
1737 void WindowManager::emit_deactivated(const string& role)
1739 this->send_event(kListEventName[Event_Inactive], role);
1742 void WindowManager::emit_syncdraw(const string& role, char const *area, int x, int y, int w, int h)
1744 this->send_event(kListEventName[Event_SyncDraw], role, area, x, y, w, h);
1747 void WindowManager::emit_syncdraw(const string &role, const string &area)
1749 struct rect rect = this->lc->getAreaSize(area);
1750 this->send_event(kListEventName[Event_SyncDraw],
1751 role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
1754 void WindowManager::emit_flushdraw(const string& role)
1756 this->send_event(kListEventName[Event_FlushDraw], role);
1759 void WindowManager::emit_visible(const string& role, bool is_visible)
1761 this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], role);
1764 void WindowManager::emit_invisible(const string& role)
1766 return emit_visible(role, false);
1769 void WindowManager::emit_visible(const string& role) { return emit_visible(role, true); }
1771 void WindowManager::emitHeadlampOff()
1773 // Send HeadlampOff event for all application
1774 this->send_event(kListEventName[Event_HeadlampOff]);
1777 void WindowManager::emitHeadlampOn()
1779 // Send HeadlampOn event for all application
1780 this->send_event(kListEventName[Event_HeadlampOn]);
1783 void WindowManager::emitParkingBrakeOff()
1785 // Send ParkingBrakeOff event for all application
1786 this->send_event(kListEventName[Event_ParkingBrakeOff]);
1789 void WindowManager::emitParkingBrakeOn()
1791 // Send ParkingBrakeOn event for all application
1792 this->send_event(kListEventName[Event_ParkingBrakeOn]);
1795 void WindowManager::emitLightstatusBrakeOff()
1797 // Send LightstatusBrakeOff event for all application
1798 this->send_event(kListEventName[Event_LightstatusBrakeOff]);
1801 void WindowManager::emitLightstatusBrakeOn()
1803 // Send LightstatusBrakeOn event for all application
1804 this->send_event(kListEventName[Event_LightstatusBrakeOn]);
1807 void WindowManager::emitCarStop()
1809 // Send CarStop event for all application
1810 this->send_event(kListEventName[Event_CarStop]);
1813 void WindowManager::emitCarRun()
1815 // Send CarRun event for all application
1816 this->send_event(kListEventName[Event_CarRun]);
1819 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
1820 Task task, unsigned* req_num)
1822 if (!g_app_list.contains(appid))
1824 return WMError::NOT_REGISTERED;
1827 auto client = g_app_list.lookUpClient(appid);
1832 unsigned current = g_app_list.currentRequestNumber();
1833 unsigned requested_num = g_app_list.getRequestNumber(appid);
1834 if (requested_num != 0)
1836 HMI_SEQ_INFO(requested_num,
1837 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1838 return REQ_REJECTED;
1841 WMRequest req = WMRequest(appid, role, area, task);
1842 unsigned new_req = g_app_list.addRequest(req);
1844 g_app_list.reqDump();
1846 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1848 return WMError::SUCCESS;
1851 WMError WindowManager::setRequest(Task task, unsigned* req_num)
1856 unsigned current = g_app_list.currentRequestNumber();
1858 WMRequest req = WMRequest(task);
1859 unsigned new_req = g_app_list.addRequest(req);
1861 g_app_list.reqDump();
1863 HMI_SEQ_DEBUG(current, "start sequence for task:%d", task);
1865 return WMError::SUCCESS;
1868 WMError WindowManager::setRequestForSlave(const string& appid, const string &role, const string &area,
1869 Task task, unsigned* req_num)
1874 unsigned current = g_app_list.currentRequestNumber();
1875 unsigned requested_num = g_app_list.getRequestNumber(appid);
1876 if (requested_num != 0)
1878 HMI_SEQ_INFO(requested_num,
1879 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1880 return REQ_REJECTED;
1883 WMRequest req = WMRequest(appid, role, area, task);
1884 unsigned new_req = g_app_list.addRequest(req);
1886 g_app_list.reqDump();
1888 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1890 return WMError::SUCCESS;
1893 WMError WindowManager::checkPolicy(unsigned req_num)
1898 // get current trigger
1900 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1901 auto trigger = g_app_list.getRequest(req_num, &found);
1904 ret = WMError::NO_ENTRY;
1907 string req_area = trigger.area;
1909 if (trigger.task == Task::TASK_ALLOCATE)
1911 const char *msg = this->check_surface_exist(trigger.role.c_str());
1915 HMI_SEQ_ERROR(req_num, msg);
1920 // Input event data to PolicyManager
1921 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1923 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1927 // Execute state transition of PolicyManager
1928 if (0 > this->pmw.executeStateTransition())
1930 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1934 ret = WMError::SUCCESS;
1936 g_app_list.reqDump();
1941 WMError WindowManager::checkPolicyForSlave(unsigned req_num)
1946 // get current trigger
1948 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1949 auto trigger = g_app_list.getRequest(req_num, &found);
1952 ret = WMError::NO_ENTRY;
1955 string req_area = trigger.area;
1957 // Input event data to PolicyManager
1958 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1960 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1964 // Execute state transition of PolicyManager
1965 if (0 > this->pmw.executeStateTransition())
1967 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1971 ret = WMError::SUCCESS;
1973 g_app_list.reqDump();
1978 WMError WindowManager::startTransition(unsigned req_num)
1980 bool sync_draw_happen = false;
1982 WMError ret = WMError::SUCCESS;
1983 auto actions = g_app_list.getActions(req_num, &found);
1986 ret = WMError::NO_ENTRY;
1987 HMI_SEQ_ERROR(req_num,
1988 "Window Manager bug :%s : Action is not set", errorDescription(ret));
1992 g_app_list.reqDump();
1993 for (const auto &action : actions)
1995 // TODO: application requests by old role,
1996 // so convert role new to old for emitting event
1997 string old_role = this->rolenew2old[action.role];
1999 if (action.visible == TaskVisible::VISIBLE)
2001 sync_draw_happen = true;
2003 this->emit_syncdraw(old_role, action.area);
2004 /* TODO: emit event for app not subscriber
2005 if(g_app_list.contains(y.appid))
2006 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
2008 else if(action.visible == TaskVisible::REQ_REMOTE_VISIBLE)
2010 // If this action is for slave, send to slave
2011 this->wmcon.sendRequest("syncDraw", action.client->appID().c_str(),
2012 old_role.c_str(), action.area.c_str());
2014 else if (action.car_state != TaskCarState::NO_TASK)
2016 this->transitionCarState(action.car_state);
2020 if (sync_draw_happen)
2026 // deactivate only, no syncDraw
2027 // Make it deactivate here
2028 for (const auto &x : actions)
2030 this->lc->visibilityChange(x);
2031 string old_role = this->rolenew2old[x.role];
2033 if (x.visible == TaskVisible::INVISIBLE)
2035 emit_deactivated(old_role);
2037 else if (x.visible == TaskVisible::REQ_REMOTE_INVISIBLE)
2039 // If this action is for slave, send to slave
2040 int i_ret = this->wmcon.sendRequest("deactivated", x.client->appID().c_str(),
2041 old_role.c_str(), "");
2044 ret = WMError::FAIL;
2048 /* if (g_app_list.contains(x.appid))
2050 auto client = g_app_list.lookUpClient(x.appid);
2051 //this->deactivate(client->surfaceID(x.role));
2054 this->lc->renderLayers();
2055 ret = WMError::NO_LAYOUT_CHANGE;
2060 void WindowManager::transitionCarState(TaskCarState task)
2062 if (TaskCarState::PARKING_BRAKE_OFF == task)
2064 this->crr_car_info.parking_brake_stt = false;
2065 this->emitParkingBrakeOff();
2067 else if (TaskCarState::PARKING_BRAKE_ON == task)
2069 this->crr_car_info.parking_brake_stt = true;
2070 this->emitParkingBrakeOn();
2072 else if (TaskCarState::ACCEL_PEDAL_OFF == task)
2074 this->crr_car_info.accel_pedal_stt = false;
2076 else if (TaskCarState::ACCEL_PEDAL_ON == task)
2078 this->crr_car_info.accel_pedal_stt = true;
2080 else if (TaskCarState::HEDLAMP_OFF == task)
2082 this->crr_car_info.headlamp_stt = false;
2083 this->emitHeadlampOff();
2085 else if (TaskCarState::HEDLAMP_ON == task)
2087 this->crr_car_info.headlamp_stt = true;
2088 this->emitHeadlampOn();
2090 else if (TaskCarState::LIGHTSTATUS_BRAKE_OFF == task)
2092 this->crr_car_info.lightstatus_brake_stt = false;
2093 this->emitLightstatusBrakeOff();
2095 else if (TaskCarState::LIGHTSTATUS_BRAKE_ON == task)
2097 this->crr_car_info.lightstatus_brake_stt = true;
2098 this->emitLightstatusBrakeOn();
2100 else if (TaskCarState::CAR_STOP == task)
2102 this->crr_car_info.running_stt = false;
2103 this->emitCarStop();
2105 else if (TaskCarState::CAR_RUN == task)
2107 this->crr_car_info.running_stt = true;
2112 WMError WindowManager::doEndDraw(unsigned req_num)
2116 bool trigger_homescreen = false;
2117 auto actions = g_app_list.getActions(req_num, &found);
2118 WMError ret = WMError::SUCCESS;
2121 ret = WMError::NO_ENTRY;
2124 auto trigger = g_app_list.getRequest(req_num, &found);
2125 HMI_SEQ_INFO(req_num, "trigger.role = %s", trigger.role.c_str());
2127 if(trigger.role == "homescreen")
2129 trigger_homescreen = true;
2132 HMI_SEQ_INFO(req_num, "do endDraw");
2134 // layout change and make it visible
2135 for (const auto &act : actions)
2137 if(act.visible != TaskVisible::NO_CHANGE)
2140 ret = this->lc->layoutChange(act);
2141 if(ret != WMError::SUCCESS)
2143 HMI_SEQ_WARNING(req_num,
2144 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
2148 if(trigger_homescreen && (act.visible == TaskVisible::INVISIBLE))
2150 HMI_SEQ_NOTICE(req_num, "don't change visible if homescreen role is trigger");
2154 ret = this->lc->visibilityChange(act);
2157 // Emit active/deactive event
2158 string old_role = this->rolenew2old[act.role];
2161 case TaskVisible::VISIBLE :
2162 emit_visible(old_role);
2163 emit_activated(old_role);
2165 case TaskVisible::REQ_REMOTE_VISIBLE :
2167 // If this action is for slave, send to slave
2168 int i_ret = this->wmcon.sendRequest("activated", "", old_role.c_str(), "");
2171 ret = WMError::FAIL;
2175 case TaskVisible::INVISIBLE :
2176 if(!trigger_homescreen)
2178 emit_invisible(old_role);
2179 emit_deactivated(old_role);
2183 // TaskVisible::REMOTE_VISIBLE, TaskVisible::REMOTE_INVISIBLE is this case
2184 // If this action is for slave, send to slave
2188 if (ret != WMError::SUCCESS)
2190 HMI_SEQ_WARNING(req_num,
2191 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
2194 HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
2197 this->lc->renderLayers();
2199 HMI_SEQ_INFO(req_num, "emit flushDraw");
2201 for(const auto &act_flush : actions)
2203 // TODO: application requests by old role,
2204 // so convert role new to old for emitting event
2205 string old_role = this->rolenew2old[act_flush.role];
2207 if(act_flush.visible == TaskVisible::VISIBLE)
2209 this->emit_flushdraw(old_role);
2211 else if(act_flush.visible == TaskVisible::REQ_REMOTE_VISIBLE)
2213 // If this action is for slave, send to slave
2214 this->wmcon.sendRequest("flushDraw", "", old_role.c_str(), "");
2221 void WindowManager::emitScreenUpdated(unsigned req_num)
2224 HMI_SEQ_DEBUG(req_num, "emit screen updated");
2226 auto actions = g_app_list.getActions(req_num, &found);
2230 HMI_SEQ_ERROR(req_num,
2231 "Window Manager bug :%s : Action is not set",
2232 errorDescription(WMError::NO_ENTRY));
2237 // create json object
2238 json_object *j = json_object_new_object();
2239 json_object *jarray = json_object_new_array();
2241 for(const auto& action: actions)
2243 if((action.visible == TaskVisible::VISIBLE) ||
2244 (action.visible == TaskVisible::REMOTE_VISIBLE))
2246 json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
2249 json_object_object_add(j, kKeyIds, jarray);
2250 HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
2252 int ret = afb_event_push(
2253 this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
2256 HMI_DEBUG("afb_event_push failed: %m");
2260 void WindowManager::setTimer()
2263 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
2264 HMI_ERROR("Could't set time (clock_gettime() returns with error");
2268 HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
2269 if (g_timer_ev_src == nullptr)
2271 // firsttime set into sd_event
2272 int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
2273 CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
2276 HMI_ERROR("Could't set timer");
2281 // update timer limitation after second time
2282 sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
2283 sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
2287 void WindowManager::stopTimer()
2289 unsigned req_num = g_app_list.currentRequestNumber();
2290 HMI_SEQ_DEBUG(req_num, "Timer stop");
2291 int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
2294 HMI_SEQ_ERROR(req_num, "Timer stop failed");
2298 void WindowManager::processNextRequest()
2301 g_app_list.reqDump();
2302 unsigned req_num = g_app_list.currentRequestNumber();
2303 if (g_app_list.haveRequest())
2305 HMI_SEQ_DEBUG(req_num, "Process next request");
2306 WMError rc = checkPolicy(req_num);
2307 if (rc != WMError::SUCCESS)
2309 HMI_SEQ_ERROR(req_num, errorDescription(rc));
2314 HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
2318 const char* WindowManager::convertRoleOldToNew(char const *old_role)
2320 const char *new_role = nullptr;
2322 for (auto const &on : this->roleold2new)
2324 std::regex regex = std::regex(on.first);
2325 if (std::regex_match(old_role, regex))
2327 // role is old. So convert to new.
2328 new_role = on.second.c_str();
2333 if (nullptr == new_role)
2335 // role is new or fallback.
2336 new_role = old_role;
2339 HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
2344 int WindowManager::loadOldRolesConfigFile()
2346 // Get afm application installed dir
2347 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
2348 HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
2351 if (!afm_app_install_dir)
2353 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
2357 file_name = string(afm_app_install_dir) + string(kPathOldRolesConfigFile);
2360 // Load old_rolea config file
2361 json_object* json_obj;
2362 int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
2365 HMI_ERROR("Could not open %s, so use default old_roles information", kPathOldRolesConfigFile);
2366 json_obj = json_tokener_parse(kDefaultOldRolesConfig);
2368 HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
2371 json_object* json_cfg;
2372 if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
2374 HMI_ERROR("Parse Error!!");
2378 int len = json_object_array_length(json_cfg);
2379 HMI_DEBUG("json_cfg len:%d", len);
2380 HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
2382 for (int i=0; i<len; i++)
2384 json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
2386 const char* old_role = jh::getStringFromJson(json_tmp, "name");
2387 if (nullptr == old_role)
2389 HMI_ERROR("Parse Error!!");
2393 const char* new_role = jh::getStringFromJson(json_tmp, "new");
2394 if (nullptr == new_role)
2396 HMI_ERROR("Parse Error!!");
2400 this->roleold2new[old_role] = string(new_role);
2404 for(auto itr = this->roleold2new.begin();
2405 itr != this->roleold2new.end(); ++itr)
2407 HMI_DEBUG(">>> role old:%s new:%s",
2408 itr->first.c_str(), itr->second.c_str());
2411 // Release json_object
2412 json_object_put(json_obj);
2417 int WindowManager::saveLastModeData(unsigned req_num)
2420 auto actions = g_app_list.getActions(req_num, &found);
2422 HMI_DEBUG("Save LastMode data");
2426 HMI_DEBUG("Not Found Entry");
2430 json_object *j_obj = json_object_new_object();
2431 json_object *j_array = json_object_new_array();
2433 for (const auto &act : actions)
2435 if (act.visible == TaskVisible::VISIBLE)
2437 unsigned layer = act.client->layerID();
2438 unsigned surface = act.client->surfaceID();
2440 t_ilm_bool visibility;
2442 ilm_layerGetVisibility(layer, &visibility);
2444 if (visibility == ILM_FALSE)
2449 ilmSurfaceProperties sp;
2450 ilm_getPropertiesOfSurface(surface, &sp);
2452 json_object *j_array_obj = json_object_new_object();
2453 json_object_object_add(j_array_obj, "role", json_object_new_string(act.role.c_str()));
2454 json_object_object_add(j_array_obj, "visible",
2455 json_object_new_string((visibility ? "true" : "false")));
2456 json_object_object_add(j_array_obj, "area", json_object_new_string(act.area.c_str()));
2457 json_object_object_add(j_array_obj, "destX", json_object_new_int(sp.destX));
2458 json_object_object_add(j_array_obj, "destY", json_object_new_int(sp.destY));
2459 json_object_object_add(j_array_obj, "destWidth", json_object_new_int(sp.destWidth));
2460 json_object_object_add(j_array_obj, "destHeight", json_object_new_int(sp.destHeight));
2461 json_object_object_add(j_array_obj, "sourceX", json_object_new_int(sp.sourceX));
2462 json_object_object_add(j_array_obj, "sourceY", json_object_new_int(sp.sourceY));
2463 json_object_object_add(j_array_obj, "sourceWidth", json_object_new_int(sp.sourceWidth));
2464 json_object_object_add(j_array_obj, "sourceHeight", json_object_new_int(sp.sourceHeight));
2466 json_object_array_add(j_array, j_array_obj);
2470 json_object_object_add(j_obj, "LastModeData", j_array);
2472 const char *buf = json_object_to_json_string(j_obj);
2474 std::string root = getenv("AFM_APP_INSTALL_DIR");
2475 std::string lastmode_path = root + WM_LASTMODE_PATH;
2477 FILE *fp = fopen(lastmode_path.c_str(), "wb");
2480 HMI_ERROR("Could not open file");
2484 int len = strlen(buf);
2485 fwrite(buf, len, 1, fp);
2489 json_object_put(j_obj);
2494 Task WindowManager::convertCanSignalToCarStateTask(const char *signal_name)
2496 wm::LowCanClient *lcc = &(this->lcc);
2497 Task task = Task::TASK_INVALID;
2499 // If car info is updated, set car state change event
2500 if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoParkingBrake]))
2502 HMI_DEBUG("Parking Brake state is changed");
2504 if (lcc->getCurrentParkingBrakeState())
2506 task = wm::Task::TASK_PARKING_BRAKE_ON;
2510 task = wm::Task::TASK_PARKING_BRAKE_OFF;
2513 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoAccelPedalPos]))
2515 // Update accel pedal position
2516 this->crr_car_info.accel_pedal_pos = lcc->getCurrentAccelPedalPosition();
2518 if (lcc->isChangedAccelPedalState())
2520 HMI_DEBUG("Accelerator Pedal state is changed");
2522 if (lcc->getCurrentAccelPedalState())
2524 task = wm::Task::TASK_ACCEL_PEDAL_ON;
2528 task = wm::Task::TASK_ACCEL_PEDAL_OFF;
2532 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoHeadlame]))
2534 HMI_DEBUG("Headlamp state is changed");
2536 if (lcc->getCurrentHeadlampState())
2538 task = wm::Task::TASK_HEDLAMP_ON;
2542 task = wm::Task::TASK_HEDLAMP_OFF;
2545 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoLightstatusBrake]))
2547 HMI_DEBUG("Lightstatus Brake state is changed");
2549 if (lcc->getCurrentLightstatusBrakeState())
2551 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_ON;
2555 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_OFF;
2561 void WindowManager::inputCarStateTask(Task task)
2563 unsigned req_num = 0;
2564 WMError ret = WMError::UNKNOWN;
2566 ret = this->setRequest(task, &req_num);
2568 if(ret != WMError::SUCCESS)
2570 HMI_ERROR(errorDescription(ret));
2574 if (req_num != g_app_list.currentRequestNumber())
2576 // Add request, then invoked after the previous task is finished
2577 HMI_SEQ_DEBUG(req_num, "request is accepted");
2584 ret = this->checkPolicy(req_num);
2586 if (ret != WMError::SUCCESS)
2588 //this->emit_error()
2589 HMI_SEQ_ERROR(req_num, errorDescription(ret));
2590 g_app_list.removeRequest(req_num);
2591 this->processNextRequest();
2595 const char *WindowManager::check_surface_exist(const char *drawing_name)
2597 auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
2600 return "Surface does not exist";
2603 /* if (!this->controller->surface_exists(*surface_id))
2605 return "Surface does not exist in controller!";
2608 /* auto layer_id = this->layers.get_layer_id(*surface_id);
2612 return "Surface is not on any layer!";
2615 HMI_DEBUG("surface %d is detected", *surface_id);
2619 const char* WindowManager::kDefaultOldRolesConfig = "{ \
2622 \"name\": \"HomeScreen\", \
2623 \"new\": \"homescreen\" \
2626 \"name\": \"Music\", \
2627 \"new\": \"music\" \
2630 \"name\": \"MediaPlayer\", \
2631 \"new\": \"music\" \
2634 \"name\": \"Video\", \
2635 \"new\": \"video\" \
2638 \"name\": \"VideoPlayer\", \
2639 \"new\": \"video\" \
2642 \"name\": \"WebBrowser\", \
2643 \"new\": \"browser\" \
2646 \"name\": \"Radio\", \
2647 \"new\": \"radio\" \
2650 \"name\": \"Phone\", \
2651 \"new\": \"phone\" \
2654 \"name\": \"Navigation\", \
2658 \"name\": \"HVAC\", \
2662 \"name\": \"Settings\", \
2663 \"new\": \"settings\" \
2666 \"name\": \"Dashboard\", \
2667 \"new\": \"dashboard\" \
2670 \"name\": \"POI\", \
2674 \"name\": \"Mixer\", \
2675 \"new\": \"mixer\" \
2678 \"name\": \"Restriction\", \
2679 \"new\": \"restriction\" \
2682 \"name\": \"^OnScreen.*\", \
2683 \"new\": \"on_screen\" \