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>
36 static const uint64_t kTimeOut = 3ULL; /* 3s */
38 /* DrawingArea name used by "{layout}.{area}" */
39 const char kNameLayoutNormal[] = "normal";
40 const char kNameLayoutSplit[] = "split";
41 const char kNameAreaFull[] = "full";
42 const char kNameAreaMain[] = "main";
43 const char kNameAreaSub[] = "sub";
45 /* Key for json obejct */
46 const char kKeyDrawingName[] = "drawing_name";
47 const char kKeyDrawingArea[] = "drawing_area";
48 const char kKeyDrawingRect[] = "drawing_rect";
49 const char kKeyX[] = "x";
50 const char kKeyY[] = "y";
51 const char kKeyWidth[] = "width";
52 const char kKeyHeight[] = "height";
53 const char kKeyWidthPixel[] = "width_pixel";
54 const char kKeyHeightPixel[] = "height_pixel";
55 const char kKeyWidthMm[] = "width_mm";
56 const char kKeyHeightMm[] = "height_mm";
57 const char kKeyScale[] = "scale";
58 const char kKeyIds[] = "ids";
60 static const vector<string> kListEventName{
72 "lightstatusBrakeOff",
78 static const char kPathOldRolesConfigFile[] = "/etc/old_roles.json";
79 static sd_event_source *g_timer_ev_src = nullptr;
80 static AppList g_app_list;
81 static WindowManager *g_context;
85 AfbClosure(unsigned pid, unsigned ppid, unsigned surface)
86 : pid(pid), ppid(ppid), surface(surface) {}
87 ~AfbClosure() = default;
96 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
98 HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
99 reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
103 static void onStateTransitioned(vector<WMAction> actions)
105 g_context->startTransitionWrapper(actions);
108 static void onError()
110 g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
113 static void onReceiveRemoteRequest(json_object *data)
115 g_context->processForRemoteRequest(data);
122 WindowManager::WindowManager()
126 const char *path = getenv("AFM_APP_INSTALL_DIR");
129 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
133 // TODO: ECU name should be decide by config file
134 // Get mode and decide ECU name
135 string ecu_name = this->wmcon.getEcuName();
137 this->lc = std::make_shared<LayerControl>(root, ecu_name);
139 HMI_DEBUG("Layer Controller initialized");
142 int WindowManager::init()
144 LayerControlCallbacks lmcb;
145 lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
146 this->surface_created(pid, surface);
148 lmcb.surfaceDestroyed = [&](unsigned surface){
149 this->surface_removed(surface);
151 this->lc->init(lmcb);
153 // TODO: application requests by old role,
154 // so create role map (old, new)
155 // Load old_roles config file
156 this->loadOldRolesConfigFile();
158 // Initialize LowCanClient
159 this->lcc.initialize();
161 // Store my context for calling callback from PolicyManager
164 // Initialize PMWrapper
165 this->pmw.initialize(this->wmcon.getEcuName());
167 // Register callback to PolicyManager
168 this->pmw.registerCallback(onStateTransitioned, onError);
170 // Initialize WMConnection
171 this->wmcon.initialize();
173 // Register callback to WMConnection
174 this->wmcon.registerCallback(onReceiveRemoteRequest);
177 for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
179 map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str());
182 const struct rect css_bg = this->lc->getAreaSize("fullscreen");
183 Screen screen = this->lc->getScreenInfo();
184 rectangle dp_bg(screen.width(), screen.height());
186 dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
187 dp_bg.fit(screen.width(), screen.height());
188 dp_bg.center(screen.width(), screen.height());
189 HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
190 css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
192 double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
193 this->lc->setupArea(dp_bg, scale);
195 return 0; //init_layers();
198 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
200 // TODO: application requests by old role,
201 // so convert role old to new
202 const char *role = this->convertRoleOldToNew(drawing_name);
204 string s_appid = appid;
205 string s_role = role;
207 if(!g_app_list.contains(s_appid))
209 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
212 // register drawing_name as fallback and make it displayed.
213 l_id = this->lc->getNewLayerID("fallback", &l_name);
214 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
217 return Err<int>("Designated role does not match any role, fallback is disabled");
221 // TODO: remote layer size is fixed value
222 if ("Remote" == l_name)
224 this->lc->createNewRemoteLayer(l_id);
228 this->lc->createNewLayer(l_id);
231 // add client into the db
232 g_app_list.addClient(s_appid, l_id, s_role);
235 // generate surface ID for ivi-shell application
237 auto rname = this->id_alloc.lookup(string(role));
240 // name does not exist yet, allocate surface id...
241 auto id = int(this->id_alloc.generate_id(role));
242 this->tmp_surface2app[id] = {s_appid, 0};
245 HMI_NOTICE("WORK AROUND: add surface on request surface");
246 auto client = g_app_list.lookUpClient(s_appid);
247 client->addSurface(id);
250 // Set role map of (new, old)
251 this->rolenew2old[role] = string(drawing_name);
256 // Check currently registered drawing names if it is already there.
257 return Err<int>("Surface already present");
260 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
263 unsigned sid = std::stol(ivi_id);
265 HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
267 * IVI-shell doesn't send surface_size event via ivi-wm protocol
268 * if the application is using XDG surface.
269 * So WM has to set surface size with original size here
271 WMError ret = this->lc->setXDGSurfaceOriginSize(sid);
274 HMI_ERROR("%s", errorDescription(ret));
275 HMI_WARNING("The main user of this API is runXDG");
279 // TODO: application requests by old role,
280 // so convert role old to new
281 const char *role = this->convertRoleOldToNew(drawing_name);
282 string s_role = role;
283 string s_appid = appid;
286 if(!g_app_list.contains(s_appid))
288 // auto lid = this->layers.get_layer_id(string(role));
289 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
293 * register drawing_name as fallback and make it displayed.
295 l_id = this->lc->getNewLayerID("fallback", &l_name);
296 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
299 return "Designated role does not match any role, fallback is disabled";
303 // TODO: remote layer size is fixed value
304 if ("Remote" == l_name)
306 this->lc->createNewRemoteLayer(l_id);
310 this->lc->createNewLayer(l_id);
313 // add client into the db
314 g_app_list.addClient(s_appid, l_id, s_role);
317 auto rname = this->id_alloc.lookup(s_role);
320 return "Surface already present";
323 // register pair drawing_name and ivi_id
324 this->id_alloc.register_name_id(role, sid);
326 auto client = g_app_list.lookUpClient(s_appid);
327 client->addSurface(sid);
329 // Set role map of (new, old)
330 this->rolenew2old[role] = string(drawing_name);
335 bool WindowManager::api_set_role(char const *appid, char const *drawing_name)
339 // TODO: application requests by old role,
340 // so convert role old to new
341 const char *role = this->convertRoleOldToNew(drawing_name);
342 string s_role = role;
343 string s_appid = appid;
347 if(!g_app_list.contains(s_appid))
349 // auto lid = this->layers.get_layer_id(string(role));
350 unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
354 * register drawing_name as fallback and make it displayed.
356 l_id = this->lc->getNewLayerID("fallback", &l_name);
357 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
360 HMI_ERROR("Designated role does not match any role, fallback is disabled");
365 // TODO: remote layer size is fixed value
366 if ("Remote" == l_name)
368 this->lc->createNewRemoteLayer(l_id);
372 this->lc->createNewLayer(l_id);
375 // add client into the db
376 g_app_list.addClient(s_appid, l_id, s_role);
377 // Set role map of (new, old)
378 this->rolenew2old[role] = string(drawing_name);
381 // for(auto itr = this->tmp_surface2app.begin();
382 // itr != this->tmp_surface2app.end() ; ++itr)
384 for(auto& x : this->tmp_surface2app)
386 if(x.second.appid == s_appid)
388 unsigned surface = x.first;
389 auto client = g_app_list.lookUpClient(s_appid);
390 client->addSurface(surface);
391 this->tmp_surface2app.erase(surface);
392 this->id_alloc.register_name_id(s_role, surface);
398 // search floating surfaceID from pid if pid is designated.
399 wm_err = g_app_list.popFloatingSurface(pid, &surface);
402 // get floating surface with appid. If WM queries appid from pid,
403 // WM can bind surface and role with appid(not implemented yet)
404 //wm_err = g_app_list.popFloatingSurface(id);
406 if(wm_err != WMError::SUCCESS){
407 HMI_ERROR("No floating surface for app: %s", id.c_str());
408 g_app_list.addFloatingClient(id, lid, role);
409 HMI_NOTICE("%s : Waiting for surface creation", id.c_str());
414 if (g_app_list.contains(id))
416 HMI_INFO("Add role: %s with surface: %d. Client %s has multi surfaces.",
417 role.c_str(), surface, id.c_str());
418 auto client = g_app_list.lookUpClient(id);
419 client->appendRole(role);
422 HMI_INFO("Create new client: %s, surface: %d into layer: %d with role: %s",
423 id.c_str(), surface, lid, role.c_str());
424 g_app_list.addClient(id, lid, role);
427 // register pair drawing_name and ivi_id
432 void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
433 char const *drawing_area, const reply_func &reply)
435 // TODO: application requests by old role,
436 // so convert role old to new
437 const char *c_role = this->convertRoleOldToNew(drawing_name);
440 string role = c_role;
441 string area = drawing_area;
443 if(!g_app_list.contains(id))
445 reply("app doesn't request 'requestSurface' or 'setRole' yet");
448 auto client = g_app_list.lookUpClient(id);
450 // unsigned srfc = client->surfaceID(role);
451 // unsigned layer = client->layerID();
453 // g_app_list.removeFloatingSurface(client->surfaceID());
454 // g_app_list.removeFloatingSurface(client);
456 Task task = Task::TASK_ALLOCATE;
457 unsigned req_num = 0;
458 WMError ret = WMError::UNKNOWN;
460 ret = this->setRequest(id, role, area, task, &req_num);
462 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
463 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
465 if(ret != WMError::SUCCESS)
467 HMI_ERROR(errorDescription(ret));
468 reply("Failed to set request");
473 if (req_num != g_app_list.currentRequestNumber())
475 // Add request, then invoked after the previous task is finished
476 HMI_SEQ_DEBUG(req_num, "request is accepted");
483 ret = this->checkPolicy(req_num);
485 if (ret != WMError::SUCCESS)
488 HMI_SEQ_ERROR(req_num, errorDescription(ret));
489 g_app_list.removeRequest(req_num);
490 this->processNextRequest();
494 void WindowManager::api_activate_surface_for_slave(
495 char const *appid, char const *drawing_name,
496 char const *drawing_area, const reply_func &reply)
498 // TODO: application requests by old role,
499 // so convert role old to new
500 const char *c_role = this->convertRoleOldToNew(drawing_name);
503 string role = c_role;
504 string area = drawing_area;
506 if(!g_app_list.contains(id))
508 // Request surface of app in slave to register app information
509 this->api_request_surface(appid, drawing_name);
511 // Set role of app in slave to register app information
512 this->api_set_role(appid, drawing_name);
514 auto client = g_app_list.lookUpClient(id);
516 // unsigned srfc = client->surfaceID(role);
517 // unsigned layer = client->layerID();
519 // g_app_list.removeFloatingSurface(client->surfaceID());
520 // g_app_list.removeFloatingSurface(client);
522 Task task = Task::TASK_ALLOCATE;
523 unsigned req_num = 0;
524 WMError ret = WMError::UNKNOWN;
526 ret = this->setRequestForSlave(id, role, area, task, &req_num);
528 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
529 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
531 if(ret != WMError::SUCCESS)
533 HMI_ERROR(errorDescription(ret));
534 reply("Failed to set request");
539 if (req_num != g_app_list.currentRequestNumber())
541 // Add request, then invoked after the previous task is finished
542 HMI_SEQ_DEBUG(req_num, "request is accepted");
549 ret = this->checkPolicyForSlave(req_num);
551 if (ret != WMError::SUCCESS)
554 HMI_SEQ_ERROR(req_num, errorDescription(ret));
555 g_app_list.removeRequest(req_num);
556 this->processNextRequest();
560 void WindowManager::api_activate_surface_to_master(
561 char const *appid, char const *drawing_name,
562 char const *drawing_area, const reply_func &reply)
564 // TODO: application requests by old role,
565 // so convert role old to new
566 const char *c_role = this->convertRoleOldToNew(drawing_name);
569 string role = c_role;
570 string area = drawing_area;
572 if(!g_app_list.contains(id))
574 reply("app doesn't request 'requestSurface' or 'setRole' yet");
577 auto client = g_app_list.lookUpClient(id);
579 // unsigned srfc = client->surfaceID(role);
580 // unsigned layer = client->layerID();
582 // g_app_list.removeFloatingSurface(client->surfaceID());
583 // g_app_list.removeFloatingSurface(client);
585 Task task = Task::TASK_ALLOCATE;
586 unsigned req_num = 0;
587 WMError ret = WMError::UNKNOWN;
589 ret = this->setRequest(id, role, area, task, &req_num);
591 //vector<WMLayerState> current_states = this->lc->getCurrentStates();
592 // ret = this->setRequest(id, role, area, task, current_states, &req_num);
594 if(ret != WMError::SUCCESS)
596 HMI_ERROR(errorDescription(ret));
597 reply("Failed to set request");
602 if (req_num != g_app_list.currentRequestNumber())
604 // Add request, then invoked after the previous task is finished
605 HMI_SEQ_DEBUG(req_num, "request is accepted");
612 int i_ret = this->wmcon.sendRequest("activateWindow", appid,
613 drawing_name, drawing_area);
617 HMI_SEQ_ERROR(req_num, errorDescription(ret));
618 g_app_list.removeRequest(req_num);
619 this->processNextRequest();
625 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
626 const reply_func &reply)
628 // TODO: application requests by old role,
629 // so convert role old to new
630 const char *c_role = this->convertRoleOldToNew(drawing_name);
636 string role = c_role;
637 string area = ""; //drawing_area;
638 Task task = Task::TASK_RELEASE;
639 unsigned req_num = 0;
640 WMError ret = WMError::UNKNOWN;
642 ret = this->setRequest(id, role, area, task, &req_num);
644 if (ret != WMError::SUCCESS)
646 HMI_ERROR(errorDescription(ret));
647 reply("Failed to set request");
652 if (req_num != g_app_list.currentRequestNumber())
654 // Add request, then invoked after the previous task is finished
655 HMI_SEQ_DEBUG(req_num, "request is accepted");
662 ret = this->checkPolicy(req_num);
664 if (ret != WMError::SUCCESS)
667 HMI_SEQ_ERROR(req_num, errorDescription(ret));
668 g_app_list.removeRequest(req_num);
669 this->processNextRequest();
673 void WindowManager::api_deactivate_surface_for_slave(char const *appid, char const *drawing_name,
674 const reply_func &reply)
676 // TODO: application requests by old role,
677 // so convert role old to new
678 const char *c_role = this->convertRoleOldToNew(drawing_name);
684 string role = c_role;
685 string area = "";//drawing_area;
686 Task task = Task::TASK_RELEASE;
687 unsigned req_num = 0;
688 WMError ret = WMError::UNKNOWN;
690 ret = this->setRequest(id, role, area, task, &req_num);
692 if (ret != WMError::SUCCESS)
694 HMI_ERROR(errorDescription(ret));
695 reply("Failed to set request");
700 if (req_num != g_app_list.currentRequestNumber())
702 // Add request, then invoked after the previous task is finished
703 HMI_SEQ_DEBUG(req_num, "request is accepted");
710 ret = this->checkPolicyForSlave(req_num);
712 if (ret != WMError::SUCCESS)
715 HMI_SEQ_ERROR(req_num, errorDescription(ret));
716 g_app_list.removeRequest(req_num);
717 this->processNextRequest();
721 void WindowManager::api_deactivate_surface_to_master(char const *appid, char const *drawing_name,
722 const reply_func &reply)
724 // TODO: application requests by old role,
725 // so convert role old to new
726 const char *c_role = this->convertRoleOldToNew(drawing_name);
732 string role = c_role;
733 string area = "";//drawing_area;
734 Task task = Task::TASK_RELEASE;
735 unsigned req_num = 0;
736 WMError ret = WMError::UNKNOWN;
738 ret = this->setRequest(id, role, area, task, &req_num);
740 if (ret != WMError::SUCCESS)
742 HMI_ERROR(errorDescription(ret));
743 reply("Failed to set request");
748 if (req_num != g_app_list.currentRequestNumber())
750 // Add request, then invoked after the previous task is finished
751 HMI_SEQ_DEBUG(req_num, "request is accepted");
758 int i_ret = this->wmcon.sendRequest("deactivateWindow", appid,
763 HMI_SEQ_ERROR(req_num, errorDescription(ret));
764 g_app_list.removeRequest(req_num);
765 this->processNextRequest();
771 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
773 // TODO: application requests by old role,
774 // so convert role old to new
775 const char *c_role = this->convertRoleOldToNew(drawing_name);
778 string role = c_role;
779 unsigned current_req = g_app_list.currentRequestNumber();
780 bool result = g_app_list.setEndDrawFinished(current_req, id, role);
784 HMI_ERROR("%s is not in transition state", id.c_str());
788 if (g_app_list.endDrawFullfilled(current_req))
790 // do task for endDraw
792 WMError ret = this->doEndDraw(current_req);
794 if(ret != WMError::SUCCESS)
796 //this->emit_error();
798 // Undo state of PolicyManager
799 this->pmw.undoState();
800 this->lc->undoUpdate();
802 this->emitScreenUpdated(current_req);
803 HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
805 g_app_list.removeRequest(current_req);
807 this->processNextRequest();
811 HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
816 int WindowManager::api_subscribe(afb_req req, int event_id)
818 struct afb_event event = this->map_afb_event[kListEventName[event_id]];
819 return afb_req_subscribe(req, event);
822 void WindowManager::api_enddraw_for_remote(char const *appid, char const *drawing_name)
824 int ret = this->wmcon.sendRequest("endDraw", appid, drawing_name, "");
829 this->pmw.undoState();
830 this->lc->undoUpdate();
832 unsigned current_req = g_app_list.currentRequestNumber();
833 g_app_list.removeRequest(current_req);
834 this->processNextRequest();
839 this->api_enddraw(appid, drawing_name);
842 bool WindowManager::api_client_set_render_order(char const* appid, const vector<string>& render_order)
846 auto client = g_app_list.lookUpClient(id);
849 client->setRenderOrder(render_order);
854 string WindowManager::api_client_attach_service_surface
855 (const char* appid, const char* dest, const char* service_surface)
857 string uuid, s_dest = dest;
858 auto client = g_app_list.lookUpClient(s_dest);
861 HMI_ERROR("Failed to look up destination [%s]", dest);
864 uuid = client->attachTmpServiceSurface(appid, service_surface);
865 this->tmp_services.emplace_back(TmpService{appid, dest, service_surface, uuid});
869 result<json_object *> WindowManager::api_get_display_info()
871 Screen screen = this->lc->getScreenInfo();
873 json_object *object = json_object_new_object();
874 json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
875 json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
877 json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
878 json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
879 json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
881 return Ok<json_object *>(object);
884 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
888 // TODO: application requests by old role,
889 // so convert role old to new
890 const char *role = this->convertRoleOldToNew(drawing_name);
892 // Check drawing name, surface/layer id
893 auto const &surface_id = this->id_alloc.lookup(role);
896 return Err<json_object *>("Surface does not exist");
899 // Set area rectangle
900 rect area_info = this->area_info[*surface_id];
901 json_object *object = json_object_new_object();
902 json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
903 json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
904 json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
905 json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
907 return Ok<json_object *>(object);
910 result<json_object *> WindowManager::api_get_car_info(char const *label)
912 json_object *j_in = nullptr;
913 json_object *j_out = nullptr;
915 if (0 == strcmp("parking_brake_status", label))
917 // Get parking brake status
918 json_bool val = (this->crr_car_info.parking_brake_stt) ? TRUE : FALSE;
919 j_in = json_object_new_boolean(val);
921 else if (0 == strcmp("accelerator.pedal.position", label))
923 // Get accelerator pedal position
924 double val = this->crr_car_info.accel_pedal_pos;
925 j_in = json_object_new_double(val);
927 else if (0 == strcmp("car_state", label))
930 const char* val = (this->crr_car_info.running_stt) ? "run" : "stop";
931 j_in = json_object_new_string(val);
933 else if (0 == strcmp("lightstatus.brake", label)) {
934 // Get lightstatus brake status
935 json_bool val = (this->crr_car_info.lightstatus_brake_stt) ? TRUE : FALSE;
936 j_in = json_object_new_boolean(val);
940 return Err<json_object *>("Car info does not exist");
943 // Create output object
944 j_out = json_object_new_object();
945 json_object_object_add(j_out, "value", j_in);
947 return Ok<json_object *>(j_out);
950 void WindowManager::send_event(const string& evname)
952 HMI_DEBUG("%s: %s", __func__, evname.c_str());
954 int ret = afb_event_push(this->map_afb_event[evname], nullptr);
957 HMI_DEBUG("afb_event_push: %m");
961 void WindowManager::send_event(const string& evname, const string& role)
963 HMI_DEBUG("%s: %s(%s)", __func__, evname.c_str(), role.c_str());
965 json_object *j = json_object_new_object();
966 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
968 int ret = afb_event_push(this->map_afb_event[evname], j);
971 HMI_DEBUG("afb_event_push failed: %m");
975 void WindowManager::send_event(const string& evname, const string& role, const string& area,
976 int x, int y, int w, int h)
978 HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
979 __func__, evname.c_str(), role.c_str(), area.c_str(), x, y, w, h);
981 json_object *j_rect = json_object_new_object();
982 json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
983 json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
984 json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
985 json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
987 json_object *j = json_object_new_object();
988 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
989 json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
990 json_object_object_add(j, kKeyDrawingRect, j_rect);
992 int ret = afb_event_push(this->map_afb_event[evname], j);
995 HMI_DEBUG("afb_event_push failed: %m");
999 string WindowManager::searchApp(unsigned pid, unsigned ppid, unsigned surface, json_object* resp)
1001 // retrieve appid from pid from application manager
1003 // check appid then add it to the client
1004 HMI_INFO("Runners:%s", json_object_get_string(resp));
1005 int size = json_object_array_length(resp);
1006 HMI_INFO("pid %d, ppid %d, surface %d",pid, ppid, surface);
1007 for(int i = 0; i < size; i++)
1009 json_object *j = json_object_array_get_idx(resp, i);
1010 int runid = jh::getIntFromJson(j, "runid");
1011 const char* id = jh::getStringFromJson(j, "id");
1012 HMI_DEBUG("Appid %s, runid %d", id, runid);
1013 if(id && (runid == ppid))
1016 s_id.erase(s_id.find('@'));
1018 HMI_INFO("App found %s", appid.c_str());
1024 HMI_WARNING("Failed to retrieve id");
1029 void WindowManager::storeSurface(const string& appid, unsigned ppid, unsigned surface)
1031 auto elem = std::find_if(this->tmp_services.begin(), this->tmp_services.end(),
1032 [&appid](TmpService& ts){
1033 return (ts.dest == appid );
1036 this->lc->setXDGSurfaceOriginSize(surface);
1037 if(elem != this->tmp_services.end())
1040 auto client = g_app_list.lookUpClient(elem->dest);
1041 if(client == nullptr)
1045 HMI_INFO("Attach surface %d (service %s) to app %s", surface, elem->service.c_str(), elem->dest.c_str());
1046 client->attachServiceSurface(elem->service, surface);
1051 auto client = g_app_list.lookUpClient(appid);
1052 if(client != nullptr)
1054 client->addSurface(surface);
1055 this->id_alloc.register_name_id(client->role(), surface);
1059 // Store tmp surface and appid for application
1060 // who requests setRole after creating shell surface
1061 this->tmp_surface2app.emplace(surface, TmpClient{appid, ppid});
1069 void WindowManager::surface_created(unsigned pid, unsigned surface_id)
1072 if(this->tmp_surface2app.count(surface_id) != 0)
1074 string appid = this->tmp_surface2app[surface_id].appid;
1075 auto client = g_app_list.lookUpClient(appid);
1076 if(client != nullptr)
1078 WMError ret = client->addSurface(surface_id);
1079 HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
1080 if(ret != WMError::SUCCESS)
1082 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
1085 this->tmp_surface2app.erase(surface_id);
1089 HMI_NOTICE("Unknown surface %d", surface_id);
1091 std::ostringstream os;
1093 string path = "/proc/" + os.str() + "/stat";
1094 std::ifstream ifs(path.c_str());
1097 if(!ifs.fail() && std::getline(ifs, str))
1099 std::sscanf(str.data(), "%*d %*s %*c %d", &ppid);
1100 HMI_INFO("Retrieve ppid %d", ppid);
1104 HMI_ERROR("Failed to open /proc/%d/stat", pid);
1105 HMI_ERROR("File system may be different");
1108 struct AfbClosure* c = new struct AfbClosure(pid, ppid, surface_id);
1109 // search pid from surfaceID
1110 afb_service_call("afm-main", "runners", json_object_new_object(),
1111 [](void* closure, int stat, json_object* resp){
1112 HMI_DEBUG("check %s", json_object_get_string(resp));
1113 struct AfbClosure* c = static_cast<struct AfbClosure*>(closure);
1117 HMI_ERROR("Failed to call runners");
1122 json_object_object_get_ex(resp, "response", &j);
1123 string appid = g_context->searchApp(c->pid, c->ppid, c->surface, j);
1126 g_context->storeSurface(appid, c->ppid, c->surface);
1129 json_object_put(resp);
1135 void WindowManager::surface_removed(unsigned surface_id)
1137 HMI_DEBUG("Delete surface_id %u", surface_id);
1138 this->id_alloc.remove_id(surface_id);
1139 g_app_list.removeSurface(surface_id);
1142 void WindowManager::removeClient(const string &appid)
1144 HMI_DEBUG("Remove clinet %s from list", appid.c_str());
1145 auto client = g_app_list.lookUpClient(appid);
1146 this->lc->appTerminated(client);
1147 g_app_list.removeClient(appid);
1150 void WindowManager::exceptionProcessForTransition()
1152 unsigned req_num = g_app_list.currentRequestNumber();
1153 HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
1154 g_app_list.removeRequest(req_num);
1155 HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
1156 this->processNextRequest();
1159 void WindowManager::analyzeReceivedEvent(const char *event, struct json_object *object)
1161 HMI_DEBUG("event:%s", event);
1163 // If receive low can signal
1164 if (strstr(event, "low-can"))
1166 // Analyze low can signal
1167 const char *signal_name = this->lcc.analyzeCanSignal(object);
1169 // Create task for car state and input it to PolicyManager
1170 Task task = this->convertCanSignalToCarStateTask(signal_name);
1171 if (Task::TASK_INVALID != task)
1173 this->inputCarStateTask(task);
1178 void WindowManager::timerHandler()
1180 unsigned req_num = g_app_list.currentRequestNumber();
1181 HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
1182 g_app_list.reqDump();
1183 g_app_list.removeRequest(req_num);
1184 this->processNextRequest();
1187 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
1189 WMError ret = WMError::UNKNOWN;
1190 // req_num is guaranteed by Window Manager
1191 unsigned req_num = g_app_list.currentRequestNumber();
1192 Task task = Task::TASK_INVALID;
1194 if (actions.empty())
1196 if (g_app_list.haveRequest())
1198 HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
1199 goto proc_remove_request;
1203 HMI_SEQ_DEBUG(req_num, "There is no request");
1208 // Check weather there is the no request task
1209 // [The no request task]
1210 // - TaskCarState::RESTRICTION_MODE_OFF
1211 // - TaskCarState::RESTRICTION_MODE_ON
1212 for (const auto &act : actions)
1214 if (TaskCarState::RESTRICTION_MODE_OFF == act.car_state)
1216 task = Task::TASK_RESTRICTION_MODE_OFF;
1219 else if (TaskCarState::RESTRICTION_MODE_ON == act.car_state)
1221 task = Task::TASK_RESTRICTION_MODE_ON;
1226 // If there is the request-less task, set request here
1227 if (Task::TASK_INVALID != task) {
1229 ret = this->setRequest(task, &req_num);
1231 if(ret != WMError::SUCCESS)
1237 for (auto &act : actions)
1242 auto const &surface_id = this->id_alloc.lookup(act.role.c_str());
1243 if(surface_id == nullopt)
1245 HMI_SEQ_DEBUG(req_num, "There is not surface id for role:%s", act.role.c_str());
1249 string appid = g_app_list.getAppID(*surface_id, &found);
1252 if (TaskVisible::INVISIBLE == act.visible)
1254 HMI_SEQ_DEBUG(req_num, "role:%s is killed, so do not set this action", act.role.c_str());
1259 HMI_SEQ_ERROR(req_num, "appid of role:%s which is visible is not found", act.role.c_str());
1260 ret = WMError::FAIL;
1264 auto client = g_app_list.lookUpClient(appid);
1265 act.req_num = req_num;
1266 act.client = client;
1268 // If Window Manager is master and this action is for slave,
1269 // change TaskVisible
1270 if (this->wmcon.isMasterMode())
1272 if (this->wmcon.isMasterArea(act.area.c_str()))
1274 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_VISIBLE");
1275 act.visible = TaskVisible::REQ_REMOTE_VISIBLE;
1277 // TODO: Check whether role is tbtnavi to request remote invisible
1278 else if (("tbtnavi" == act.role) &&
1279 (TaskVisible::INVISIBLE == act.visible))
1281 HMI_DEBUG("Set TaskVisible::REQ_REMOTE_INVISIBLE");
1282 act.visible = TaskVisible::REQ_REMOTE_INVISIBLE;
1287 ret = g_app_list.setAction(req_num, act);
1288 if (ret != WMError::SUCCESS)
1290 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1295 HMI_SEQ_DEBUG(req_num, "Start transition.");
1296 ret = this->startTransition(req_num);
1297 if (ret != WMError::SUCCESS)
1299 if (ret == WMError::NO_LAYOUT_CHANGE)
1301 goto proc_remove_request;
1305 HMI_SEQ_ERROR(req_num, "Transition state is failed");
1313 //this->emit_error()
1314 HMI_SEQ_ERROR(req_num, errorDescription(ret));
1315 this->pmw.undoState();
1317 proc_remove_request:
1318 g_app_list.removeRequest(req_num);
1319 this->processNextRequest();
1322 void WindowManager::processError(WMError error)
1324 unsigned req_num = g_app_list.currentRequestNumber();
1326 //this->emit_error()
1327 HMI_SEQ_ERROR(req_num, errorDescription(error));
1328 g_app_list.removeRequest(req_num);
1329 this->processNextRequest();
1332 void WindowManager::processForRemoteRequest(json_object *data)
1334 const char *req = jh::getStringFromJson(data, "req");
1335 const char *appid = jh::getStringFromJson(data, "appid");
1336 const char *drawing_name = jh::getStringFromJson(data, "drawing_name");
1337 const char *drawing_area = jh::getStringFromJson(data, "drawing_area");
1338 string request = req;
1339 string role = drawing_name;
1340 string area = drawing_area;
1342 if (!req || !drawing_name)
1344 HMI_ERROR("Parse Error!!");
1348 if (this->wmcon.isMasterMode())
1352 HMI_ERROR("Parse Error!!");
1356 auto reply = [](const char *errmsg) {
1357 if (errmsg != nullptr)
1364 if ("activateWindow" == request)
1368 HMI_ERROR("Parse Error!!");
1372 this->api_activate_surface_for_slave(
1373 appid, drawing_name, drawing_area, reply);
1375 else if ("deactivateWindow" == request)
1377 this->api_deactivate_surface_for_slave(
1378 appid, drawing_name, reply);
1380 else if ("endDraw" == request)
1382 this->api_enddraw(appid, drawing_name);
1387 if ("syncDraw" == request)
1391 if (!appid || !drawing_area)
1393 HMI_ERROR("Parse Error!!");
1397 unsigned req_num = g_app_list.currentRequestNumber();
1398 auto client = g_app_list.lookUpClient(appid);
1400 // TODO: application requests by old role,
1401 // so convert role old to new
1402 const char *c_role = this->convertRoleOldToNew(drawing_name);
1405 bool end_draw_finished = false;
1412 TaskVisible::REMOTE_VISIBLE,
1414 TaskCarState::NO_TASK
1418 WMError ret = g_app_list.setAction(req_num, act);
1419 if (ret != WMError::SUCCESS)
1421 HMI_SEQ_ERROR(req_num, "Setting action is failed");
1425 this->emit_syncdraw(role, area);
1426 this->wmcon.startSyncDrawForRemote(appid);
1429 else if ("activated" == request)
1431 this->emit_visible(role);
1432 this->emit_activated(area);
1434 else if ("deactivated" == request)
1438 if (!appid || !drawing_area)
1440 HMI_ERROR("Parse Error!!");
1444 unsigned req_num = g_app_list.currentRequestNumber();
1445 auto client = g_app_list.lookUpClient(appid);
1447 // TODO: application requests by old role,
1448 // so convert role old to new
1449 const char *c_role = this->convertRoleOldToNew(drawing_name);
1452 bool end_draw_finished = true;
1459 TaskVisible::REMOTE_INVISIBLE,
1461 TaskCarState::NO_TASK
1464 this->lc->visibilityChange(act);
1465 this->lc->renderLayers();
1466 this->lc->renderLayersRemote();
1468 this->emit_invisible(role);
1469 this->emit_deactivated(role);
1470 this->emitScreenUpdated(req_num);
1472 g_app_list.removeRequest(req_num);
1473 this->processNextRequest();
1475 else if ("flushDraw" == request)
1477 this->emit_flushdraw(role);
1483 ******* Private Functions *******
1486 void WindowManager::emit_activated(const string& role)
1488 this->send_event(kListEventName[Event_Active], role);
1491 void WindowManager::emit_deactivated(const string& role)
1493 this->send_event(kListEventName[Event_Inactive], role);
1496 void WindowManager::emit_syncdraw(const string& role, char const *area, int x, int y, int w, int h)
1498 this->send_event(kListEventName[Event_SyncDraw], role, area, x, y, w, h);
1501 void WindowManager::emit_syncdraw(const string &role, const string &area)
1503 struct rect rect = this->lc->getAreaSize(area);
1504 this->send_event(kListEventName[Event_SyncDraw],
1505 role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
1508 void WindowManager::emit_flushdraw(const string& role)
1510 this->send_event(kListEventName[Event_FlushDraw], role);
1513 void WindowManager::emit_visible(const string& role, bool is_visible)
1515 this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], role);
1518 void WindowManager::emit_invisible(const string& role)
1520 return emit_visible(role, false);
1523 void WindowManager::emit_visible(const string& role) { return emit_visible(role, true); }
1525 void WindowManager::emitHeadlampOff()
1527 // Send HeadlampOff event for all application
1528 this->send_event(kListEventName[Event_HeadlampOff]);
1531 void WindowManager::emitHeadlampOn()
1533 // Send HeadlampOn event for all application
1534 this->send_event(kListEventName[Event_HeadlampOn]);
1537 void WindowManager::emitParkingBrakeOff()
1539 // Send ParkingBrakeOff event for all application
1540 this->send_event(kListEventName[Event_ParkingBrakeOff]);
1543 void WindowManager::emitParkingBrakeOn()
1545 // Send ParkingBrakeOn event for all application
1546 this->send_event(kListEventName[Event_ParkingBrakeOn]);
1549 void WindowManager::emitLightstatusBrakeOff()
1551 // Send LightstatusBrakeOff event for all application
1552 this->send_event(kListEventName[Event_LightstatusBrakeOff]);
1555 void WindowManager::emitLightstatusBrakeOn()
1557 // Send LightstatusBrakeOn event for all application
1558 this->send_event(kListEventName[Event_LightstatusBrakeOn]);
1561 void WindowManager::emitCarStop()
1563 // Send CarStop event for all application
1564 this->send_event(kListEventName[Event_CarStop]);
1567 void WindowManager::emitCarRun()
1569 // Send CarRun event for all application
1570 this->send_event(kListEventName[Event_CarRun]);
1573 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
1574 Task task, unsigned* req_num)
1576 if (!g_app_list.contains(appid))
1578 return WMError::NOT_REGISTERED;
1581 auto client = g_app_list.lookUpClient(appid);
1586 unsigned current = g_app_list.currentRequestNumber();
1587 unsigned requested_num = g_app_list.getRequestNumber(appid);
1588 if (requested_num != 0)
1590 HMI_SEQ_INFO(requested_num,
1591 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1592 return REQ_REJECTED;
1595 WMRequest req = WMRequest(appid, role, area, task);
1596 unsigned new_req = g_app_list.addRequest(req);
1598 g_app_list.reqDump();
1600 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1602 return WMError::SUCCESS;
1605 WMError WindowManager::setRequest(Task task, unsigned* req_num)
1610 unsigned current = g_app_list.currentRequestNumber();
1612 WMRequest req = WMRequest(task);
1613 unsigned new_req = g_app_list.addRequest(req);
1615 g_app_list.reqDump();
1617 HMI_SEQ_DEBUG(current, "start sequence for task:%d", task);
1619 return WMError::SUCCESS;
1622 WMError WindowManager::setRequestForSlave(const string& appid, const string &role, const string &area,
1623 Task task, unsigned* req_num)
1628 unsigned current = g_app_list.currentRequestNumber();
1629 unsigned requested_num = g_app_list.getRequestNumber(appid);
1630 if (requested_num != 0)
1632 HMI_SEQ_INFO(requested_num,
1633 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
1634 return REQ_REJECTED;
1637 WMRequest req = WMRequest(appid, role, area, task);
1638 unsigned new_req = g_app_list.addRequest(req);
1640 g_app_list.reqDump();
1642 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
1644 return WMError::SUCCESS;
1647 WMError WindowManager::checkPolicy(unsigned req_num)
1652 // get current trigger
1654 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1655 auto trigger = g_app_list.getRequest(req_num, &found);
1658 ret = WMError::NO_ENTRY;
1661 string req_area = trigger.area;
1663 if (trigger.task == Task::TASK_ALLOCATE)
1665 const char *msg = this->check_surface_exist(trigger.role.c_str());
1669 HMI_SEQ_ERROR(req_num, msg);
1674 // Input event data to PolicyManager
1675 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1677 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1681 // Execute state transition of PolicyManager
1682 if (0 > this->pmw.executeStateTransition())
1684 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1688 ret = WMError::SUCCESS;
1690 g_app_list.reqDump();
1695 WMError WindowManager::checkPolicyForSlave(unsigned req_num)
1700 // get current trigger
1702 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
1703 auto trigger = g_app_list.getRequest(req_num, &found);
1706 ret = WMError::NO_ENTRY;
1709 string req_area = trigger.area;
1711 // Input event data to PolicyManager
1712 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
1714 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
1718 // Execute state transition of PolicyManager
1719 if (0 > this->pmw.executeStateTransition())
1721 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
1725 ret = WMError::SUCCESS;
1727 g_app_list.reqDump();
1732 WMError WindowManager::startTransition(unsigned req_num)
1734 bool sync_draw_happen = false;
1736 WMError ret = WMError::SUCCESS;
1737 auto actions = g_app_list.getActions(req_num, &found);
1740 ret = WMError::NO_ENTRY;
1741 HMI_SEQ_ERROR(req_num,
1742 "Window Manager bug :%s : Action is not set", errorDescription(ret));
1746 g_app_list.reqDump();
1747 for (const auto &action : actions)
1749 // TODO: application requests by old role,
1750 // so convert role new to old for emitting event
1751 string old_role = this->rolenew2old[action.role];
1753 if (action.visible == TaskVisible::VISIBLE)
1755 sync_draw_happen = true;
1757 this->emit_syncdraw(old_role, action.area);
1758 /* TODO: emit event for app not subscriber
1759 if(g_app_list.contains(y.appid))
1760 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
1762 else if(action.visible == TaskVisible::REQ_REMOTE_VISIBLE)
1764 // If this action is for slave, send to slave
1765 this->wmcon.sendRequest("syncDraw", action.client->appID().c_str(),
1766 old_role.c_str(), action.area.c_str());
1768 else if (action.car_state != TaskCarState::NO_TASK)
1770 this->transitionCarState(action.car_state);
1774 if (sync_draw_happen)
1780 // deactivate only, no syncDraw
1781 // Make it deactivate here
1782 for (const auto &x : actions)
1784 this->lc->visibilityChange(x);
1785 string old_role = this->rolenew2old[x.role];
1787 if (x.visible == TaskVisible::INVISIBLE)
1789 emit_deactivated(old_role);
1791 else if (x.visible == TaskVisible::REQ_REMOTE_INVISIBLE)
1793 // If this action is for slave, send to slave
1794 int i_ret = this->wmcon.sendRequest("deactivated", x.client->appID().c_str(),
1795 old_role.c_str(), "");
1798 ret = WMError::FAIL;
1802 /* if (g_app_list.contains(x.appid))
1804 auto client = g_app_list.lookUpClient(x.appid);
1805 //this->deactivate(client->surfaceID(x.role));
1808 this->lc->renderLayers();
1809 this->lc->renderLayersRemote();
1810 ret = WMError::NO_LAYOUT_CHANGE;
1815 void WindowManager::transitionCarState(TaskCarState task)
1817 if (TaskCarState::PARKING_BRAKE_OFF == task)
1819 this->crr_car_info.parking_brake_stt = false;
1820 this->emitParkingBrakeOff();
1822 else if (TaskCarState::PARKING_BRAKE_ON == task)
1824 this->crr_car_info.parking_brake_stt = true;
1825 this->emitParkingBrakeOn();
1827 else if (TaskCarState::ACCEL_PEDAL_OFF == task)
1829 this->crr_car_info.accel_pedal_stt = false;
1831 else if (TaskCarState::ACCEL_PEDAL_ON == task)
1833 this->crr_car_info.accel_pedal_stt = true;
1835 else if (TaskCarState::HEDLAMP_OFF == task)
1837 this->crr_car_info.headlamp_stt = false;
1838 this->emitHeadlampOff();
1840 else if (TaskCarState::HEDLAMP_ON == task)
1842 this->crr_car_info.headlamp_stt = true;
1843 this->emitHeadlampOn();
1845 else if (TaskCarState::LIGHTSTATUS_BRAKE_OFF == task)
1847 this->crr_car_info.lightstatus_brake_stt = false;
1848 this->emitLightstatusBrakeOff();
1850 else if (TaskCarState::LIGHTSTATUS_BRAKE_ON == task)
1852 this->crr_car_info.lightstatus_brake_stt = true;
1853 this->emitLightstatusBrakeOn();
1855 else if (TaskCarState::CAR_STOP == task)
1857 this->crr_car_info.running_stt = false;
1858 this->emitCarStop();
1860 else if (TaskCarState::CAR_RUN == task)
1862 this->crr_car_info.running_stt = true;
1867 WMError WindowManager::doEndDraw(unsigned req_num)
1871 bool trigger_homescreen = false;
1872 auto actions = g_app_list.getActions(req_num, &found);
1873 WMError ret = WMError::SUCCESS;
1876 ret = WMError::NO_ENTRY;
1879 auto trigger = g_app_list.getRequest(req_num, &found);
1880 HMI_SEQ_INFO(req_num, "trigger.role = %s", trigger.role.c_str());
1882 if(trigger.role == "homescreen")
1884 trigger_homescreen = true;
1887 HMI_SEQ_INFO(req_num, "do endDraw");
1889 // layout change and make it visible
1890 for (const auto &act : actions)
1892 if(act.visible != TaskVisible::NO_CHANGE)
1895 ret = this->lc->layoutChange(act);
1896 if(ret != WMError::SUCCESS)
1898 HMI_SEQ_WARNING(req_num,
1899 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1903 if(trigger_homescreen && (act.visible == TaskVisible::INVISIBLE))
1905 HMI_SEQ_NOTICE(req_num, "don't change visible if homescreen role is trigger");
1909 ret = this->lc->visibilityChange(act);
1912 // Emit active/deactive event
1913 string old_role = this->rolenew2old[act.role];
1916 case TaskVisible::VISIBLE :
1917 emit_visible(old_role);
1918 emit_activated(old_role);
1920 case TaskVisible::REQ_REMOTE_VISIBLE :
1922 // If this action is for slave, send to slave
1923 int i_ret = this->wmcon.sendRequest("activated", "", old_role.c_str(), "");
1926 ret = WMError::FAIL;
1930 case TaskVisible::INVISIBLE :
1931 if(!trigger_homescreen)
1933 emit_invisible(old_role);
1934 emit_deactivated(old_role);
1938 // TaskVisible::REMOTE_VISIBLE, TaskVisible::REMOTE_INVISIBLE is this case
1939 // If this action is for slave, send to slave
1943 if (ret != WMError::SUCCESS)
1945 HMI_SEQ_WARNING(req_num,
1946 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1949 HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
1952 this->lc->renderLayers();
1953 this->lc->renderLayersRemote();
1955 HMI_SEQ_INFO(req_num, "emit flushDraw");
1957 for(const auto &act_flush : actions)
1959 // TODO: application requests by old role,
1960 // so convert role new to old for emitting event
1961 string old_role = this->rolenew2old[act_flush.role];
1963 if(act_flush.visible == TaskVisible::VISIBLE)
1965 this->emit_flushdraw(old_role);
1967 else if(act_flush.visible == TaskVisible::REQ_REMOTE_VISIBLE)
1969 // If this action is for slave, send to slave
1970 this->wmcon.sendRequest("flushDraw", "", old_role.c_str(), "");
1977 void WindowManager::emitScreenUpdated(unsigned req_num)
1980 HMI_SEQ_DEBUG(req_num, "emit screen updated");
1982 auto actions = g_app_list.getActions(req_num, &found);
1985 // create json object
1986 json_object *j = json_object_new_object();
1987 json_object *jarray = json_object_new_array();
1989 for(const auto& action: actions)
1991 if((action.visible == TaskVisible::VISIBLE) ||
1992 (action.visible == TaskVisible::REMOTE_VISIBLE))
1994 json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
1997 json_object_object_add(j, kKeyIds, jarray);
1998 HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
2000 int ret = afb_event_push(
2001 this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
2004 HMI_DEBUG("afb_event_push failed: %m");
2008 void WindowManager::setTimer()
2011 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
2012 HMI_ERROR("Could't set time (clock_gettime() returns with error");
2016 HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
2017 if (g_timer_ev_src == nullptr)
2019 // firsttime set into sd_event
2020 int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
2021 CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
2024 HMI_ERROR("Could't set timer");
2029 // update timer limitation after second time
2030 sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
2031 sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
2035 void WindowManager::stopTimer()
2037 unsigned req_num = g_app_list.currentRequestNumber();
2038 HMI_SEQ_DEBUG(req_num, "Timer stop");
2039 int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
2042 HMI_SEQ_ERROR(req_num, "Timer stop failed");
2046 void WindowManager::processNextRequest()
2049 g_app_list.reqDump();
2050 unsigned req_num = g_app_list.currentRequestNumber();
2051 if (g_app_list.haveRequest())
2053 HMI_SEQ_DEBUG(req_num, "Process next request");
2054 WMError rc = checkPolicy(req_num);
2055 if (rc != WMError::SUCCESS)
2057 HMI_SEQ_ERROR(req_num, errorDescription(rc));
2062 HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
2066 const char* WindowManager::convertRoleOldToNew(char const *old_role)
2068 const char *new_role = nullptr;
2070 for (auto const &on : this->roleold2new)
2072 std::regex regex = std::regex(on.first);
2073 if (std::regex_match(old_role, regex))
2075 // role is old. So convert to new.
2076 new_role = on.second.c_str();
2081 if (nullptr == new_role)
2083 // role is new or fallback.
2084 new_role = old_role;
2087 HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
2092 int WindowManager::loadOldRolesConfigFile()
2094 // Get afm application installed dir
2095 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
2096 HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
2099 if (!afm_app_install_dir)
2101 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
2105 file_name = string(afm_app_install_dir) + string(kPathOldRolesConfigFile);
2108 // Load old_rolea config file
2109 json_object* json_obj;
2110 int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
2113 HMI_ERROR("Could not open %s, so use default old_roles information", kPathOldRolesConfigFile);
2114 json_obj = json_tokener_parse(kDefaultOldRolesConfig);
2116 HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
2119 json_object* json_cfg;
2120 if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
2122 HMI_ERROR("Parse Error!!");
2126 int len = json_object_array_length(json_cfg);
2127 HMI_DEBUG("json_cfg len:%d", len);
2128 HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
2130 for (int i=0; i<len; i++)
2132 json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
2134 const char* old_role = jh::getStringFromJson(json_tmp, "name");
2135 if (nullptr == old_role)
2137 HMI_ERROR("Parse Error!!");
2141 const char* new_role = jh::getStringFromJson(json_tmp, "new");
2142 if (nullptr == new_role)
2144 HMI_ERROR("Parse Error!!");
2148 this->roleold2new[old_role] = string(new_role);
2152 for(auto itr = this->roleold2new.begin();
2153 itr != this->roleold2new.end(); ++itr)
2155 HMI_DEBUG(">>> role old:%s new:%s",
2156 itr->first.c_str(), itr->second.c_str());
2159 // Release json_object
2160 json_object_put(json_obj);
2165 Task WindowManager::convertCanSignalToCarStateTask(const char *signal_name)
2167 wm::LowCanClient *lcc = &(this->lcc);
2168 Task task = Task::TASK_INVALID;
2170 // If car info is updated, set car state change event
2171 if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoParkingBrake]))
2173 HMI_DEBUG("Parking Brake state is changed");
2175 if (lcc->getCurrentParkingBrakeState())
2177 task = wm::Task::TASK_PARKING_BRAKE_ON;
2181 task = wm::Task::TASK_PARKING_BRAKE_OFF;
2184 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoAccelPedalPos]))
2186 // Update accel pedal position
2187 this->crr_car_info.accel_pedal_pos = lcc->getCurrentAccelPedalPosition();
2189 if (lcc->isChangedAccelPedalState())
2191 HMI_DEBUG("Accelerator Pedal state is changed");
2193 if (lcc->getCurrentAccelPedalState())
2195 task = wm::Task::TASK_ACCEL_PEDAL_ON;
2199 task = wm::Task::TASK_ACCEL_PEDAL_OFF;
2203 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoHeadlame]))
2205 HMI_DEBUG("Headlamp state is changed");
2207 if (lcc->getCurrentHeadlampState())
2209 task = wm::Task::TASK_HEDLAMP_ON;
2213 task = wm::Task::TASK_HEDLAMP_OFF;
2216 else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoLightstatusBrake]))
2218 HMI_DEBUG("Lightstatus Brake state is changed");
2220 if (lcc->getCurrentLightstatusBrakeState())
2222 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_ON;
2226 task = wm::Task::TASK_LIGHTSTATUS_BRAKE_OFF;
2232 void WindowManager::inputCarStateTask(Task task)
2234 unsigned req_num = 0;
2235 WMError ret = WMError::UNKNOWN;
2237 ret = this->setRequest(task, &req_num);
2239 if(ret != WMError::SUCCESS)
2241 HMI_ERROR(errorDescription(ret));
2245 if (req_num != g_app_list.currentRequestNumber())
2247 // Add request, then invoked after the previous task is finished
2248 HMI_SEQ_DEBUG(req_num, "request is accepted");
2255 ret = this->checkPolicy(req_num);
2257 if (ret != WMError::SUCCESS)
2259 //this->emit_error()
2260 HMI_SEQ_ERROR(req_num, errorDescription(ret));
2261 g_app_list.removeRequest(req_num);
2262 this->processNextRequest();
2266 const char *WindowManager::check_surface_exist(const char *drawing_name)
2268 auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
2271 return "Surface does not exist";
2274 /* if (!this->controller->surface_exists(*surface_id))
2276 return "Surface does not exist in controller!";
2279 /* auto layer_id = this->layers.get_layer_id(*surface_id);
2283 return "Surface is not on any layer!";
2286 HMI_DEBUG("surface %d is detected", *surface_id);
2290 const char* WindowManager::kDefaultOldRolesConfig = "{ \
2293 \"name\": \"HomeScreen\", \
2294 \"new\": \"homescreen\" \
2297 \"name\": \"Music\", \
2298 \"new\": \"music\" \
2301 \"name\": \"MediaPlayer\", \
2302 \"new\": \"music\" \
2305 \"name\": \"Video\", \
2306 \"new\": \"video\" \
2309 \"name\": \"VideoPlayer\", \
2310 \"new\": \"video\" \
2313 \"name\": \"WebBrowser\", \
2314 \"new\": \"browser\" \
2317 \"name\": \"Radio\", \
2318 \"new\": \"radio\" \
2321 \"name\": \"Phone\", \
2322 \"new\": \"phone\" \
2325 \"name\": \"Navigation\", \
2329 \"name\": \"HVAC\", \
2333 \"name\": \"Settings\", \
2334 \"new\": \"settings\" \
2337 \"name\": \"Dashboard\", \
2338 \"new\": \"dashboard\" \
2341 \"name\": \"POI\", \
2345 \"name\": \"Mixer\", \
2346 \"new\": \"mixer\" \
2349 \"name\": \"Restriction\", \
2350 \"new\": \"restriction\" \
2353 \"name\": \"^OnScreen.*\", \
2354 \"new\": \"on_screen\" \