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