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