Emit active/inactive
[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             string old_role = this->rolenew2old[x.role];
887             emit_deactivated(old_role.c_str());
888
889             /* if (g_app_list.contains(x.appid))
890             {
891                 auto client = g_app_list.lookUpClient(x.appid);
892                 //this->deactivate(client->surfaceID(x.role));
893             } */
894         }
895         this->lc->renderLayers();
896         ret = WMError::NO_LAYOUT_CHANGE;
897     }
898     return ret;
899 }
900
901 WMError WindowManager::doEndDraw(unsigned req_num)
902 {
903     // get actions
904     bool found;
905     auto actions = g_app_list.getActions(req_num, &found);
906     WMError ret = WMError::SUCCESS;
907     if (!found)
908     {
909         ret = WMError::NO_ENTRY;
910         return ret;
911     }
912
913     HMI_SEQ_INFO(req_num, "do endDraw");
914
915     // layout change and make it visible
916     for (const auto &act : actions)
917     {
918         if(act.visible != TaskVisible::NO_CHANGE)
919         {
920             // layout change
921             ret = this->lc->layoutChange(act);
922             if(ret != WMError::SUCCESS)
923             {
924                 HMI_SEQ_WARNING(req_num,
925                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
926                 return ret;
927             }
928             ret = this->lc->visibilityChange(act);
929
930             // Emit active/deactive event
931             string old_role = this->rolenew2old[act.role];
932             if(act.visible == VISIBLE)
933             {
934                 emit_activated(old_role.c_str());
935             }
936             else
937             {
938                 emit_deactivated(old_role.c_str());
939             }
940
941             if (ret != WMError::SUCCESS)
942             {
943                 HMI_SEQ_WARNING(req_num,
944                     "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
945                 return ret;
946             }
947             HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
948         }
949     }
950     this->lc->renderLayers();
951
952     HMI_SEQ_INFO(req_num, "emit flushDraw");
953
954     for(const auto &act_flush : actions)
955     {
956         if(act_flush.visible == TaskVisible::VISIBLE)
957         {
958             // TODO: application requests by old role,
959             //       so convert role new to old for emitting event
960             string old_role = this->rolenew2old[act_flush.role];
961
962             this->emit_flushdraw(old_role.c_str());
963         }
964     }
965
966     return ret;
967 }
968
969 void WindowManager::emitScreenUpdated(unsigned req_num)
970 {
971     // Get visible apps
972     HMI_SEQ_DEBUG(req_num, "emit screen updated");
973     bool found = false;
974     auto actions = g_app_list.getActions(req_num, &found);
975
976     // create json object
977     json_object *j = json_object_new_object();
978     json_object *jarray = json_object_new_array();
979
980     for(const auto& action: actions)
981     {
982         if(action.visible != TaskVisible::INVISIBLE)
983         {
984             json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
985         }
986     }
987     json_object_object_add(j, kKeyIds, jarray);
988     HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
989
990     int ret = afb_event_push(
991         this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
992     if (ret != 0)
993     {
994         HMI_DEBUG("afb_event_push failed: %m");
995     }
996 }
997
998 void WindowManager::setTimer()
999 {
1000     struct timespec ts;
1001     if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0) {
1002         HMI_ERROR("Could't set time (clock_gettime() returns with error");
1003         return;
1004     }
1005
1006     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
1007     if (g_timer_ev_src == nullptr)
1008     {
1009         // firsttime set into sd_event
1010         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
1011             CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
1012         if (ret < 0)
1013         {
1014             HMI_ERROR("Could't set timer");
1015         }
1016     }
1017     else
1018     {
1019         // update timer limitation after second time
1020         sd_event_source_set_time(g_timer_ev_src, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL);
1021         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
1022     }
1023 }
1024
1025 void WindowManager::stopTimer()
1026 {
1027     unsigned req_num = g_app_list.currentRequestNumber();
1028     HMI_SEQ_DEBUG(req_num, "Timer stop");
1029     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
1030     if (rc < 0)
1031     {
1032         HMI_SEQ_ERROR(req_num, "Timer stop failed");
1033     }
1034 }
1035
1036 void WindowManager::processNextRequest()
1037 {
1038     g_app_list.next();
1039     g_app_list.reqDump();
1040     unsigned req_num = g_app_list.currentRequestNumber();
1041     if (g_app_list.haveRequest())
1042     {
1043         HMI_SEQ_DEBUG(req_num, "Process next request");
1044         WMError rc = checkPolicy(req_num);
1045         if (rc != WMError::SUCCESS)
1046         {
1047             HMI_SEQ_ERROR(req_num, errorDescription(rc));
1048         }
1049     }
1050     else
1051     {
1052         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
1053     }
1054 }
1055
1056 const char* WindowManager::convertRoleOldToNew(char const *old_role)
1057 {
1058     const char *new_role = nullptr;
1059
1060     for (auto const &on : this->roleold2new)
1061     {
1062         std::regex regex = std::regex(on.first);
1063         if (std::regex_match(old_role, regex))
1064         {
1065             // role is old. So convert to new.
1066             new_role = on.second.c_str();
1067             break;
1068         }
1069     }
1070
1071     if (nullptr == new_role)
1072     {
1073         // role is new or fallback.
1074         new_role = old_role;
1075     }
1076
1077     HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
1078
1079     return new_role;
1080 }
1081
1082 int WindowManager::loadOldRoleDb()
1083 {
1084     // Get afm application installed dir
1085     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
1086     HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
1087
1088     string file_name;
1089     if (!afm_app_install_dir)
1090     {
1091         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
1092     }
1093     else
1094     {
1095         file_name = string(afm_app_install_dir) + string("/etc/old_roles.db");
1096     }
1097
1098     // Load old_role.db
1099     json_object* json_obj;
1100     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
1101     if (0 > ret)
1102     {
1103         HMI_ERROR("Could not open old_role.db, so use default old_role information");
1104         json_obj = json_tokener_parse(kDefaultOldRoleDb);
1105     }
1106     HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
1107
1108     // Perse apps
1109     json_object* json_cfg;
1110     if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
1111     {
1112         HMI_ERROR("Parse Error!!");
1113         return -1;
1114     }
1115
1116     int len = json_object_array_length(json_cfg);
1117     HMI_DEBUG("json_cfg len:%d", len);
1118     HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
1119
1120     for (int i=0; i<len; i++)
1121     {
1122         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
1123
1124         const char* old_role = jh::getStringFromJson(json_tmp, "name");
1125         if (nullptr == old_role)
1126         {
1127             HMI_ERROR("Parse Error!!");
1128             return -1;
1129         }
1130
1131         const char* new_role = jh::getStringFromJson(json_tmp, "new");
1132         if (nullptr == new_role)
1133         {
1134             HMI_ERROR("Parse Error!!");
1135             return -1;
1136         }
1137
1138         this->roleold2new[old_role] = string(new_role);
1139     }
1140
1141     // Check
1142     for(auto itr = this->roleold2new.begin();
1143       itr != this->roleold2new.end(); ++itr)
1144     {
1145         HMI_DEBUG(">>> role old:%s new:%s",
1146                   itr->first.c_str(), itr->second.c_str());
1147     }
1148
1149     // Release json_object
1150     json_object_put(json_obj);
1151
1152     return 0;
1153 }
1154
1155 const char *WindowManager::check_surface_exist(const char *drawing_name)
1156 {
1157     auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
1158     if (!surface_id)
1159     {
1160         return "Surface does not exist";
1161     }
1162
1163     /* if (!this->controller->surface_exists(*surface_id))
1164     {
1165         return "Surface does not exist in controller!";
1166     } */
1167
1168     /* auto layer_id = this->layers.get_layer_id(*surface_id);
1169
1170     if (!layer_id)
1171     {
1172         return "Surface is not on any layer!";
1173     } */
1174
1175     HMI_DEBUG("surface %d is detected", *surface_id);
1176     return nullptr;
1177 }
1178
1179 const char* WindowManager::kDefaultOldRoleDb = "{ \
1180     \"old_roles\": [ \
1181         { \
1182             \"name\": \"HomeScreen\", \
1183             \"new\": \"homescreen\" \
1184         }, \
1185         { \
1186             \"name\": \"Music\", \
1187             \"new\": \"music\" \
1188         }, \
1189         { \
1190             \"name\": \"MediaPlayer\", \
1191             \"new\": \"music\" \
1192         }, \
1193         { \
1194             \"name\": \"Video\", \
1195             \"new\": \"video\" \
1196         }, \
1197         { \
1198             \"name\": \"VideoPlayer\", \
1199             \"new\": \"video\" \
1200         }, \
1201         { \
1202             \"name\": \"WebBrowser\", \
1203             \"new\": \"browser\" \
1204         }, \
1205         { \
1206             \"name\": \"Radio\", \
1207             \"new\": \"radio\" \
1208         }, \
1209         { \
1210             \"name\": \"Phone\", \
1211             \"new\": \"phone\" \
1212         }, \
1213         { \
1214             \"name\": \"Navigation\", \
1215             \"new\": \"map\" \
1216         }, \
1217         { \
1218             \"name\": \"HVAC\", \
1219             \"new\": \"hvac\" \
1220         }, \
1221         { \
1222             \"name\": \"Settings\", \
1223             \"new\": \"settings\" \
1224         }, \
1225         { \
1226             \"name\": \"Dashboard\", \
1227             \"new\": \"dashboard\" \
1228         }, \
1229         { \
1230             \"name\": \"POI\", \
1231             \"new\": \"poi\" \
1232         }, \
1233         { \
1234             \"name\": \"Mixer\", \
1235             \"new\": \"mixer\" \
1236         }, \
1237         { \
1238             \"name\": \"Restriction\", \
1239             \"new\": \"restriction\" \
1240         }, \
1241         { \
1242             \"name\": \"^OnScreen.*\", \
1243             \"new\": \"on_screen\" \
1244         } \
1245     ] \
1246 }";
1247
1248 } // namespace wm