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