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.
20 #include "window_manager.hpp"
21 #include "json_helper.hpp"
22 #include "applist.hpp"
26 #include <systemd/sd-event.h>
35 static const uint64_t kTimeOut = 3ULL; /* 3s */
37 /* DrawingArea name used by "{layout}.{area}" */
38 const char kNameLayoutNormal[] = "normal";
39 const char kNameLayoutSplit[] = "split";
40 const char kNameAreaFull[] = "full";
41 const char kNameAreaMain[] = "main";
42 const char kNameAreaSub[] = "sub";
44 /* Key for json obejct */
45 const char kKeyDrawingName[] = "drawing_name";
46 const char kKeyDrawingArea[] = "drawing_area";
47 const char kKeyDrawingRect[] = "drawing_rect";
48 const char kKeyX[] = "x";
49 const char kKeyY[] = "y";
50 const char kKeyWidth[] = "width";
51 const char kKeyHeight[] = "height";
52 const char kKeyWidthPixel[] = "width_pixel";
53 const char kKeyHeightPixel[] = "height_pixel";
54 const char kKeyWidthMm[] = "width_mm";
55 const char kKeyHeightMm[] = "height_mm";
56 const char kKeyScale[] = "scale";
57 const char kKeyIds[] = "ids";
59 static const vector<string> kListEventName{
69 static sd_event_source *g_timer_ev_src = nullptr;
70 static AppList g_app_list;
71 static WindowManager *g_context;
76 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
78 HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
79 reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
83 static void onStateTransitioned(vector<WMAction> actions)
85 g_context->startTransitionWrapper(actions);
90 g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
97 WindowManager::WindowManager()
100 const char *path = getenv("AFM_APP_INSTALL_DIR");
103 HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
107 this->lc = std::make_shared<LayerControl>(root);
109 HMI_DEBUG("Layer Controller initialized");
112 int WindowManager::init()
114 LayerControlCallbacks lmcb;
115 lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
116 this->surface_created(surface);
118 lmcb.surfaceDestroyed = [&](unsigned surface){
119 this->surface_removed(surface);
122 if(this->lc->init(lmcb) != WMError::SUCCESS)
127 // Store my context for calling callback from PolicyManager
130 // Initialize PMWrapper
131 this->pmw.initialize();
133 // Register callback to PolicyManager
134 this->pmw.registerCallback(onStateTransitioned, onError);
137 for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
139 map_afb_event[kListEventName[i]] = afb_api_make_event(afbBindingV3root, kListEventName[i].c_str());
142 const struct rect css_bg = this->lc->getAreaSize("fullscreen");
143 Screen screen = this->lc->getScreenInfo();
144 rectangle dp_bg(screen.width(), screen.height());
146 dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
147 dp_bg.fit(screen.width(), screen.height());
148 dp_bg.center(screen.width(), screen.height());
149 HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
150 css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
152 double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
153 this->lc->setupArea(dp_bg, scale);
158 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
160 string str_id = appid;
161 string role = drawing_name;
164 if(!g_app_list.contains(str_id))
166 lid = this->lc->getNewLayerID(role);
169 // register drawing_name as fallback and make it displayed.
170 lid = this->lc->getNewLayerID(string("fallback"));
171 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
174 return Err<int>("Designated role does not match any role, fallback is disabled");
177 this->lc->createNewLayer(lid);
178 // add client into the db
179 g_app_list.addClient(str_id, lid, role);
182 // generate surface ID for ivi-shell application
183 auto rname = this->id_alloc.lookup(role);
186 // name does not exist yet, allocate surface id...
187 auto id = int(this->id_alloc.generate_id(role));
188 this->tmp_surface2app[id] = {str_id, lid};
190 // POI: AGL LifeCycle Management
191 this->amgr.states[str_id] = lcm::CREATED;
192 this->amgr.emit_activity_status_changed(str_id.c_str(),
193 this->amgr.states_s[lcm::CREATED]);
198 // Check currently registered drawing names if it is already there.
199 return Err<int>("Surface already present");
202 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
205 string str_id = appid;
206 string role = drawing_name;
208 unsigned sid = std::stol(ivi_id);
209 HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
211 * IVI-shell doesn't send surface_size event via ivi-wm protocol
212 * if the application is using XDG surface.
213 * So WM has to set surface size with original size here
215 WMError ret = this->lc->setXDGSurfaceOriginSize(sid);
218 HMI_ERROR("%s", errorDescription(ret));
219 HMI_WARNING("The main user of this API is runXDG");
223 if(!g_app_list.contains(str_id))
225 unsigned l_id = this->lc->getNewLayerID(role);
228 // register drawing_name as fallback and make it displayed.
229 l_id = this->lc->getNewLayerID("fallback");
230 HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
233 return "Designated role does not match any role, fallback is disabled";
236 this->lc->createNewLayer(l_id);
237 // add client into the db
238 g_app_list.addClient(str_id, l_id, role);
241 auto rname = this->id_alloc.lookup(role);
245 return "Surface already present";
248 // register pair drawing_name and ivi_id
249 this->id_alloc.register_name_id(role, sid);
251 auto client = g_app_list.lookUpClient(str_id);
252 client->addSurface(sid);
254 // POI: AGL LifeCycle Management
255 this->amgr.states[str_id] = lcm::CREATED;
256 this->amgr.emit_activity_status_changed(str_id.c_str(),
257 this->amgr.states_s[lcm::CREATED]);
262 void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
263 char const *drawing_area, const reply_func &reply)
266 string role = drawing_name;
267 string area = drawing_area;
269 if(!g_app_list.contains(id))
271 reply("app doesn't request 'requestSurface' or 'setRole' yet");
274 auto client = g_app_list.lookUpClient(id);
276 Task task = Task::TASK_ALLOCATE;
277 unsigned req_num = 0;
278 WMError ret = WMError::UNKNOWN;
280 ret = this->setRequest(id, role, area, task, &req_num);
282 if(ret != WMError::SUCCESS)
284 HMI_ERROR(errorDescription(ret));
285 reply("Failed to set request");
290 if (req_num != g_app_list.currentRequestNumber())
292 // Add request, then invoked after the previous task is finished
293 HMI_SEQ_DEBUG(req_num, "request is accepted");
299 ret = this->checkPolicy(req_num);
301 if (ret != WMError::SUCCESS)
304 HMI_SEQ_ERROR(req_num, errorDescription(ret));
305 g_app_list.removeRequest(req_num);
306 this->processNextRequest();
308 // POI: AGL LifeCycle Management
309 if (this->amgr.states[id] == lcm::CREATED) {
310 this->amgr.states[id] = lcm::STARTED;
311 this->amgr.emit_activity_status_changed(id.c_str(),
312 this->amgr.states_s[lcm::STARTED]);
317 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
318 const reply_func &reply)
322 string role = drawing_name;
323 string area = ""; //drawing_area;
324 Task task = Task::TASK_RELEASE;
325 unsigned req_num = 0;
326 WMError ret = WMError::UNKNOWN;
328 ret = this->setRequest(id, role, area, task, &req_num);
330 if (ret != WMError::SUCCESS)
332 HMI_ERROR(errorDescription(ret));
333 reply("Failed to set request");
338 if (req_num != g_app_list.currentRequestNumber())
340 // Add request, then invoked after the previous task is finished
341 HMI_SEQ_DEBUG(req_num, "request is accepted");
346 ret = this->checkPolicy(req_num);
348 if (ret != WMError::SUCCESS)
351 HMI_SEQ_ERROR(req_num, errorDescription(ret));
352 g_app_list.removeRequest(req_num);
353 this->processNextRequest();
355 // POI: AGL LifeCycle Management
356 int state = this->amgr.states[id];
357 if (state == lcm::STARTED || state == lcm::BACKGROUND) {
358 this->amgr.states[id] = lcm::STOPPED;
359 this->amgr.emit_activity_status_changed(id.c_str(),
360 this->amgr.states_s[lcm::STOPPED]);
365 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
368 string role = drawing_name;
369 unsigned current_req = g_app_list.currentRequestNumber();
370 bool result = g_app_list.setEndDrawFinished(current_req, id, role);
374 HMI_ERROR("%s is not in transition state", id.c_str());
378 if (g_app_list.endDrawFullfilled(current_req))
380 // do task for endDraw
382 WMError ret = this->doEndDraw(current_req);
384 if(ret != WMError::SUCCESS)
386 //this->emit_error();
388 // Undo state of PolicyManager
389 this->pmw.undoState();
390 this->lc->undoUpdate();
392 this->emitScreenUpdated(current_req);
393 HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
395 g_app_list.removeRequest(current_req);
397 this->processNextRequest();
401 HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
406 int WindowManager::api_subscribe(afb_req_t req, int event_id)
408 afb_event_t event = this->map_afb_event[kListEventName[event_id]];
409 return afb_req_subscribe(req, event);
412 result<json_object *> WindowManager::api_get_display_info()
414 Screen screen = this->lc->getScreenInfo();
416 json_object *object = json_object_new_object();
417 json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
418 json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
420 json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
421 json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
422 json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
424 return Ok<json_object *>(object);
427 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
431 string role = drawing_name;
433 // Check drawing name, surface/layer id
434 auto const &surface_id = this->id_alloc.lookup(role);
437 return Err<json_object *>("Surface does not exist");
440 // Set area rectangle
441 struct rect area_info = this->area_info[*surface_id];
442 json_object *object = json_object_new_object();
443 json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
444 json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
445 json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
446 json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
448 return Ok<json_object *>(object);
451 void WindowManager::send_event(const string& evname, const string& role)
453 json_object *j = json_object_new_object();
454 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
456 int ret = afb_event_push(this->map_afb_event[evname], j);
459 HMI_DEBUG("afb_event_push failed: %m");
463 void WindowManager::send_event(const string& evname, const string& role, const string& area,
464 int x, int y, int w, int h)
466 json_object *j_rect = json_object_new_object();
467 json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
468 json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
469 json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
470 json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
472 json_object *j = json_object_new_object();
473 json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
474 json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
475 json_object_object_add(j, kKeyDrawingRect, j_rect);
477 int ret = afb_event_push(this->map_afb_event[evname], j);
480 HMI_DEBUG("afb_event_push failed: %m");
487 void WindowManager::surface_created(unsigned surface_id)
490 if(this->tmp_surface2app.count(surface_id) != 0)
492 string appid = this->tmp_surface2app[surface_id].appid;
493 auto client = g_app_list.lookUpClient(appid);
494 if(client != nullptr)
496 WMError ret = client->addSurface(surface_id);
497 HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
498 if(ret != WMError::SUCCESS)
500 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
503 this->tmp_surface2app.erase(surface_id);
507 void WindowManager::surface_removed(unsigned surface_id)
509 HMI_DEBUG("Delete surface_id %u", surface_id);
510 this->id_alloc.remove_id(surface_id);
511 g_app_list.removeSurface(surface_id);
514 void WindowManager::removeClient(const string &appid)
516 HMI_DEBUG("Remove clinet %s from list", appid.c_str());
517 auto client = g_app_list.lookUpClient(appid);
518 this->lc->appTerminated(client);
519 g_app_list.removeClient(appid);
520 // POI: AGL LifeCycle Management
521 if (this->amgr.states[appid] != lcm::DESTROYED) {
522 this->amgr.states[appid] = lcm::DESTROYED;
523 this->amgr.emit_activity_status_changed(appid.c_str(),
524 this->amgr.states_s[lcm::DESTROYED]);
528 void WindowManager::exceptionProcessForTransition()
530 unsigned req_num = g_app_list.currentRequestNumber();
531 HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
532 g_app_list.removeRequest(req_num);
533 HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
534 this->processNextRequest();
537 void WindowManager::timerHandler()
539 unsigned req_num = g_app_list.currentRequestNumber();
540 HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
541 g_app_list.reqDump();
542 g_app_list.removeRequest(req_num);
543 this->processNextRequest();
546 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
549 unsigned req_num = g_app_list.currentRequestNumber();
553 if (g_app_list.haveRequest())
555 HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
556 goto proc_remove_request;
560 HMI_SEQ_DEBUG(req_num, "There is no request");
565 for (auto &act : actions)
570 auto const &surface_id = this->id_alloc.lookup(act.role);
571 if(surface_id == nullopt)
573 goto proc_remove_request;
575 string appid = g_app_list.getAppID(*surface_id, &found);
578 if (TaskVisible::INVISIBLE == act.visible)
580 // App is killed, so do not set this action
585 HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
590 auto client = g_app_list.lookUpClient(appid);
591 act.req_num = req_num;
595 ret = g_app_list.setAction(req_num, act);
596 if (ret != WMError::SUCCESS)
598 HMI_SEQ_ERROR(req_num, "Setting action is failed");
603 HMI_SEQ_DEBUG(req_num, "Start transition.");
604 ret = this->startTransition(req_num);
605 if (ret != WMError::SUCCESS)
607 if (ret == WMError::NO_LAYOUT_CHANGE)
609 goto proc_remove_request;
613 HMI_SEQ_ERROR(req_num, "Transition state is failed");
622 HMI_SEQ_ERROR(req_num, errorDescription(ret));
623 this->pmw.undoState();
626 g_app_list.removeRequest(req_num);
627 this->processNextRequest();
630 void WindowManager::processError(WMError error)
632 unsigned req_num = g_app_list.currentRequestNumber();
635 HMI_SEQ_ERROR(req_num, errorDescription(error));
636 g_app_list.removeRequest(req_num);
637 this->processNextRequest();
641 ******* Private Functions *******
644 void WindowManager::emit_activated(const string& role)
646 this->send_event(kListEventName[Event_Active], role);
649 void WindowManager::emit_deactivated(const string& role)
651 this->send_event(kListEventName[Event_Inactive], role);
654 void WindowManager::emit_syncdraw(const string& role, char const *area, int x, int y, int w, int h)
656 this->send_event(kListEventName[Event_SyncDraw], role, area, x, y, w, h);
659 void WindowManager::emit_syncdraw(const string &role, const string &area)
661 struct rect rect = this->lc->getAreaSize(area);
662 this->send_event(kListEventName[Event_SyncDraw],
663 role, area, rect.x, rect.y, rect.w, rect.h);
666 void WindowManager::emit_flushdraw(const string& role)
668 this->send_event(kListEventName[Event_FlushDraw], role);
671 void WindowManager::emit_visible(const string& role, bool is_visible)
673 this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], role);
676 void WindowManager::emit_invisible(const string& role)
678 return emit_visible(role, false);
681 void WindowManager::emit_visible(const string& role) { return emit_visible(role, true); }
683 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
684 Task task, unsigned* req_num)
686 if (!g_app_list.contains(appid))
688 return WMError::NOT_REGISTERED;
691 auto client = g_app_list.lookUpClient(appid);
696 unsigned current = g_app_list.currentRequestNumber();
697 unsigned requested_num = g_app_list.getRequestNumber(appid);
698 if (requested_num != 0)
700 HMI_SEQ_INFO(requested_num,
701 "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
705 WMRequest req = WMRequest(appid, role, area, task);
706 unsigned new_req = g_app_list.addRequest(req);
708 g_app_list.reqDump();
710 HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
712 return WMError::SUCCESS;
715 WMError WindowManager::checkPolicy(unsigned req_num)
720 // get current trigger
722 WMError ret = WMError::LAYOUT_CHANGE_FAIL;
723 auto trigger = g_app_list.getRequest(req_num, &found);
726 ret = WMError::NO_ENTRY;
729 string req_area = trigger.area;
731 // Input event data to PolicyManager
732 if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
734 HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
738 // Execute state transition of PolicyManager
739 if (0 > this->pmw.executeStateTransition())
741 HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
745 ret = WMError::SUCCESS;
747 g_app_list.reqDump();
752 WMError WindowManager::startTransition(unsigned req_num)
754 bool sync_draw_happen = false;
756 WMError ret = WMError::SUCCESS;
757 auto actions = g_app_list.getActions(req_num, &found);
760 ret = WMError::NO_ENTRY;
761 HMI_SEQ_ERROR(req_num,
762 "Window Manager bug :%s : Action is not set", errorDescription(ret));
766 g_app_list.reqDump();
767 for (const auto &action : actions)
769 if (action.visible == TaskVisible::VISIBLE)
771 sync_draw_happen = true;
772 this->emit_syncdraw(action.role, action.area);
773 /* TODO: emit event for app not subscriber
774 if(g_app_list.contains(y.appid))
775 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
779 if (sync_draw_happen)
785 // deactivate only, no syncDraw
786 // Make it deactivate here
787 for (const auto &x : actions)
789 this->lc->visibilityChange(x);
790 emit_deactivated(x.role);
791 /* if (g_app_list.contains(x.client->appID()))
793 auto client = g_app_list.lookUpClient(x.client->appID());
794 this->deactivate(client->surfaceID(x.role));
797 this->lc->renderLayers();
798 ret = WMError::NO_LAYOUT_CHANGE;
803 WMError WindowManager::doEndDraw(unsigned req_num)
807 auto actions = g_app_list.getActions(req_num, &found);
808 WMError ret = WMError::SUCCESS;
811 ret = WMError::NO_ENTRY;
815 HMI_SEQ_INFO(req_num, "do endDraw");
817 // layout change and make it visible
818 for (const auto &act : actions)
820 if(act.visible != TaskVisible::NO_CHANGE)
823 ret = this->lc->layoutChange(act);
824 if(ret != WMError::SUCCESS)
826 HMI_SEQ_WARNING(req_num,
827 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
830 ret = this->lc->visibilityChange(act);
832 if(act.visible == VISIBLE)
834 emit_visible(act.role);
835 emit_activated(act.role);
839 emit_invisible(act.role);
840 emit_deactivated(act.role);
843 if (ret != WMError::SUCCESS)
845 HMI_SEQ_WARNING(req_num,
846 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
849 HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
852 this->lc->renderLayers();
854 HMI_SEQ_INFO(req_num, "emit flushDraw");
856 for(const auto &act_flush : actions)
858 if(act_flush.visible == TaskVisible::VISIBLE)
860 this->emit_flushdraw(act_flush.role);
867 void WindowManager::emitScreenUpdated(unsigned req_num)
870 HMI_SEQ_DEBUG(req_num, "emit screen updated");
872 auto actions = g_app_list.getActions(req_num, &found);
875 HMI_SEQ_ERROR(req_num,
876 "Window Manager bug :%s : Action is not set",
877 errorDescription(WMError::NO_ENTRY));
881 // create json object
882 json_object *j = json_object_new_object();
883 json_object *jarray = json_object_new_array();
885 for(const auto& action: actions)
887 std::string appid = action.client->appID();
889 if(action.visible != TaskVisible::INVISIBLE)
891 json_object_array_add(jarray, json_object_new_string(appid.c_str()));
892 // POI: AGL LifeCycle Management
893 if (this->amgr.states[appid] != lcm::FOREGROUND) {
894 this->amgr.states[appid] = lcm::FOREGROUND;
895 this->amgr.emit_activity_status_changed(appid.c_str(), this->amgr.states_s[lcm::FOREGROUND]);
898 // POI: AGL LifeCycle Management
899 if (this->amgr.states[appid] != lcm::BACKGROUND) {
900 this->amgr.states[appid] = lcm::BACKGROUND;
901 this->amgr.emit_activity_status_changed(appid.c_str(), this->amgr.states_s[lcm::BACKGROUND]);
905 json_object_object_add(j, kKeyIds, jarray);
906 HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
908 int ret = afb_event_push(
909 this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
912 HMI_DEBUG("afb_event_push failed: %m");
916 void WindowManager::setTimer()
919 if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
920 HMI_ERROR("Could't set time (clock_gettime() returns with error");
924 HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
925 if (g_timer_ev_src == nullptr)
927 // firsttime set into sd_event
928 int ret = sd_event_add_time(afb_api_get_event_loop(afbBindingV3root), &g_timer_ev_src,
929 CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
932 HMI_ERROR("Could't set timer");
937 // update timer limitation after second time
938 sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
939 sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
943 void WindowManager::stopTimer()
945 unsigned req_num = g_app_list.currentRequestNumber();
946 HMI_SEQ_DEBUG(req_num, "Timer stop");
947 int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
950 HMI_SEQ_ERROR(req_num, "Timer stop failed");
954 void WindowManager::processNextRequest()
957 g_app_list.reqDump();
958 unsigned req_num = g_app_list.currentRequestNumber();
959 if (g_app_list.haveRequest())
961 HMI_SEQ_DEBUG(req_num, "Process next request");
962 WMError rc = checkPolicy(req_num);
963 if (rc != WMError::SUCCESS)
965 HMI_SEQ_ERROR(req_num, errorDescription(rc));
970 HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
979 ActivityManager::ActivityManager (void)
980 : states_s { "NOTEXISTS",
991 void ActivityManager::api_register_activity_observer (afb_req_t req)
993 std::string observer = afb_req_get_application_id(req);
995 json_object *j_data = afb_req_json(req);
996 json_object *j_target;
997 if (!json_object_object_get_ex(j_data, LCM_TARGET, &j_target)) {
998 afb_req_fail(req, "failed", "Need char const* argument target");
1001 std::string target(json_object_get_string(j_target));
1003 for (auto itr = this->map_observers.begin(); itr != this->map_observers.end(); ++itr) {
1004 observers mp = itr->second;
1005 if (mp.count(observer)) {
1007 HMI_DEBUG("observer(%s) is already exist", observer.c_str());
1008 if (this->map_observers[target].count(observer)) {
1009 // Aready registered
1010 HMI_DEBUG("observer(%s->%s) is already registered", observer.c_str(), target.c_str());
1012 HMI_DEBUG("observer(%s->%s) is registered", observer.c_str(), target.c_str());
1014 (this->map_observers[target])[observer] = mp[observer];
1021 afb_event_t event = afb_daemon_make_event(LCM_EVENT_STATUS_CHANGED);
1022 //afb_event_t event = afb_daemon_make_event(LCM_EVENT_STATUS_CHANGED);
1023 (this->map_observers[target])[observer] = {
1025 std::bitset<NUM_STATUS>(ACTIVITY_FILTER_ALL_SET)
1028 if (afb_req_subscribe(req, event) != 0) {
1029 HMI_ERROR("cannot subscribe event");
1033 void ActivityManager::api_unregister_activity_observer (afb_req_t req)
1035 std::string observer = afb_req_get_application_id(req);
1037 json_object *j_data = afb_req_json(req);
1038 json_object *j_target;
1040 if (!json_object_object_get_ex(j_data, LCM_TARGET, &j_target)) {
1041 afb_req_fail(req, "failed", "Need char const* argument target");
1044 std::string target(json_object_get_string(j_target));
1046 HMI_DEBUG("observer(%s->%s) is unregistered.", observer.c_str(), target.c_str());
1049 wm::result<json_object *> ActivityManager::api_get_activity_status (const char *appid)
1051 std::string id = appid;
1054 if (this->states.count(id)) {
1055 st = this->states[id];
1057 if (st < 0 || st >= NUM_STATUS) {
1058 HMI_ERROR("Illegal lifecycle state (%d) of [%s]", st, appid);
1059 return wm::Err<json_object *>("Illegal lifecycle state");
1063 const char * state = this->states_s[st];
1065 json_object *object = json_object_new_object();
1066 json_object_object_add(object, LCM_API, json_object_new_string(LCM_API_GET_ACTIVITY_STATUS));
1067 json_object_object_add(object, LCM_TARGET, json_object_new_string(appid));
1068 json_object_object_add(object, LCM_STATE, json_object_new_string(state));
1070 return wm::Ok<json_object *>(object);
1073 void ActivityManager::emit_activity_status_changed (const char* appid, const char* state)
1075 // POI: AGL LifeCycle Management
1076 // E.g. statusChanged(CREATED->STARTED)
1077 std::string id = appid;
1079 if (this->map_observers.count(id)) {
1080 observers mp = this->map_observers[id];
1081 for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
1082 afb_event_t event = itr->second.event;
1083 if (afb_event_is_valid(event)) {
1084 HMI_DEBUG("emit_activity_status_changed(%s, %s)", appid, state);
1085 json_object *data = json_object_new_object();
1086 json_object_object_add(data, LCM_STATE, json_object_new_string(state));
1087 json_object_object_add(data, LCM_TARGET, json_object_new_string(appid));
1089 afb_event_push(event, json_object_get(data));
1090 json_object_put(data);
1092 HMI_ERROR("afb_event is not valid");