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