58ae4bcf0d0b475b55ec464f67063c11cf43c232
[apps/agl-service-windowmanager-2017.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 sd_event_source *g_timer_ev_src = nullptr;
60 static AppList g_app_list;
61 static WindowManager *g_context;
62
63 namespace
64 {
65
66 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
67 {
68     HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request");
69     reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
70     return 0;
71 }
72
73 static void onStateTransitioned(vector<WMAction> actions)
74 {
75     g_context->startTransitionWrapper(actions);
76 }
77
78 static void onError()
79 {
80     g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
81 }
82 } // namespace
83
84 /**
85  * WindowManager Impl
86  */
87 WindowManager::WindowManager()
88     : id_alloc{}
89 {
90     const char *path = getenv("AFM_APP_INSTALL_DIR");
91     if (!path)
92     {
93         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
94     }
95     string root = path;
96
97     this->lc = std::make_shared<LayerControl>(root);
98
99     HMI_DEBUG("Layer Controller initialized");
100 }
101
102 int WindowManager::init()
103 {
104     // TODO: application requests by old role,
105     //       so create role map (old, new)
106     // Load old_role.db
107     LayerControlCallbacks lmcb;
108     lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
109         this->surface_created(surface);
110         };
111     lmcb.surfaceDestroyed = [&](unsigned surface){
112         this->surface_removed(surface);
113     };
114     this->lc->init(lmcb);
115     this->loadOldRoleDb();
116
117     // Store my context for calling callback from PolicyManager
118     g_context = this;
119
120     // Initialize PMWrapper
121     this->pmw.initialize();
122
123     // Register callback to PolicyManager
124     this->pmw.registerCallback(onStateTransitioned, onError);
125
126     // Make afb event
127     for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
128     {
129         map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i]);
130     }
131
132     const struct rect css_bg = this->lc->getAreaSize("fullscreen");
133     Screen screen = this->lc->getScreenInfo();
134     rectangle dp_bg(screen.width(), screen.height());
135
136     dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h);
137     dp_bg.fit(screen.width(), screen.height());
138     dp_bg.center(screen.width(), screen.height());
139     HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)",
140               css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height());
141
142     double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
143     this->lc->setupArea(dp_bg, scale);
144
145     return 0; //init_layers();
146 }
147
148 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
149 {
150     // TODO: application requests by old role,
151     //       so convert role old to new
152     const char *role = this->convertRoleOldToNew(drawing_name);
153     string l_name;
154     string s_appid = appid;
155     string s_role = role;
156
157     if(!g_app_list.contains(s_appid))
158     {
159         // auto lid = this->layers.get_layer_id(string(role));
160         unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
161         if (l_id == 0)
162         {
163             /**
164              * register drawing_name as fallback and make it displayed.
165              */
166             l_id = this->lc->getNewLayerID("fallback", &l_name);
167             HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
168             if (l_id == 0)
169             {
170                 return Err<int>("Designated role does not match any role, fallback is disabled");
171             }
172         }
173         this->lc->createNewLayer(l_id);
174         // add client into the db
175         g_app_list.addClient(s_appid, l_id, s_role);
176     }
177
178     // generate surface ID for ivi-shell application
179
180     auto rname = this->id_alloc.lookup(string(role));
181     if (!rname)
182     {
183         // name does not exist yet, allocate surface id...
184         auto id = int(this->id_alloc.generate_id(role));
185         this->tmp_surface2app[id] = s_appid;
186
187         // Set role map of (new, old)
188         this->rolenew2old[role] = string(drawing_name);
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     // TODO: application requests by old role,
201     //       so convert role old to new
202     const char *role = this->convertRoleOldToNew(drawing_name);
203     string s_role = role;
204     string s_appid = appid;
205     string l_name;
206
207     if(!g_app_list.contains(s_appid))
208     {
209         // auto lid = this->layers.get_layer_id(string(role));
210         unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
211         if (l_id == 0)
212         {
213             /**
214              * register drawing_name as fallback and make it displayed.
215              */
216             l_id = this->lc->getNewLayerID("fallback", &l_name);
217             HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
218             if (l_id == 0)
219             {
220                 return "Designated role does not match any role, fallback is disabled";
221             }
222         }
223         this->lc->createNewLayer(l_id);
224         // add client into the db
225         g_app_list.addClient(s_appid, l_id, s_role);
226     }
227
228     unsigned sid = std::stol(ivi_id);
229
230     auto rname = this->id_alloc.lookup(s_role);
231     if (rname)
232     {
233         return "Surface already present";
234     }
235     if(this->tmp_surface2app.count(sid) != 0)
236     {
237         this->tmp_surface2app.erase(sid);
238     }
239
240
241     // register pair drawing_name and ivi_id
242     this->id_alloc.register_name_id(role, sid);
243     // this->layers.add_surface(sid, *lid);
244
245     // this surface is already created
246     // HMI_DEBUG("surface_id is %u, layer_id is %u", sid, *lid);
247
248     // this->controller->layers[*lid]->add_surface(sid);
249     // this->layout_commit();
250
251     // add client into the db
252     // g_app_list.addClient(appid_str, lid, s_role);
253     auto client = g_app_list.lookUpClient(s_appid);
254     client->addSurface(sid);
255
256     // Set role map of (new, old)
257     this->rolenew2old[role] = string(drawing_name);
258
259     return nullptr;
260 }
261
262 bool WindowManager::api_set_role(char const *appid, char const *drawing_name, unsigned pid){
263     string id = appid;
264     string role = drawing_name;
265     string l_name;
266     unsigned surface = 0;
267     WMError wm_err = WMError::UNKNOWN;
268     bool ret = false;
269
270     // get layer ID which role should be in
271     // auto lid = this->layers.get_layer_id(role);
272     unsigned lid = this->lc->getNewLayerID(role, &l_name);
273     if (lid == 0)
274     {
275         // lid = this->layers.get_layer_id(string("fallback"));
276         HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
277         if (lid == 0)
278         {
279             HMI_ERROR("Drawing name does not match any role, fallback is disabled");
280             return ret;
281         }
282     }
283
284     if(0 != pid){
285         // search floating surfaceID from pid if pid is designated.
286         wm_err = g_app_list.popFloatingSurface(pid, &surface);
287     }
288     else{
289         // get floating surface with appid. If WM queries appid from pid,
290         // WM can bind surface and role with appid(not implemented yet)
291         //wm_err = g_app_list.popFloatingSurface(id);
292     }
293     if(wm_err != WMError::SUCCESS){
294         HMI_ERROR("No floating surface for app: %s", id.c_str());
295         g_app_list.addFloatingClient(id, lid, role);
296         HMI_NOTICE("%s : Waiting for surface creation", id.c_str());
297         return ret;
298     }
299
300     ret = true;
301     if (g_app_list.contains(id))
302     {
303         HMI_INFO("Add role: %s with surface: %d. Client %s has multi surfaces.",
304                  role.c_str(), surface, id.c_str());
305         auto client = g_app_list.lookUpClient(id);
306         client->appendRole(role);
307     }
308     else{
309         HMI_INFO("Create new client: %s, surface: %d into layer: %d with role: %s",
310                  id.c_str(), surface, lid, role.c_str());
311         g_app_list.addClient(id, lid, role);
312     }
313
314     // register pair drawing_name and ivi_id
315     this->id_alloc.register_name_id(role.c_str(), surface);
316
317     // this surface is already created
318     HMI_DEBUG("surface_id is %u, layer_id is %u", surface, lid);
319
320     return ret;
321 }
322
323 void WindowManager::api_activate_surface(char const *appid, char const *drawing_name,
324                                char const *drawing_area, const reply_func &reply)
325 {
326     // TODO: application requests by old role,
327     //       so convert role old to new
328     const char *c_role = this->convertRoleOldToNew(drawing_name);
329
330     string id = appid;
331     string role = c_role;
332     string area = drawing_area;
333
334     if(!g_app_list.contains(id))
335     {
336         reply("app doesn't request 'requestSurface' or 'setRole' yet");
337         return;
338     }
339     auto client = g_app_list.lookUpClient(id);
340
341     // unsigned srfc = client->surfaceID(role);
342     // unsigned layer = client->layerID();
343
344     // g_app_list.removeFloatingSurface(client->surfaceID());
345     // g_app_list.removeFloatingSurface(client);
346
347     Task task = Task::TASK_ALLOCATE;
348     unsigned req_num = 0;
349     WMError ret = WMError::UNKNOWN;
350
351     ret = this->setRequest(id, role, area, task, &req_num);
352
353     //vector<WMLayerState> current_states = this->lc->getCurrentStates();
354     // ret = this->setRequest(id, role, area, task, current_states, &req_num);
355
356     if(ret != WMError::SUCCESS)
357     {
358         HMI_ERROR(errorDescription(ret));
359         reply("Failed to set request");
360         return;
361     }
362
363     reply(nullptr);
364     if (req_num != g_app_list.currentRequestNumber())
365     {
366         // Add request, then invoked after the previous task is finished
367         HMI_SEQ_DEBUG(req_num, "request is accepted");
368         return;
369     }
370
371     /*
372      * Do allocate tasks
373      */
374     ret = this->checkPolicy(req_num);
375
376     if (ret != WMError::SUCCESS)
377     {
378         //this->emit_error()
379         HMI_SEQ_ERROR(req_num, errorDescription(ret));
380         g_app_list.removeRequest(req_num);
381         this->processNextRequest();
382     }
383 }
384
385 void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name,
386                                  const reply_func &reply)
387 {
388     // TODO: application requests by old role,
389     //       so convert role old to new
390     const char *c_role = this->convertRoleOldToNew(drawing_name);
391
392     /*
393     * Check Phase
394     */
395     string id = appid;
396     string role = c_role;
397     string area = ""; //drawing_area;
398     Task task = Task::TASK_RELEASE;
399     unsigned req_num = 0;
400     WMError ret = WMError::UNKNOWN;
401
402     ret = this->setRequest(id, role, area, task, &req_num);
403
404     if (ret != WMError::SUCCESS)
405     {
406         HMI_ERROR(errorDescription(ret));
407         reply("Failed to set request");
408         return;
409     }
410
411     reply(nullptr);
412     if (req_num != g_app_list.currentRequestNumber())
413     {
414         // Add request, then invoked after the previous task is finished
415         HMI_SEQ_DEBUG(req_num, "request is accepted");
416         return;
417     }
418
419     /*
420     * Do allocate tasks
421     */
422     ret = this->checkPolicy(req_num);
423
424     if (ret != WMError::SUCCESS)
425     {
426         //this->emit_error()
427         HMI_SEQ_ERROR(req_num, errorDescription(ret));
428         g_app_list.removeRequest(req_num);
429         this->processNextRequest();
430     }
431 }
432
433 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
434 {
435     // TODO: application requests by old role,
436     //       so convert role old to new
437     const char *c_role = this->convertRoleOldToNew(drawing_name);
438
439     string id = appid;
440     string role = c_role;
441     unsigned current_req = g_app_list.currentRequestNumber();
442     bool result = g_app_list.setEndDrawFinished(current_req, id, role);
443
444     if (!result)
445     {
446         HMI_ERROR("%s is not in transition state", id.c_str());
447         return;
448     }
449
450     if (g_app_list.endDrawFullfilled(current_req))
451     {
452         // do task for endDraw
453         this->stopTimer();
454         WMError ret = this->doEndDraw(current_req);
455
456         if(ret != WMError::SUCCESS)
457         {
458             //this->emit_error();
459
460             // Undo state of PolicyManager
461             this->pmw.undoState();
462             this->lc->undoUpdate();
463         }
464         this->emitScreenUpdated(current_req);
465         HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
466
467         g_app_list.removeRequest(current_req);
468
469         this->processNextRequest();
470     }
471     else
472     {
473         HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
474         return;
475     }
476 }
477
478 result<json_object *> WindowManager::api_get_display_info()
479 {
480     Screen screen = this->lc->getScreenInfo();
481
482     json_object *object = json_object_new_object();
483     json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width()));
484     json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height()));
485     // TODO: set size
486     json_object_object_add(object, kKeyWidthMm, json_object_new_int(0));
487     json_object_object_add(object, kKeyHeightMm, json_object_new_int(0));
488     json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale()));
489
490     return Ok<json_object *>(object);
491 }
492
493 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
494 {
495     HMI_DEBUG("called");
496
497     // TODO: application requests by old role,
498     //       so convert role old to new
499     const char *role = this->convertRoleOldToNew(drawing_name);
500
501     // Check drawing name, surface/layer id
502     auto const &surface_id = this->id_alloc.lookup(string(role));
503     if (!surface_id)
504     {
505         return Err<json_object *>("Surface does not exist");
506     }
507
508     // Set area rectangle
509     rect area_info = this->area_info[*surface_id];
510     json_object *object = json_object_new_object();
511     json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
512     json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
513     json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
514     json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
515
516     return Ok<json_object *>(object);
517 }
518
519 void WindowManager::send_event(char const *evname, char const *label)
520 {
521     HMI_DEBUG("%s: %s(%s)", __func__, evname, label);
522
523     json_object *j = json_object_new_object();
524     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
525
526     int ret = afb_event_push(this->map_afb_event[evname], j);
527     if (ret != 0)
528     {
529         HMI_DEBUG("afb_event_push failed: %m");
530     }
531 }
532
533 void WindowManager::send_event(char const *evname, char const *label, char const *area,
534                      int x, int y, int w, int h)
535 {
536     HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
537               __func__, evname, label, area, x, y, w, h);
538
539     json_object *j_rect = json_object_new_object();
540     json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
541     json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
542     json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
543     json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
544
545     json_object *j = json_object_new_object();
546     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
547     json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area));
548     json_object_object_add(j, kKeyDrawingRect, j_rect);
549
550     int ret = afb_event_push(this->map_afb_event[evname], j);
551     if (ret != 0)
552     {
553         HMI_DEBUG("afb_event_push failed: %m");
554     }
555 }
556
557 /**
558  * proxied events
559  */
560 void WindowManager::surface_created(uint32_t surface_id)
561 {
562     if(this->tmp_surface2app.count(surface_id) != 0)
563     {
564         string appid = this->tmp_surface2app[surface_id];
565         this->tmp_surface2app.erase(surface_id);
566         if(g_app_list.contains(appid))
567         {
568             auto client = g_app_list.lookUpClient(appid);
569             WMError ret = client->addSurface(surface_id);
570             HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str());
571             if(ret != WMError::SUCCESS)
572             {
573                 HMI_ERROR("Failed to add surface to client %s", client->appID().c_str());
574             }
575         }
576     }
577     else
578     {
579         HMI_NOTICE("Unknown surface %d", surface_id);
580         this->tmp_surface2app[surface_id] = ""; /* Store for requestSurfaceXDG */
581     }
582 }
583
584 void WindowManager::surface_removed(uint32_t surface_id)
585 {
586     HMI_DEBUG("Delete surface_id %u", surface_id);
587     this->id_alloc.remove_id(surface_id);
588     // this->layers.remove_surface(surface_id);
589     g_app_list.removeSurface(surface_id);
590 }
591
592 void WindowManager::removeClient(const string &appid)
593 {
594     HMI_DEBUG("Remove clinet %s from list", appid.c_str());
595     auto client = g_app_list.lookUpClient(appid);
596     this->lc->terminateApp(client);
597     g_app_list.removeClient(appid);
598 }
599
600 void WindowManager::exceptionProcessForTransition()
601 {
602     unsigned req_num = g_app_list.currentRequestNumber();
603     HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
604     g_app_list.removeRequest(req_num);
605     HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
606     this->processNextRequest();
607 }
608
609 void WindowManager::timerHandler()
610 {
611     unsigned req_num = g_app_list.currentRequestNumber();
612     HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
613     g_app_list.reqDump();
614     g_app_list.removeRequest(req_num);
615     this->processNextRequest();
616 }
617
618 void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
619 {
620     WMError ret;
621     // req_num is guaranteed by Window Manager
622     unsigned req_num = g_app_list.currentRequestNumber();
623
624     if (actions.empty())
625     {
626         if (g_app_list.haveRequest())
627         {
628             HMI_SEQ_DEBUG(req_num, "There is no WMAction for this request");
629             goto proc_remove_request;
630         }
631         else
632         {
633             HMI_SEQ_DEBUG(req_num, "There is no request");
634             return;
635         }
636     }
637
638     for (auto &act : actions)
639     {
640         if ("" != act.role)
641         {
642             bool found;
643             auto const &surface_id = this->id_alloc.lookup(act.role.c_str());
644             if(surface_id == nullopt)
645             {
646                 goto proc_remove_request;
647             }
648             std::string appid = g_app_list.getAppID(*surface_id, &found);
649             if (!found)
650             {
651                 if (TaskVisible::INVISIBLE == act.visible)
652                 {
653                     // App is killed, so do not set this action
654                     continue;
655                 }
656                 else
657                 {
658                     HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
659                     ret = WMError::FAIL;
660                     goto error;
661                 }
662             }
663             auto client = g_app_list.lookUpClient(appid);
664             act.req_num = req_num;
665             act.client = client;
666         }
667
668         ret = g_app_list.setAction(req_num, act);
669         if (ret != WMError::SUCCESS)
670         {
671             HMI_SEQ_ERROR(req_num, "Setting action is failed");
672             goto error;
673         }
674     }
675
676     HMI_SEQ_DEBUG(req_num, "Start transition.");
677     ret = this->startTransition(req_num);
678     if (ret != WMError::SUCCESS)
679     {
680         if (ret == WMError::NO_LAYOUT_CHANGE)
681         {
682             goto proc_remove_request;
683         }
684         else
685         {
686             HMI_SEQ_ERROR(req_num, "Transition state is failed");
687             goto error;
688         }
689     }
690
691     return;
692
693 error:
694     //this->emit_error()
695     HMI_SEQ_ERROR(req_num, errorDescription(ret));
696     this->pmw.undoState();
697
698 proc_remove_request:
699     g_app_list.removeRequest(req_num);
700     this->processNextRequest();
701 }
702
703 void WindowManager::processError(WMError error)
704 {
705     unsigned req_num = g_app_list.currentRequestNumber();
706
707     //this->emit_error()
708     HMI_SEQ_ERROR(req_num, errorDescription(error));
709     g_app_list.removeRequest(req_num);
710     this->processNextRequest();
711 }
712
713 /*
714  ******* Private Functions *******
715  */
716
717 void WindowManager::emit_activated(char const *label)
718 {
719     this->send_event(kListEventName[Event_Active], label);
720 }
721
722 void WindowManager::emit_deactivated(char const *label)
723 {
724     this->send_event(kListEventName[Event_Inactive], label);
725 }
726
727 void WindowManager::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h)
728 {
729     this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h);
730 }
731
732 void WindowManager::emit_syncdraw(const string &role, const string &area)
733 {
734     rect rect = this->lc->getAreaSize(area);
735     this->send_event(kListEventName[Event_SyncDraw],
736         role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
737 }
738
739 void WindowManager::emit_flushdraw(char const *label)
740 {
741     this->send_event(kListEventName[Event_FlushDraw], label);
742 }
743
744 void WindowManager::emit_visible(char const *label, bool is_visible)
745 {
746     this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label);
747 }
748
749 void WindowManager::emit_invisible(char const *label)
750 {
751     return emit_visible(label, false);
752 }
753
754 void WindowManager::emit_visible(char const *label) { return emit_visible(label, true); }
755
756 void WindowManager::activate(int id)
757 {
758     // TODO: application requests by old role,
759     //       so convert role new to old for emitting event
760     /* const char* old_role = this->rolenew2old[label].c_str();
761
762     this->emit_visible(old_role);
763     this->emit_activated(old_role); */
764 }
765
766 void WindowManager::deactivate(int id)
767 {
768     // TODO: application requests by old role,
769     //       so convert role new to old for emitting event
770     /* const char* old_role = this->rolenew2old[label].c_str();
771
772     this->emit_deactivated(old_role);
773     this->emit_invisible(old_role); */
774 }
775
776 WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
777                             Task task, unsigned* req_num)
778 {
779     if (!g_app_list.contains(appid))
780     {
781         return WMError::NOT_REGISTERED;
782     }
783
784     auto client = g_app_list.lookUpClient(appid);
785
786     /*
787      * Queueing Phase
788      */
789     unsigned current = g_app_list.currentRequestNumber();
790     unsigned requested_num = g_app_list.getRequestNumber(appid);
791     if (requested_num != 0)
792     {
793         HMI_SEQ_INFO(requested_num,
794             "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
795         return REQ_REJECTED;
796     }
797
798     WMRequest req = WMRequest(appid, role, area, task);
799     unsigned new_req = g_app_list.addRequest(req);
800     *req_num = new_req;
801     g_app_list.reqDump();
802
803     HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
804
805     return WMError::SUCCESS;
806 }
807
808 WMError WindowManager::checkPolicy(unsigned req_num)
809 {
810     /*
811     * Check Policy
812     */
813     // get current trigger
814     bool found = false;
815     WMError ret = WMError::LAYOUT_CHANGE_FAIL;
816     auto trigger = g_app_list.getRequest(req_num, &found);
817     if (!found)
818     {
819         ret = WMError::NO_ENTRY;
820         return ret;
821     }
822     string req_area = trigger.area;
823
824     if (trigger.task == Task::TASK_ALLOCATE)
825     {
826         const char *msg = this->check_surface_exist(trigger.role.c_str());
827
828         if (msg)
829         {
830             HMI_SEQ_ERROR(req_num, msg);
831             return ret;
832         }
833     }
834
835     // Input event data to PolicyManager
836     if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
837     {
838         HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
839         return ret;
840     }
841
842     // Execute state transition of PolicyManager
843     if (0 > this->pmw.executeStateTransition())
844     {
845         HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
846         return ret;
847     }
848
849     ret = WMError::SUCCESS;
850
851     g_app_list.reqDump();
852
853     return ret;
854 }
855
856 WMError WindowManager::startTransition(unsigned req_num)
857 {
858     bool sync_draw_happen = false;
859     bool found = false;
860     WMError ret = WMError::SUCCESS;
861     auto actions = g_app_list.getActions(req_num, &found);
862     if (!found)
863     {
864         ret = WMError::NO_ENTRY;
865         HMI_SEQ_ERROR(req_num,
866             "Window Manager bug :%s : Action is not set", errorDescription(ret));
867         return ret;
868     }
869
870     g_app_list.reqDump();
871     for (const auto &action : actions)
872     {
873         if (action.visible == TaskVisible::VISIBLE)
874         {
875             sync_draw_happen = true;
876
877             // TODO: application requests by old role,
878             //       so convert role new to old for emitting event
879             string old_role = this->rolenew2old[action.role];
880
881             this->emit_syncdraw(old_role, action.area);
882             /* TODO: emit event for app not subscriber
883             if(g_app_list.contains(y.appid))
884                 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
885         }
886     }
887
888     if (sync_draw_happen)
889     {
890         this->setTimer();
891     }
892     else
893     {
894         // deactivate only, no syncDraw
895         // Make it deactivate here
896         for (const auto &x : actions)
897         {
898             this->lc->visibilityChange(x);
899             string old_role = this->rolenew2old[x.role];
900             emit_deactivated(old_role.c_str());
901
902             /* if (g_app_list.contains(x.appid))
903             {
904                 auto client = g_app_list.lookUpClient(x.appid);
905                 //this->deactivate(client->surfaceID(x.role));
906             } */
907         }
908         this->lc->renderLayers();
909         ret = WMError::NO_LAYOUT_CHANGE;
910     }
911     return ret;
912 }
913
914 WMError WindowManager::doEndDraw(unsigned req_num)
915 {
916     // get actions
917     bool found;
918     auto actions = g_app_list.getActions(req_num, &found);
919     WMError ret = WMError::SUCCESS;
920     if (!found)
921     {
922         ret = WMError::NO_ENTRY;
923         return ret;
924     }
925
926     HMI_SEQ_INFO(req_num, "do endDraw");
927
928     // layout change and make it visible
929     for (const auto &act : actions)
930     {
931         if(act.visible != TaskVisible::NO_CHANGE)
932         {
933             // layout change
934             ret = this->lc->layoutChange(act);
935             if(ret != WMError::SUCCESS)
936             {
937                 HMI_SEQ_WARNING(req_num,
938                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
939                 return ret;
940             }
941             ret = this->lc->visibilityChange(act);
942
943             // Emit active/deactive event
944             string old_role = this->rolenew2old[act.role];
945             if(act.visible == VISIBLE)
946             {
947                 emit_activated(old_role.c_str());
948             }
949             else
950             {
951                 emit_deactivated(old_role.c_str());
952             }
953
954             if (ret != WMError::SUCCESS)
955             {
956                 HMI_SEQ_WARNING(req_num,
957                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
958                 return ret;
959             }
960             HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
961         }
962     }
963     this->lc->renderLayers();
964
965     HMI_SEQ_INFO(req_num, "emit flushDraw");
966
967     for(const auto &act_flush : actions)
968     {
969         if(act_flush.visible == TaskVisible::VISIBLE)
970         {
971             // TODO: application requests by old role,
972             //       so convert role new to old for emitting event
973             string old_role = this->rolenew2old[act_flush.role];
974
975             this->emit_flushdraw(old_role.c_str());
976         }
977     }
978
979     return ret;
980 }
981
982 void WindowManager::emitScreenUpdated(unsigned req_num)
983 {
984     // Get visible apps
985     HMI_SEQ_DEBUG(req_num, "emit screen updated");
986     bool found = false;
987     auto actions = g_app_list.getActions(req_num, &found);
988
989     // create json object
990     json_object *j = json_object_new_object();
991     json_object *jarray = json_object_new_array();
992
993     for(const auto& action: actions)
994     {
995         if(action.visible != TaskVisible::INVISIBLE)
996         {
997             json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
998         }
999     }
1000     json_object_object_add(j, kKeyIds, jarray);
1001     HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
1002
1003     int ret = afb_event_push(
1004         this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
1005     if (ret != 0)
1006     {
1007         HMI_DEBUG("afb_event_push failed: %m");
1008     }
1009 }
1010
1011 void WindowManager::setTimer()
1012 {
1013     struct timespec ts;
1014     if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
1015         HMI_ERROR("Could't set time (clock_gettime() returns with error");
1016         return;
1017     }
1018
1019     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
1020     if (g_timer_ev_src == nullptr)
1021     {
1022         // firsttime set into sd_event
1023         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
1024             CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
1025         if (ret < 0)
1026         {
1027             HMI_ERROR("Could't set timer");
1028         }
1029     }
1030     else
1031     {
1032         // update timer limitation after second time
1033         sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
1034         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
1035     }
1036 }
1037
1038 void WindowManager::stopTimer()
1039 {
1040     unsigned req_num = g_app_list.currentRequestNumber();
1041     HMI_SEQ_DEBUG(req_num, "Timer stop");
1042     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
1043     if (rc < 0)
1044     {
1045         HMI_SEQ_ERROR(req_num, "Timer stop failed");
1046     }
1047 }
1048
1049 void WindowManager::processNextRequest()
1050 {
1051     g_app_list.next();
1052     g_app_list.reqDump();
1053     unsigned req_num = g_app_list.currentRequestNumber();
1054     if (g_app_list.haveRequest())
1055     {
1056         HMI_SEQ_DEBUG(req_num, "Process next request");
1057         WMError rc = checkPolicy(req_num);
1058         if (rc != WMError::SUCCESS)
1059         {
1060             HMI_SEQ_ERROR(req_num, errorDescription(rc));
1061         }
1062     }
1063     else
1064     {
1065         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
1066     }
1067 }
1068
1069 const char* WindowManager::convertRoleOldToNew(char const *old_role)
1070 {
1071     const char *new_role = nullptr;
1072
1073     for (auto const &on : this->roleold2new)
1074     {
1075         std::regex regex = std::regex(on.first);
1076         if (std::regex_match(old_role, regex))
1077         {
1078             // role is old. So convert to new.
1079             new_role = on.second.c_str();
1080             break;
1081         }
1082     }
1083
1084     if (nullptr == new_role)
1085     {
1086         // role is new or fallback.
1087         new_role = old_role;
1088     }
1089
1090     HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
1091
1092     return new_role;
1093 }
1094
1095 int WindowManager::loadOldRoleDb()
1096 {
1097     // Get afm application installed dir
1098     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
1099     HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
1100
1101     string file_name;
1102     if (!afm_app_install_dir)
1103     {
1104         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
1105     }
1106     else
1107     {
1108         file_name = string(afm_app_install_dir) + string("/etc/old_roles.db");
1109     }
1110
1111     // Load old_role.db
1112     json_object* json_obj;
1113     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
1114     if (0 > ret)
1115     {
1116         HMI_ERROR("Could not open old_role.db, so use default old_role information");
1117         json_obj = json_tokener_parse(kDefaultOldRoleDb);
1118     }
1119     HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
1120
1121     // Perse apps
1122     json_object* json_cfg;
1123     if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
1124     {
1125         HMI_ERROR("Parse Error!!");
1126         return -1;
1127     }
1128
1129     int len = json_object_array_length(json_cfg);
1130     HMI_DEBUG("json_cfg len:%d", len);
1131     HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
1132
1133     for (int i=0; i<len; i++)
1134     {
1135         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
1136
1137         const char* old_role = jh::getStringFromJson(json_tmp, "name");
1138         if (nullptr == old_role)
1139         {
1140             HMI_ERROR("Parse Error!!");
1141             return -1;
1142         }
1143
1144         const char* new_role = jh::getStringFromJson(json_tmp, "new");
1145         if (nullptr == new_role)
1146         {
1147             HMI_ERROR("Parse Error!!");
1148             return -1;
1149         }
1150
1151         this->roleold2new[old_role] = string(new_role);
1152     }
1153
1154     // Check
1155     for(auto itr = this->roleold2new.begin();
1156       itr != this->roleold2new.end(); ++itr)
1157     {
1158         HMI_DEBUG(">>> role old:%s new:%s",
1159                   itr->first.c_str(), itr->second.c_str());
1160     }
1161
1162     // Release json_object
1163     json_object_put(json_obj);
1164
1165     return 0;
1166 }
1167
1168 const char *WindowManager::check_surface_exist(const char *drawing_name)
1169 {
1170     auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
1171     if (!surface_id)
1172     {
1173         return "Surface does not exist";
1174     }
1175
1176     /* if (!this->controller->surface_exists(*surface_id))
1177     {
1178         return "Surface does not exist in controller!";
1179     } */
1180
1181     /* auto layer_id = this->layers.get_layer_id(*surface_id);
1182
1183     if (!layer_id)
1184     {
1185         return "Surface is not on any layer!";
1186     } */
1187
1188     HMI_DEBUG("surface %d is detected", *surface_id);
1189     return nullptr;
1190 }
1191
1192 const char* WindowManager::kDefaultOldRoleDb = "{ \
1193     \"old_roles\": [ \
1194         { \
1195             \"name\": \"HomeScreen\", \
1196             \"new\": \"homescreen\" \
1197         }, \
1198         { \
1199             \"name\": \"Music\", \
1200             \"new\": \"music\" \
1201         }, \
1202         { \
1203             \"name\": \"MediaPlayer\", \
1204             \"new\": \"music\" \
1205         }, \
1206         { \
1207             \"name\": \"Video\", \
1208             \"new\": \"video\" \
1209         }, \
1210         { \
1211             \"name\": \"VideoPlayer\", \
1212             \"new\": \"video\" \
1213         }, \
1214         { \
1215             \"name\": \"WebBrowser\", \
1216             \"new\": \"browser\" \
1217         }, \
1218         { \
1219             \"name\": \"Radio\", \
1220             \"new\": \"radio\" \
1221         }, \
1222         { \
1223             \"name\": \"Phone\", \
1224             \"new\": \"phone\" \
1225         }, \
1226         { \
1227             \"name\": \"Navigation\", \
1228             \"new\": \"map\" \
1229         }, \
1230         { \
1231             \"name\": \"HVAC\", \
1232             \"new\": \"hvac\" \
1233         }, \
1234         { \
1235             \"name\": \"Settings\", \
1236             \"new\": \"settings\" \
1237         }, \
1238         { \
1239             \"name\": \"Dashboard\", \
1240             \"new\": \"dashboard\" \
1241         }, \
1242         { \
1243             \"name\": \"POI\", \
1244             \"new\": \"poi\" \
1245         }, \
1246         { \
1247             \"name\": \"Mixer\", \
1248             \"new\": \"mixer\" \
1249         }, \
1250         { \
1251             \"name\": \"Restriction\", \
1252             \"new\": \"restriction\" \
1253         }, \
1254         { \
1255             \"name\": \"^OnScreen.*\", \
1256             \"new\": \"on_screen\" \
1257         } \
1258     ] \
1259 }";
1260
1261 } // namespace wm