Fix top surface becomes invisible when background surface is crashed.
[apps/agl-service-windowmanager.git] / src / window_manager.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  * Copyright (c) 2018 Konsulko Group
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <fstream>
19 #include <regex>
20
21 #include "window_manager.hpp"
22 #include "json_helper.hpp"
23 #include "applist.hpp"
24
25 extern "C"
26 {
27 #include <systemd/sd-event.h>
28 }
29
30 using std::string;
31 using std::vector;
32 using std::unordered_map;
33
34 namespace wm
35 {
36
37 static const uint64_t kTimeOut = 3ULL; /* 3s */
38
39 /* DrawingArea name used by "{layout}.{area}" */
40 const char kNameLayoutNormal[] = "normal";
41 const char kNameLayoutSplit[]  = "split";
42 const char kNameAreaFull[]     = "full";
43 const char kNameAreaMain[]     = "main";
44 const char kNameAreaSub[]      = "sub";
45
46 /* Key for json obejct */
47 const char kKeyDrawingName[] = "drawing_name";
48 const char kKeyDrawingArea[] = "drawing_area";
49 const char kKeyDrawingRect[] = "drawing_rect";
50 const char kKeyX[]           = "x";
51 const char kKeyY[]           = "y";
52 const char kKeyWidth[]       = "width";
53 const char kKeyHeight[]      = "height";
54 const char kKeyWidthPixel[]  = "width_pixel";
55 const char kKeyHeightPixel[] = "height_pixel";
56 const char kKeyWidthMm[]     = "width_mm";
57 const char kKeyHeightMm[]    = "height_mm";
58 const char kKeyScale[]       = "scale";
59 const char kKeyIds[]         = "ids";
60
61 static const vector<string> kListEventName{
62         "active",
63         "inactive",
64         "visible",
65         "invisible",
66         "syncDraw",
67         "flushDraw",
68         "screenUpdated",
69         "error"};
70
71 static sd_event_source *g_timer_ev_src = nullptr;
72 static AppList g_app_list;
73 static WindowManager *g_context;
74
75 namespace
76 {
77
78 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
79 {
80     HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
81     reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
82     return 0;
83 }
84
85 static void onStateTransitioned(vector<WMAction> actions)
86 {
87     g_context->startTransitionWrapper(actions);
88 }
89
90 static void onError()
91 {
92     g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
93 }
94 } // namespace
95
96 /**
97  * WindowManager Impl
98  */
99 WindowManager::WindowManager()
100     : id_alloc{}
101 {
102     const char *path = getenv("AFM_APP_INSTALL_DIR");
103     if (!path)
104     {
105         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
106     }
107     string root = path;
108
109     this->lc = std::make_shared<LayerControl>(root);
110
111     HMI_DEBUG("Layer Controller initialized");
112 }
113
114 int WindowManager::init()
115 {
116     LayerControlCallbacks lmcb;
117     lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
118         this->surface_created(surface);
119         };
120     lmcb.surfaceDestroyed = [&](unsigned surface){
121         this->surface_removed(surface);
122     };
123
124     if(this->lc->init(lmcb) != WMError::SUCCESS)
125     {
126         return -1;
127     }
128
129     // TODO: application requests by old role,
130     //       so create role map (old, new)
131     // Load old_role.db
132     this->loadOldRoleDb();
133
134     // Store my context for calling callback from PolicyManager
135     g_context = this;
136
137     // Initialize PMWrapper
138     this->pmw.initialize();
139
140     // Register callback to PolicyManager
141     this->pmw.registerCallback(onStateTransitioned, onError);
142
143     // Make afb event for subscriber
144     for (int i = Event_ScreenUpdated; i < Event_Error; i++)
145     {
146         map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str());
147     }
148
149     const struct rect css_bg = this->lc->getAreaSize("fullscreen");
150     Screen screen = this->lc->getScreenInfo();
151     rectangle dp_bg(screen.width(), screen.height());
152
153     dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
154     dp_bg.fit(screen.width(), screen.height());
155     dp_bg.center(screen.width(), screen.height());
156     HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
157               css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
158
159     double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
160     this->lc->setupArea(dp_bg, scale);
161
162     return 0;
163 }
164
165 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
166 {
167     // TODO: application requests by old role,
168     //       so convert role old to new
169     const char *new_role = this->convertRoleOldToNew(drawing_name);
170
171     string str_id = appid;
172     string role = new_role;
173     unsigned lid = 0;
174
175     if(!g_app_list.contains(str_id))
176     {
177         lid = this->lc->getNewLayerID(role);
178         if (lid == 0)
179         {
180             // register drawing_name as fallback and make it displayed.
181             lid = this->lc->getNewLayerID(string("fallback"));
182             HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
183             if (lid == 0)
184             {
185                 return Err<int>("Designated role does not match any role, fallback is disabled");
186             }
187         }
188         this->lc->createNewLayer(lid);
189         // add client into the db
190         g_app_list.addClient(str_id, lid, drawing_name);
191     }
192
193     // generate surface ID for ivi-shell application
194     auto rname = this->id_alloc.lookup(role);
195     if (!rname)
196     {
197         // name does not exist yet, allocate surface id...
198         auto id = int(this->id_alloc.generate_id(role));
199         this->tmp_surface2app[id] = {str_id, lid};
200
201         auto client = g_app_list.lookUpClient(str_id);
202         client->registerSurface(id);
203
204         // Set role map of (new, old)
205         this->rolenew2old[role] = std::string(drawing_name);
206
207         return Ok<int>(id);
208     }
209
210     // Check currently registered drawing names if it is already there.
211     return Err<int>("Surface already present");
212 }
213
214 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
215                                      char const *ivi_id)
216 {
217     // TODO: application requests by old role,
218     //       so convert role old to new
219     const char *new_role = this->convertRoleOldToNew(drawing_name);
220
221     string str_id   = appid;
222     string role = new_role;
223
224     unsigned sid = std::stol(ivi_id);
225     HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
226     /*
227      * IVI-shell doesn't send surface_size event via ivi-wm protocol
228      * if the application is using XDG surface.
229      * So WM has to set surface size with original size here
230      */
231     WMError ret = this->lc->setXDGSurfaceOriginSize(sid);
232     if(ret != SUCCESS)
233     {
234         HMI_ERROR("%s", errorDescription(ret));
235         HMI_WARNING("The main user of this API is runXDG");
236         return "fail";
237     }
238
239     if(!g_app_list.contains(str_id))
240     {
241         unsigned l_id = this->lc->getNewLayerID(role);
242         if (l_id == 0)
243         {
244             // register drawing_name as fallback and make it displayed.
245             l_id = this->lc->getNewLayerID("fallback");
246             HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
247             if (l_id == 0)
248             {
249                 return "Designated role does not match any role, fallback is disabled";
250             }
251         }
252         this->lc->createNewLayer(l_id);
253         // add client into the db
254         g_app_list.addClient(str_id, l_id, drawing_name);
255     }
256
257     auto rname = this->id_alloc.lookup(role);
258
259     if (rname)
260     {
261         return "Surface already present";
262     }
263
264     // register pair drawing_name and ivi_id
265     this->id_alloc.register_name_id(role, sid);
266
267     auto client = g_app_list.lookUpClient(str_id);
268     client->addSurface(sid);
269
270     // Set role map of (new, old)
271     this->rolenew2old[role] = std::string(drawing_name);
272
273     return nullptr;
274 }
275
276 void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
277                                char const *drawing_area, const reply_func &reply)
278 {
279     // TODO: application requests by old role,
280     //       so convert role old to new
281     const char *c_role = this->convertRoleOldToNew(drawing_name);
282
283     string id = appid;
284     string role = c_role;
285     string area = drawing_area;
286
287     if(!g_app_list.contains(id))
288     {
289         reply("app doesn't request 'requestSurface' or 'setRole' yet");
290         return;
291     }
292     auto client = g_app_list.lookUpClient(id);
293
294     Task task = Task::TASK_ALLOCATE;
295     unsigned req_num = 0;
296     WMError ret = WMError::UNKNOWN;
297
298     ret = this->setRequest(id, role, area, task, &req_num);
299
300     if(ret != WMError::SUCCESS)
301     {
302         HMI_ERROR(errorDescription(ret));
303         reply("Failed to set request");
304         return;
305     }
306
307     reply(nullptr);
308     if (req_num != g_app_list.currentRequestNumber())
309     {
310         // Add request, then invoked after the previous task is finished
311         HMI_SEQ_DEBUG(req_num, "request is accepted");
312         return;
313     }
314
315      // Do allocate tasks
316     ret = this->checkPolicy(req_num);
317
318     if (ret != WMError::SUCCESS)
319     {
320         //this->emit_error()
321         HMI_SEQ_ERROR(req_num, errorDescription(ret));
322         g_app_list.removeRequest(req_num);
323         this->processNextRequest();
324     }
325 }
326
327 void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
328                                  const reply_func &reply)
329 {
330     // TODO: application requests by old role,
331     //       so convert role old to new
332     const char *c_role = this->convertRoleOldToNew(drawing_name);
333     // Check Phase
334     string id = appid;
335     string role = c_role;
336     string area = ""; //drawing_area;
337     Task task = Task::TASK_RELEASE;
338     unsigned req_num = 0;
339     WMError ret = WMError::UNKNOWN;
340
341     ret = this->setRequest(id, role, area, task, &req_num);
342
343     if (ret != WMError::SUCCESS)
344     {
345         HMI_ERROR(errorDescription(ret));
346         reply("Failed to set request");
347         return;
348     }
349
350     reply(nullptr);
351     if (req_num != g_app_list.currentRequestNumber())
352     {
353         // Add request, then invoked after the previous task is finished
354         HMI_SEQ_DEBUG(req_num, "request is accepted");
355         return;
356     }
357
358     // Do allocate tasks
359     ret = this->checkPolicy(req_num);
360
361     if (ret != WMError::SUCCESS)
362     {
363         //this->emit_error()
364         HMI_SEQ_ERROR(req_num, errorDescription(ret));
365         g_app_list.removeRequest(req_num);
366         this->processNextRequest();
367     }
368 }
369
370 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
371 {
372     // TODO: application requests by old role,
373     //       so convert role old to new
374     const char *c_role = this->convertRoleOldToNew(drawing_name);
375
376     string id = appid;
377     string role = c_role;
378     unsigned current_req = g_app_list.currentRequestNumber();
379     bool result = g_app_list.setEndDrawFinished(current_req, id, role);
380
381     if (!result)
382     {
383         HMI_ERROR("%s is not in transition state", id.c_str());
384         return;
385     }
386
387     if (g_app_list.endDrawFullfilled(current_req))
388     {
389         // do task for endDraw
390         this->stopTimer();
391         WMError ret = this->doEndDraw(current_req);
392
393         if(ret != WMError::SUCCESS)
394         {
395             //this->emit_error();
396
397             // Undo state of PolicyManager
398             this->pmw.undoState();
399             this->lc->undoUpdate();
400         }
401         this->emitScreenUpdated(current_req);
402         HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
403
404         g_app_list.removeRequest(current_req);
405
406         this->processNextRequest();
407     }
408     else
409     {
410         HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
411         return;
412     }
413 }
414
415 bool WindowManager::api_subscribe(afb_req_t req, EventType event_id)
416 {
417     bool ret = false;
418     char* appid = afb_req_get_application_id(req);
419     if(event_id < Event_Val_Min || event_id > Event_Val_Max)
420     {
421         HMI_ERROR("not defined in Window Manager", event_id);
422         return ret;
423     }
424     HMI_INFO("%s subscribe %s : %d", appid, kListEventName[event_id].c_str(), event_id);
425     if(event_id == Event_ScreenUpdated)
426     {
427         // Event_ScreenUpdated should be emitted to subscriber
428         afb_event_t event = this->map_afb_event[kListEventName[event_id]];
429         int rc = afb_req_subscribe(req, event);
430         if(rc == 0)
431         {
432             ret = true;
433         }
434     }
435     else if(appid)
436     {
437         string id = appid;
438         free(appid);
439         auto client = g_app_list.lookUpClient(id);
440         if(client != nullptr)
441         {
442             ret = client->subscribe(req, kListEventName[event_id]);
443         }
444     }
445     return ret;
446 }
447
448 result<json_object *> WindowManager::api_get_display_info()
449 {
450     Screen screen = this->lc->getScreenInfo();
451
452     json_object *object = json_object_new_object();
453     json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
454     json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
455     // TODO: set size
456     json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
457     json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
458     json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
459
460     return Ok<json_object *>(object);
461 }
462
463 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
464 {
465     HMI_DEBUG("called");
466
467     // TODO: application requests by old role,
468     //       so convert role old to new
469     const char *c_role = this->convertRoleOldToNew(drawing_name);
470     string role = c_role;
471
472     // Check drawing name, surface/layer id
473     auto const &surface_id = this->id_alloc.lookup(role);
474     if (!surface_id)
475     {
476         return Err<json_object *>("Surface does not exist");
477     }
478
479     // Set area rectangle
480     struct rect area_info = this->area_info[*surface_id];
481     json_object *object = json_object_new_object();
482     json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
483     json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
484     json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
485     json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
486
487     return Ok<json_object *>(object);
488 }
489
490 /**
491  * proxied events
492  */
493 void WindowManager::surface_created(unsigned surface_id)
494 {
495     // requestSurface
496     if(this->tmp_surface2app.count(surface_id) != 0)
497     {
498         string appid = this->tmp_surface2app[surface_id].appid;
499         auto client = g_app_list.lookUpClient(appid);
500         if(client != nullptr)
501         {
502             WMError ret = client->addSurface(surface_id);
503             HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
504             if(ret != WMError::SUCCESS)
505             {
506                 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
507             }
508         }
509         this->tmp_surface2app.erase(surface_id);
510     }
511 }
512
513 void WindowManager::surface_removed(unsigned surface_id)
514 {
515     HMI_DEBUG("Delete surface_id %u", surface_id);
516     this->id_alloc.remove_id(surface_id);
517     g_app_list.removeSurface(surface_id);
518 }
519
520 void WindowManager::removeClient(const string &appid)
521 {
522     HMI_DEBUG("Remove clinet %s from list", appid.c_str());
523     auto client = g_app_list.lookUpClient(appid);
524     this->lc->appTerminated(client);
525     g_app_list.removeClient(appid);
526 }
527
528 void WindowManager::exceptionProcessForTransition()
529 {
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();
535 }
536
537 void WindowManager::timerHandler()
538 {
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();
544 }
545
546 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
547 {
548     WMError ret;
549     unsigned req_num = g_app_list.currentRequestNumber();
550
551     if (actions.empty())
552     {
553         if (g_app_list.haveRequest())
554         {
555             HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
556             goto proc_remove_request;
557         }
558         else
559         {
560             HMI_SEQ_DEBUG(req_num, "There is no request");
561             return;
562         }
563     }
564
565     for (auto &act : actions)
566     {
567         if ("" != act.role)
568         {
569             bool found;
570             auto const &surface_id = this->id_alloc.lookup(act.role);
571             if(surface_id == nullopt)
572             {
573                 goto proc_remove_request;
574             }
575             string appid = g_app_list.getAppID(*surface_id, &found);
576             if (!found)
577             {
578                 if (TaskVisible::INVISIBLE == act.visible)
579                 {
580                     // App is killed, so do not set this action
581                     continue;
582                 }
583                 else
584                 {
585                     HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
586                     ret = WMError::FAIL;
587                     goto error;
588                 }
589             }
590             auto client = g_app_list.lookUpClient(appid);
591             act.req_num = req_num;
592             act.client = client;
593         }
594
595         ret = g_app_list.setAction(req_num, act);
596         if (ret != WMError::SUCCESS)
597         {
598             HMI_SEQ_ERROR(req_num, "Setting action is failed");
599             goto error;
600         }
601     }
602
603     HMI_SEQ_DEBUG(req_num, "Start transition.");
604     ret = this->startTransition(req_num);
605     if (ret != WMError::SUCCESS)
606     {
607         if (ret == WMError::NO_LAYOUT_CHANGE)
608         {
609             goto proc_remove_request;
610         }
611         else
612         {
613             HMI_SEQ_ERROR(req_num, "Transition state is failed");
614             goto error;
615         }
616     }
617
618     return;
619
620 error:
621     //this->emit_error()
622     HMI_SEQ_ERROR(req_num, errorDescription(ret));
623     this->pmw.undoState();
624
625 proc_remove_request:
626     g_app_list.removeRequest(req_num);
627     this->processNextRequest();
628 }
629
630 void WindowManager::processError(WMError error)
631 {
632     unsigned req_num = g_app_list.currentRequestNumber();
633
634     //this->emit_error()
635     HMI_SEQ_ERROR(req_num, errorDescription(error));
636     g_app_list.removeRequest(req_num);
637     this->processNextRequest();
638 }
639
640 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
641                             Task task, unsigned* req_num)
642 {
643     if (!g_app_list.contains(appid))
644     {
645         return WMError::NOT_REGISTERED;
646     }
647
648     auto client = g_app_list.lookUpClient(appid);
649
650     /*
651      * Queueing Phase
652      */
653     unsigned current = g_app_list.currentRequestNumber();
654     unsigned requested_num = g_app_list.getRequestNumber(appid);
655     if (requested_num != 0)
656     {
657         HMI_SEQ_INFO(requested_num,
658             "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
659         return REQ_REJECTED;
660     }
661
662     WMRequest req = WMRequest(appid, role, area, task);
663     unsigned new_req = g_app_list.addRequest(req);
664     *req_num = new_req;
665     g_app_list.reqDump();
666
667     HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
668
669     return WMError::SUCCESS;
670 }
671
672 WMError WindowManager::checkPolicy(unsigned req_num)
673 {
674     /*
675     * Check Policy
676     */
677     // get current trigger
678     bool found = false;
679     WMError ret = WMError::LAYOUT_CHANGE_FAIL;
680     auto trigger = g_app_list.getRequest(req_num, &found);
681     if (!found)
682     {
683         ret = WMError::NO_ENTRY;
684         return ret;
685     }
686     string req_area = trigger.area;
687
688     // Input event data to PolicyManager
689     if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
690     {
691         HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
692         return ret;
693     }
694
695     // Execute state transition of PolicyManager
696     if (0 > this->pmw.executeStateTransition())
697     {
698         HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
699         return ret;
700     }
701
702     ret = WMError::SUCCESS;
703
704     g_app_list.reqDump();
705
706     return ret;
707 }
708
709 WMError WindowManager::startTransition(unsigned req_num)
710 {
711     bool sync_draw_happen = false;
712     bool found = false;
713     WMError ret = WMError::SUCCESS;
714     auto actions = g_app_list.getActions(req_num, &found);
715     if (!found)
716     {
717         ret = WMError::NO_ENTRY;
718         HMI_SEQ_ERROR(req_num,
719             "Window Manager bug :%s : Action is not set", errorDescription(ret));
720         return ret;
721     }
722
723     g_app_list.reqDump();
724     for (const auto &action : actions)
725     {
726         if (action.visible == TaskVisible::VISIBLE)
727         {
728             sync_draw_happen = true;
729             struct rect r = this->lc->getAreaSize(action.area);
730             action.client->emitSyncDraw(action.area, r);
731         }
732     }
733
734     if (sync_draw_happen)
735     {
736         this->setTimer();
737     }
738     else
739     {
740         // deactivate only, no syncDraw
741         // Make it deactivate here
742         for (const auto &x : actions)
743         {
744             this->lc->visibilityChange(x);
745             x.client->emitActive(false);
746             x.client->emitVisible(false);
747         }
748         this->lc->renderLayers();
749         ret = WMError::NO_LAYOUT_CHANGE;
750     }
751     return ret;
752 }
753
754 WMError WindowManager::doEndDraw(unsigned req_num)
755 {
756     // get actions
757     bool found;
758     auto actions = g_app_list.getActions(req_num, &found);
759     WMError ret = WMError::SUCCESS;
760     if (!found)
761     {
762         ret = WMError::NO_ENTRY;
763         return ret;
764     }
765
766     HMI_SEQ_INFO(req_num, "do endDraw");
767
768     // layout change and make it visible
769     for (const auto &act : actions)
770     {
771         if(act.visible != TaskVisible::NO_CHANGE)
772         {
773             // layout change
774             ret = this->lc->layoutChange(act);
775             if(ret != WMError::SUCCESS)
776             {
777                 HMI_SEQ_WARNING(req_num,
778                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
779                 return ret;
780             }
781             ret = this->lc->visibilityChange(act);
782
783             act.client->emitActive((act.visible == VISIBLE));
784             act.client->emitVisible((act.visible == VISIBLE));
785
786             if (ret != WMError::SUCCESS)
787             {
788                 HMI_SEQ_WARNING(req_num,
789                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
790                 return ret;
791             }
792             HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
793         }
794     }
795     this->lc->renderLayers();
796
797     HMI_SEQ_INFO(req_num, "emit flushDraw");
798
799     for(const auto &act_flush : actions)
800     {
801         if(act_flush.visible == TaskVisible::VISIBLE)
802         {
803             act_flush.client->emitFlushDraw();
804         }
805     }
806
807     return ret;
808 }
809
810 void WindowManager::emitScreenUpdated(unsigned req_num)
811 {
812     // Get visible apps
813     HMI_SEQ_DEBUG(req_num, "emit screen updated");
814     bool found = false;
815     auto actions = g_app_list.getActions(req_num, &found);
816     if (!found)
817     {
818         HMI_SEQ_ERROR(req_num,
819                       "Window Manager bug :%s : Action is not set",
820                       errorDescription(WMError::NO_ENTRY));
821         return;
822     }
823
824     // create json object
825     json_object *j = json_object_new_object();
826     json_object *jarray = json_object_new_array();
827
828     for(const auto& action: actions)
829     {
830         if(action.visible != TaskVisible::INVISIBLE)
831         {
832             json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
833         }
834     }
835     json_object_object_add(j, kKeyIds, jarray);
836     HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
837
838     int ret = afb_event_push(
839         this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
840     if (ret < 0)
841     {
842         HMI_DEBUG("afb_event_push failed: %m");
843     }
844 }
845
846 void WindowManager::setTimer()
847 {
848     struct timespec ts;
849     if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
850         HMI_ERROR("Could't set time (clock_gettime() returns with error");
851         return;
852     }
853
854     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
855     if (g_timer_ev_src == nullptr)
856     {
857         // firsttime set into sd_event
858         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
859             CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
860         if (ret < 0)
861         {
862             HMI_ERROR("Could't set timer");
863         }
864     }
865     else
866     {
867         // update timer limitation after second time
868         sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
869         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
870     }
871 }
872
873 void WindowManager::stopTimer()
874 {
875     unsigned req_num = g_app_list.currentRequestNumber();
876     HMI_SEQ_DEBUG(req_num, "Timer stop");
877     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
878     if (rc < 0)
879     {
880         HMI_SEQ_ERROR(req_num, "Timer stop failed");
881     }
882 }
883
884 void WindowManager::processNextRequest()
885 {
886     g_app_list.next();
887     g_app_list.reqDump();
888     unsigned req_num = g_app_list.currentRequestNumber();
889     if (g_app_list.haveRequest())
890     {
891         HMI_SEQ_DEBUG(req_num, "Process next request");
892         WMError rc = checkPolicy(req_num);
893         if (rc != WMError::SUCCESS)
894         {
895             HMI_SEQ_ERROR(req_num, errorDescription(rc));
896         }
897     }
898     else
899     {
900         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
901     }
902 }
903
904 const char* WindowManager::convertRoleOldToNew(char const *old_role)
905 {
906     const char *new_role = nullptr;
907
908     for (auto const &on : this->roleold2new)
909     {
910         std::regex regex = std::regex(on.first);
911         if (std::regex_match(old_role, regex))
912         {
913             // role is old. So convert to new.
914             new_role = on.second.c_str();
915             break;
916         }
917     }
918
919     if (nullptr == new_role)
920     {
921         // role is new or fallback.
922         new_role = old_role;
923     }
924
925     HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
926
927     return new_role;
928 }
929
930 int WindowManager::loadOldRoleDb()
931 {
932     std::string file_name(get_file_path("old_roles.db"));
933
934     // Load old_role.db
935     json_object* json_obj;
936     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
937     if (0 > ret)
938     {
939         HMI_ERROR("Could not open old_role.db, so use default old_role information");
940         json_obj = json_tokener_parse(kDefaultOldRoleDb);
941     }
942     HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
943
944     // Perse apps
945     json_object* json_cfg;
946     if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
947     {
948         HMI_ERROR("Parse Error!!");
949         return -1;
950     }
951
952     int len = json_object_array_length(json_cfg);
953     HMI_DEBUG("json_cfg len:%d", len);
954     HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
955
956     for (int i=0; i<len; i++)
957     {
958         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
959
960         const char* old_role = jh::getStringFromJson(json_tmp, "name");
961         if (nullptr == old_role)
962         {
963             HMI_ERROR("Parse Error!!");
964             return -1;
965         }
966
967         const char* new_role = jh::getStringFromJson(json_tmp, "new");
968         if (nullptr == new_role)
969         {
970             HMI_ERROR("Parse Error!!");
971             return -1;
972         }
973
974         this->roleold2new[old_role] = std::string(new_role);
975     }
976
977     // Check
978     for(auto itr = this->roleold2new.begin();
979       itr != this->roleold2new.end(); ++itr)
980     {
981         HMI_DEBUG(">>> role old:%s new:%s",
982                   itr->first.c_str(), itr->second.c_str());
983     }
984
985     // Release json_object
986     json_object_put(json_obj);
987
988     return 0;
989 }
990
991 const char* WindowManager::kDefaultOldRoleDb = "{ \
992     \"old_roles\": [ \
993         { \
994             \"name\": \"HomeScreen\", \
995             \"new\": \"homescreen\" \
996         }, \
997         { \
998             \"name\": \"Music\", \
999             \"new\": \"music\" \
1000         }, \
1001         { \
1002             \"name\": \"MediaPlayer\", \
1003             \"new\": \"music\" \
1004         }, \
1005         { \
1006             \"name\": \"Video\", \
1007             \"new\": \"video\" \
1008         }, \
1009         { \
1010             \"name\": \"VideoPlayer\", \
1011             \"new\": \"video\" \
1012         }, \
1013         { \
1014             \"name\": \"WebBrowser\", \
1015             \"new\": \"browser\" \
1016         }, \
1017         { \
1018             \"name\": \"Radio\", \
1019             \"new\": \"radio\" \
1020         }, \
1021         { \
1022             \"name\": \"Phone\", \
1023             \"new\": \"phone\" \
1024         }, \
1025         { \
1026             \"name\": \"Navigation\", \
1027             \"new\": \"map\" \
1028         }, \
1029         { \
1030             \"name\": \"HVAC\", \
1031             \"new\": \"hvac\" \
1032         }, \
1033         { \
1034             \"name\": \"Settings\", \
1035             \"new\": \"settings\" \
1036         }, \
1037         { \
1038             \"name\": \"Dashboard\", \
1039             \"new\": \"dashboard\" \
1040         }, \
1041         { \
1042             \"name\": \"POI\", \
1043             \"new\": \"poi\" \
1044         }, \
1045         { \
1046             \"name\": \"Mixer\", \
1047             \"new\": \"mixer\" \
1048         }, \
1049         { \
1050             \"name\": \"Restriction\", \
1051             \"new\": \"restriction\" \
1052         }, \
1053         { \
1054             \"name\": \"^OnScreen.*\", \
1055             \"new\": \"on_screen\" \
1056         } \
1057     ] \
1058 }";
1059
1060 } // namespace wm