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