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