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