Convert the roles from old one to new
[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 namespace wm
30 {
31
32 static const unsigned kTimeOut = 3000000UL; /* 3s */
33
34 /* DrawingArea name used by "{layout}.{area}" */
35 const char kNameLayoutNormal[] = "normal";
36 const char kNameLayoutSplit[]  = "split";
37 const char kNameAreaFull[]     = "full";
38 const char kNameAreaMain[]     = "main";
39 const char kNameAreaSub[]      = "sub";
40
41 /* Key for json obejct */
42 const char kKeyDrawingName[] = "drawing_name";
43 const char kKeyDrawingArea[] = "drawing_area";
44 const char kKeyDrawingRect[] = "drawing_rect";
45 const char kKeyX[]           = "x";
46 const char kKeyY[]           = "y";
47 const char kKeyWidth[]       = "width";
48 const char kKeyHeight[]      = "height";
49 const char kKeyWidthPixel[]  = "width_pixel";
50 const char kKeyHeightPixel[] = "height_pixel";
51 const char kKeyWidthMm[]     = "width_mm";
52 const char kKeyHeightMm[]    = "height_mm";
53 const char kKeyIds[]         = "ids";
54
55 static sd_event_source *g_timer_ev_src = nullptr;
56 static AppList g_app_list;
57
58 namespace
59 {
60
61 using nlohmann::json;
62
63 result<json> file_to_json(char const *filename)
64 {
65     json j;
66     std::ifstream i(filename);
67     if (i.fail())
68     {
69         HMI_DEBUG("wm", "Could not open config file, so use default layer information");
70         j = default_layers_json;
71     }
72     else
73     {
74         i >> j;
75     }
76
77     return Ok(j);
78 }
79
80 struct result<layer_map> load_layer_map(char const *filename)
81 {
82     HMI_DEBUG("wm", "loading IDs from %s", filename);
83
84     auto j = file_to_json(filename);
85     if (j.is_err())
86     {
87         return Err<layer_map>(j.unwrap_err());
88     }
89     json jids = j.unwrap();
90
91     return to_layer_map(jids);
92 }
93
94 static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
95 {
96     HMI_NOTICE("wm", "Time out occurs because the client replys endDraw slow, so revert the request");
97     reinterpret_cast<wm::WindowManager *>(userdata)->timerHandler();
98     return 0;
99 }
100
101 } // namespace
102
103 /**
104  * WindowManager Impl
105  */
106 WindowManager::WindowManager(wl::display *d)
107     : chooks{this},
108       display{d},
109       controller{},
110       outputs(),
111       layers(),
112       id_alloc{},
113       pending_events(false)
114 {
115     char const *path_layers_json = getenv("AFM_APP_INSTALL_DIR");
116     std::string path;
117     if (!path_layers_json)
118     {
119         HMI_ERROR("wm", "AFM_APP_INSTALL_DIR is not defined");
120         path = std::string(path_layers_json);
121     }
122     else
123     {
124         path = std::string(path_layers_json) + std::string("/etc/layers.json");
125     }
126
127     try
128     {
129         {
130             auto l = load_layer_map(path.c_str());
131             if (l.is_ok())
132             {
133                 this->layers = l.unwrap();
134             }
135             else
136             {
137                 HMI_ERROR("wm", "%s", l.err().value());
138             }
139         }
140     }
141     catch (std::exception &e)
142     {
143         HMI_ERROR("wm", "Loading of configuration failed: %s", e.what());
144     }
145 }
146
147 int WindowManager::init()
148 {
149     if (!this->display->ok())
150     {
151         return -1;
152     }
153
154     if (this->layers.mapping.empty())
155     {
156         HMI_ERROR("wm", "No surface -> layer mapping loaded");
157         return -1;
158     }
159
160     // TODO: application requests by old role,
161     //       so create role map (old, new)
162     // Load old_role.db
163     this->loadOldRoleDb();
164
165     // Make afb event
166     for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
167     {
168         map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i]);
169     }
170
171     this->display->add_global_handler(
172         "wl_output", [this](wl_registry *r, uint32_t name, uint32_t v) {
173             this->outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
174         });
175
176     this->display->add_global_handler(
177         "ivi_wm", [this](wl_registry *r, uint32_t name, uint32_t v) {
178             this->controller =
179                 std::make_unique<struct compositor::controller>(r, name, v);
180
181             // Init controller hooks
182             this->controller->chooks = &this->chooks;
183
184             // This protocol needs the output, so lets just add our mapping here...
185             this->controller->add_proxy_to_id_mapping(
186                 this->outputs.back()->proxy.get(),
187                 wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>(
188                     this->outputs.back()->proxy.get())));
189
190             // Create screen
191             this->controller->create_screen(this->outputs.back()->proxy.get());
192
193             // Set display to controller
194             this->controller->display = this->display;
195         });
196
197     // First level objects
198     this->display->roundtrip();
199     // Second level objects
200     this->display->roundtrip();
201     // Third level objects
202     this->display->roundtrip();
203
204     return init_layers();
205 }
206
207 int WindowManager::dispatch_pending_events()
208 {
209     if (this->pop_pending_events())
210     {
211         this->display->dispatch_pending();
212         return 0;
213     }
214     return -1;
215 }
216
217 void WindowManager::set_pending_events()
218 {
219     this->pending_events.store(true, std::memory_order_release);
220 }
221
222 result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
223 {
224     // TODO: application requests by old role,
225     //       so convert role old to new
226     const char *role = this->convertRoleOldToNew(drawing_name);
227
228     auto lid = this->layers.get_layer_id(std::string(role));
229     if (!lid)
230     {
231         /**
232        * register drawing_name as fallback and make it displayed.
233        */
234         lid = this->layers.get_layer_id(std::string("fallback"));
235         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", role);
236         if (!lid)
237         {
238             return Err<int>("Drawing name does not match any role, Fallback is disabled");
239         }
240     }
241
242     auto rname = this->lookup_id(role);
243     if (!rname)
244     {
245         // name does not exist yet, allocate surface id...
246         auto id = int(this->id_alloc.generate_id(role));
247         this->layers.add_surface(id, *lid);
248
249         // set the main_surface[_name] here and now
250         if (!this->layers.main_surface_name.empty() &&
251             this->layers.main_surface_name == drawing_name)
252         {
253             this->layers.main_surface = id;
254             HMI_DEBUG("wm", "Set main_surface id to %u", id);
255         }
256
257         // add client into the db
258         std::string appid_str(appid);
259         g_app_list.addClient(appid_str, *lid, id, std::string(role));
260
261         // Set role map of (new, old)
262         this->rolenew2old[role] = std::string(drawing_name);
263
264         return Ok<int>(id);
265     }
266
267     // Check currently registered drawing names if it is already there.
268     return Err<int>("Surface already present");
269 }
270
271 char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
272                                      char const *ivi_id)
273 {
274     ST();
275
276     // TODO: application requests by old role,
277     //       so convert role old to new
278     const char *role = this->convertRoleOldToNew(drawing_name);
279
280     auto lid = this->layers.get_layer_id(std::string(role));
281     unsigned sid = std::stol(ivi_id);
282
283     if (!lid)
284     {
285         /**
286        * register drawing_name as fallback and make it displayed.
287        */
288         lid = this->layers.get_layer_id(std::string("fallback"));
289         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", role);
290         if (!lid)
291         {
292             return "Drawing name does not match any role, Fallback is disabled";
293         }
294     }
295
296     auto rname = this->lookup_id(role);
297
298     if (rname)
299     {
300         return "Surface already present";
301     }
302
303     // register pair drawing_name and ivi_id
304     this->id_alloc.register_name_id(role, sid);
305     this->layers.add_surface(sid, *lid);
306
307     // this surface is already created
308     HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", sid, *lid);
309
310     this->controller->layers[*lid]->add_surface(sid);
311     this->layout_commit();
312
313     // add client into the db
314     std::string appid_str(appid);
315     g_app_list.addClient(appid_str, *lid, sid, std::string(role));
316
317     // Set role map of (new, old)
318     this->rolenew2old[role] = std::string(drawing_name);
319
320     return nullptr;
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     ST();
327
328     // TODO: application requests by old role,
329     //       so convert role old to new
330     const char *c_role = this->convertRoleOldToNew(drawing_name);
331
332     std::string id = appid;
333     std::string role = c_role;
334     std::string area = drawing_area;
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     if(ret != WMError::SUCCESS)
342     {
343         HMI_ERROR("wm", errorDescription(ret));
344         reply("Failed to set request");
345         return;
346     }
347
348     reply(nullptr);
349     if (req_num != g_app_list.currentRequestNumber())
350     {
351         // Add request, then invoked after the previous task is finished
352         HMI_SEQ_DEBUG(req_num, "request is accepted");
353         return;
354     }
355
356     /*
357      * Do allocate tasks
358      */
359     ret = this->doTransition(req_num);
360
361     if (ret != WMError::SUCCESS)
362     {
363         //this->emit_error()
364         HMI_SEQ_ERROR(req_num, errorDescription(ret));
365         g_app_list.removeRequest(req_num);
366         this->processNextRequest();
367     }
368 }
369
370 void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name,
371                                  const reply_func &reply)
372 {
373     ST();
374
375     // TODO: application requests by old role,
376     //       so convert role old to new
377     const char *c_role = this->convertRoleOldToNew(drawing_name);
378
379     /*
380     * Check Phase
381     */
382     std::string id = appid;
383     std::string role = c_role;
384     std::string area = ""; //drawing_area;
385     Task task = Task::TASK_RELEASE;
386     unsigned req_num = 0;
387     WMError ret = WMError::UNKNOWN;
388
389     ret = this->setRequest(id, role, area, task, &req_num);
390
391     if (ret != WMError::SUCCESS)
392     {
393         HMI_ERROR("wm", errorDescription(ret));
394         reply("Failed to set request");
395         return;
396     }
397
398     reply(nullptr);
399     if (req_num != g_app_list.currentRequestNumber())
400     {
401         // Add request, then invoked after the previous task is finished
402         HMI_SEQ_DEBUG(req_num, "request is accepted");
403         return;
404     }
405
406     /*
407     * Do allocate tasks
408     */
409     ret = this->doTransition(req_num);
410
411     if (ret != WMError::SUCCESS)
412     {
413         //this->emit_error()
414         HMI_SEQ_ERROR(req_num, errorDescription(ret));
415         g_app_list.removeRequest(req_num);
416         this->processNextRequest();
417     }
418 }
419
420 void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
421 {
422     // TODO: application requests by old role,
423     //       so convert role old to new
424     const char *c_role = this->convertRoleOldToNew(drawing_name);
425
426     std::string id = appid;
427     std::string role = c_role;
428     unsigned current_req = g_app_list.currentRequestNumber();
429     bool result = g_app_list.setEndDrawFinished(current_req, id, role);
430
431     if (!result)
432     {
433         HMI_ERROR("wm", "%s is not in transition state", id.c_str());
434         return;
435     }
436
437     if (g_app_list.endDrawFullfilled(current_req))
438     {
439         // do task for endDraw
440         this->stopTimer();
441         WMError ret = this->doEndDraw(current_req);
442
443         if(ret != WMError::SUCCESS)
444         {
445             //this->emit_error();
446         }
447         this->emitScreenUpdated(current_req);
448         HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
449
450         g_app_list.removeRequest(current_req);
451
452         this->processNextRequest();
453     }
454     else
455     {
456         HMI_SEQ_INFO(current_req, "Wait other App call endDraw");
457         return;
458     }
459 }
460
461 result<json_object *> WindowManager::api_get_display_info()
462 {
463     // Check controller
464     if (!this->controller)
465     {
466         return Err<json_object *>("ivi_controller global not available");
467     }
468
469     // Set display info
470     compositor::size o_size = this->controller->output_size;
471     compositor::size p_size = this->controller->physical_size;
472
473     json_object *object = json_object_new_object();
474     json_object_object_add(object, kKeyWidthPixel, json_object_new_int(o_size.w));
475     json_object_object_add(object, kKeyHeightPixel, json_object_new_int(o_size.h));
476     json_object_object_add(object, kKeyWidthMm, json_object_new_int(p_size.w));
477     json_object_object_add(object, kKeyHeightMm, json_object_new_int(p_size.h));
478
479     return Ok<json_object *>(object);
480 }
481
482 result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
483 {
484     HMI_DEBUG("wm", "called");
485
486     // TODO: application requests by old role,
487     //       so convert role old to new
488     const char *role = this->convertRoleOldToNew(drawing_name);
489
490     // Check drawing name, surface/layer id
491     auto const &surface_id = this->lookup_id(role);
492     if (!surface_id)
493     {
494         return Err<json_object *>("Surface does not exist");
495     }
496
497     if (!this->controller->surface_exists(*surface_id))
498     {
499         return Err<json_object *>("Surface does not exist in controller!");
500     }
501
502     auto layer_id = this->layers.get_layer_id(*surface_id);
503     if (!layer_id)
504     {
505         return Err<json_object *>("Surface is not on any layer!");
506     }
507
508     auto o_state = *this->layers.get_layout_state(*surface_id);
509     if (o_state == nullptr)
510     {
511         return Err<json_object *>("Could not find layer for surface");
512     }
513
514     struct LayoutState &state = *o_state;
515     if ((state.main != *surface_id) && (state.sub != *surface_id))
516     {
517         return Err<json_object *>("Surface is inactive");
518     }
519
520     // Set area rectangle
521     compositor::rect area_info = this->area_info[*surface_id];
522     json_object *object = json_object_new_object();
523     json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
524     json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
525     json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w));
526     json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
527
528     return Ok<json_object *>(object);
529 }
530
531 void WindowManager::api_ping() { this->dispatch_pending_events(); }
532
533 void WindowManager::send_event(char const *evname, char const *label)
534 {
535     HMI_DEBUG("wm", "%s: %s(%s)", __func__, evname, label);
536
537     json_object *j = json_object_new_object();
538     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
539
540     int ret = afb_event_push(this->map_afb_event[evname], j);
541     if (ret != 0)
542     {
543         HMI_DEBUG("wm", "afb_event_push failed: %m");
544     }
545 }
546
547 void WindowManager::send_event(char const *evname, char const *label, char const *area,
548                      int x, int y, int w, int h)
549 {
550     HMI_DEBUG("wm", "%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
551               __func__, evname, label, area, x, y, w, h);
552
553     json_object *j_rect = json_object_new_object();
554     json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
555     json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
556     json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
557     json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
558
559     json_object *j = json_object_new_object();
560     json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
561     json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area));
562     json_object_object_add(j, kKeyDrawingRect, j_rect);
563
564     int ret = afb_event_push(this->map_afb_event[evname], j);
565     if (ret != 0)
566     {
567         HMI_DEBUG("wm", "afb_event_push failed: %m");
568     }
569 }
570
571 /**
572  * proxied events
573  */
574 void WindowManager::surface_created(uint32_t surface_id)
575 {
576     auto layer_id = this->layers.get_layer_id(surface_id);
577     if (!layer_id)
578     {
579         HMI_DEBUG("wm", "Newly created surfce %d is not associated with any layer!",
580                   surface_id);
581         return;
582     }
583
584     HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", surface_id, *layer_id);
585
586     this->controller->layers[*layer_id]->add_surface(surface_id);
587     this->layout_commit();
588 }
589
590 void WindowManager::surface_removed(uint32_t surface_id)
591 {
592     HMI_DEBUG("wm", "surface_id is %u", surface_id);
593     g_app_list.removeSurface(surface_id);
594 }
595
596 void WindowManager::removeClient(const std::string &appid)
597 {
598     HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str());
599     g_app_list.removeClient(appid);
600 }
601
602 void WindowManager::exceptionProcessForTransition()
603 {
604     unsigned req_num = g_app_list.currentRequestNumber();
605     HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num);
606     g_app_list.removeRequest(req_num);
607     HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists");
608     this->processNextRequest();
609 }
610
611 void WindowManager::timerHandler()
612 {
613     unsigned req_num = g_app_list.currentRequestNumber();
614     HMI_SEQ_DEBUG(req_num, "Timer expired remove Request");
615     g_app_list.reqDump();
616     g_app_list.removeRequest(req_num);
617     this->processNextRequest();
618 }
619
620 /*
621  ******* Private Functions *******
622  */
623
624 bool WindowManager::pop_pending_events()
625 {
626     bool x{true};
627     return this->pending_events.compare_exchange_strong(
628         x, false, std::memory_order_consume);
629 }
630
631 optional<int> WindowManager::lookup_id(char const *name)
632 {
633     return this->id_alloc.lookup(std::string(name));
634 }
635 optional<std::string> WindowManager::lookup_name(int id)
636 {
637     return this->id_alloc.lookup(id);
638 }
639
640 /**
641  * init_layers()
642  */
643 int WindowManager::init_layers()
644 {
645     if (!this->controller)
646     {
647         HMI_ERROR("wm", "ivi_controller global not available");
648         return -1;
649     }
650
651     if (this->outputs.empty())
652     {
653         HMI_ERROR("wm", "no output was set up!");
654         return -1;
655     }
656
657     auto &c = this->controller;
658
659     auto &o = this->outputs.front();
660     auto &s = c->screens.begin()->second;
661     auto &layers = c->layers;
662
663     // Write output dimensions to ivi controller...
664     c->output_size = compositor::size{uint32_t(o->width), uint32_t(o->height)};
665     c->physical_size = compositor::size{uint32_t(o->physical_width),
666                                         uint32_t(o->physical_height)};
667
668     // Clear scene
669     layers.clear();
670
671     // Clear screen
672     s->clear();
673
674     // Quick and dirty setup of layers
675     for (auto const &i : this->layers.mapping)
676     {
677         c->layer_create(i.second.layer_id, o->width, o->height);
678         auto &l = layers[i.second.layer_id];
679         l->set_destination_rectangle(0, 0, o->width, o->height);
680         l->set_visibility(1);
681         HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"",
682                   i.second.name.c_str(), i.second.layer_id, i.second.role.c_str());
683     }
684
685     // Add layers to screen
686     s->set_render_order(this->layers.layers);
687
688     this->layout_commit();
689
690     this->layers.setupArea(o->width, o->height);
691
692     return 0;
693 }
694
695 void WindowManager::surface_set_layout(int surface_id, const std::string& area)
696 {
697     if (!this->controller->surface_exists(surface_id))
698     {
699         HMI_ERROR("wm", "Surface %d does not exist", surface_id);
700         return;
701     }
702
703     auto o_layer_id = this->layers.get_layer_id(surface_id);
704
705     if (!o_layer_id)
706     {
707         HMI_ERROR("wm", "Surface %d is not associated with any layer!", surface_id);
708         return;
709     }
710
711     uint32_t layer_id = *o_layer_id;
712
713     auto const &layer = this->layers.get_layer(layer_id);
714     auto rect = this->layers.getAreaSize(area);
715     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "%s : x:%d y:%d w:%d h:%d", area.c_str(),
716                     rect.x, rect.y, rect.w, rect.h);
717     auto &s = this->controller->surfaces[surface_id];
718
719     int x = rect.x;
720     int y = rect.y;
721     int w = rect.w;
722     int h = rect.h;
723
724     // less-than-0 values refer to MAX + 1 - $VALUE
725     // e.g. MAX is either screen width or height
726     if (w < 0)
727     {
728         w = this->controller->output_size.w + 1 + w;
729     }
730     if (h < 0)
731     {
732         h = this->controller->output_size.h + 1 + h;
733     }
734
735     HMI_DEBUG("wm", "surface_set_layout for surface %u on layer %u", surface_id,
736               layer_id);
737
738     // set destination to the display rectangle
739     s->set_destination_rectangle(x, y, w, h);
740
741     // update area information
742     this->area_info[surface_id].x = x;
743     this->area_info[surface_id].y = y;
744     this->area_info[surface_id].w = w;
745     this->area_info[surface_id].h = h;
746
747     HMI_DEBUG("wm", "Surface %u now on layer %u with rect { %d, %d, %d, %d }",
748               surface_id, layer_id, x, y, w, h);
749 }
750
751 void WindowManager::layout_commit()
752 {
753     this->controller->commit_changes();
754     this->display->flush();
755 }
756
757 void WindowManager::emit_activated(char const *label)
758 {
759     this->send_event(kListEventName[Event_Active], label);
760 }
761
762 void WindowManager::emit_deactivated(char const *label)
763 {
764     this->send_event(kListEventName[Event_Inactive], label);
765 }
766
767 void WindowManager::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h)
768 {
769     this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h);
770 }
771
772 void WindowManager::emit_syncdraw(const std::string &role, const std::string &area)
773 {
774     compositor::rect rect = this->layers.getAreaSize(area);
775     this->send_event(kListEventName[Event_SyncDraw],
776         role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
777 }
778
779 void WindowManager::emit_flushdraw(char const *label)
780 {
781     this->send_event(kListEventName[Event_FlushDraw], label);
782 }
783
784 void WindowManager::emit_visible(char const *label, bool is_visible)
785 {
786     this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label);
787 }
788
789 void WindowManager::emit_invisible(char const *label)
790 {
791     return emit_visible(label, false);
792 }
793
794 void WindowManager::emit_visible(char const *label) { return emit_visible(label, true); }
795
796 void WindowManager::activate(int id)
797 {
798     auto ip = this->controller->sprops.find(id);
799     if (ip != this->controller->sprops.end())
800     {
801         this->controller->surfaces[id]->set_visibility(1);
802         char const *label =
803             this->lookup_name(id).value_or("unknown-name").c_str();
804
805          // FOR CES DEMO >>>
806         if ((0 == strcmp(label, "radio")) ||
807             (0 == strcmp(label, "music")) ||
808             (0 == strcmp(label, "video")) ||
809             (0 == strcmp(label, "map")))
810         {
811             for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i)
812             {
813                 if (id == *i)
814                 {
815                     // Remove id
816                     this->surface_bg.erase(i);
817
818                     // Remove from BG layer (999)
819                     HMI_DEBUG("wm", "Remove %s(%d) from BG layer", label, id);
820                     this->controller->layers[999]->remove_surface(id);
821
822                     // Add to FG layer (1001)
823                     HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id);
824                     this->controller->layers[1001]->add_surface(id);
825
826                     for (int j : this->surface_bg)
827                     {
828                         HMI_DEBUG("wm", "Stored id:%d", j);
829                     }
830                     break;
831                 }
832             }
833         }
834         // <<< FOR CES DEMO
835
836         this->layout_commit();
837
838         // TODO: application requests by old role,
839         //       so convert role new to old for emitting event
840         const char* old_role = this->rolenew2old[label].c_str();
841
842         this->emit_visible(old_role);
843         this->emit_activated(old_role);
844     }
845 }
846
847 void WindowManager::deactivate(int id)
848 {
849     auto ip = this->controller->sprops.find(id);
850     if (ip != this->controller->sprops.end())
851     {
852         char const *label =
853             this->lookup_name(id).value_or("unknown-name").c_str();
854
855         // FOR CES DEMO >>>
856         if ((0 == strcmp(label, "radio")) ||
857             (0 == strcmp(label, "music")) ||
858             (0 == strcmp(label, "video")) ||
859             (0 == strcmp(label, "map")))
860         {
861
862             // Store id
863             this->surface_bg.push_back(id);
864
865             // Remove from FG layer (1001)
866             HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id);
867             this->controller->layers[1001]->remove_surface(id);
868
869             // Add to BG layer (999)
870             HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id);
871             this->controller->layers[999]->add_surface(id);
872
873             for (int j : surface_bg)
874             {
875                 HMI_DEBUG("wm", "Stored id:%d", j);
876             }
877         }
878         else
879         {
880             this->controller->surfaces[id]->set_visibility(0);
881         }
882         // <<< FOR CES DEMO
883
884         this->layout_commit();
885
886         // TODO: application requests by old role,
887         //       so convert role new to old for emitting event
888         const char* old_role = this->rolenew2old[label].c_str();
889
890         this->emit_deactivated(old_role);
891         this->emit_invisible(old_role);
892     }
893 }
894
895 WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area,
896                             Task task, unsigned* req_num)
897 {
898     if (!g_app_list.contains(appid))
899     {
900         return WMError::NOT_REGISTERED;
901     }
902
903     auto client = g_app_list.lookUpClient(appid);
904
905     /*
906      * Queueing Phase
907      */
908     unsigned current = g_app_list.currentRequestNumber();
909     unsigned requested_num = g_app_list.getRequestNumber(appid);
910     if (requested_num != 0)
911     {
912         HMI_SEQ_INFO(requested_num,
913             "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
914         return REQ_REJECTED;
915     }
916
917     WMRequest req = WMRequest(appid, role, area, task);
918     unsigned new_req = g_app_list.addRequest(req);
919     *req_num = new_req;
920     g_app_list.reqDump();
921
922     HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
923
924     return WMError::SUCCESS;
925 }
926
927 WMError WindowManager::doTransition(unsigned req_num)
928 {
929     HMI_SEQ_DEBUG(req_num, "check policy");
930     WMError ret = this->checkPolicy(req_num);
931     if (ret != WMError::SUCCESS)
932     {
933         return ret;
934     }
935     HMI_SEQ_DEBUG(req_num, "Start transition.");
936     ret = this->startTransition(req_num);
937     return ret;
938 }
939
940 WMError WindowManager::checkPolicy(unsigned req_num)
941 {
942     /*
943     * Check Policy
944     */
945     // get current trigger
946     bool found = false;
947     bool split = false;
948     WMError ret = WMError::LAYOUT_CHANGE_FAIL;
949     auto trigger = g_app_list.getRequest(req_num, &found);
950     if (!found)
951     {
952         ret = WMError::NO_ENTRY;
953         return ret;
954     }
955     std::string req_area = trigger.area;
956
957     // >>>> Compatible with current window manager until policy manager coming
958     if (trigger.task == Task::TASK_ALLOCATE)
959     {
960         HMI_SEQ_DEBUG(req_num, "Check split or not");
961         const char *msg = this->check_surface_exist(trigger.role.c_str());
962
963         if (msg)
964         {
965             HMI_SEQ_ERROR(req_num, msg);
966             ret = WMError::LAYOUT_CHANGE_FAIL;
967             return ret;
968         }
969
970         auto const &surface_id = this->lookup_id(trigger.role.c_str());
971         auto o_state = *this->layers.get_layout_state(*surface_id);
972         struct LayoutState &state = *o_state;
973
974         unsigned curernt_sid = state.main;
975         split = this->can_split(state, *surface_id);
976
977         if (split)
978         {
979             HMI_SEQ_DEBUG(req_num, "Split happens");
980             // Get current visible role
981             std::string add_role = this->lookup_name(state.main).value();
982             // Set next area
983             std::string add_area = std::string(kNameLayoutSplit) + "." + std::string(kNameAreaMain);
984             // Change request area
985             req_area = std::string(kNameLayoutSplit) + "." + std::string(kNameAreaSub);
986             HMI_SEQ_NOTICE(req_num, "Change request area from %s to %s, because split happens",
987                                 trigger.area.c_str(), req_area.c_str());
988             // set another action
989             std::string add_name = g_app_list.getAppID(curernt_sid, add_role, &found);
990             if (!found)
991             {
992                 HMI_SEQ_ERROR(req_num, "Couldn't widhdraw with surfaceID : %d", curernt_sid);
993                 ret = WMError::NOT_REGISTERED;
994                 return ret;
995             }
996             HMI_SEQ_INFO(req_num, "Additional split app %s, role: %s, area: %s",
997                          add_name.c_str(), add_role.c_str(), add_area.c_str());
998             // Set split action
999             bool end_draw_finished = false;
1000             WMAction split_action{
1001                 add_name,
1002                 add_role,
1003                 add_area,
1004                 TaskVisible::VISIBLE,
1005                 end_draw_finished};
1006             WMError ret = g_app_list.setAction(req_num, split_action);
1007             if (ret != WMError::SUCCESS)
1008             {
1009                 HMI_SEQ_ERROR(req_num, "Failed to set action");
1010                 return ret;
1011             }
1012             g_app_list.reqDump();
1013         }
1014     }
1015     else
1016     {
1017         HMI_SEQ_DEBUG(req_num, "split doesn't happen");
1018     }
1019
1020     // Set invisible task(Remove if policy manager finish)
1021     ret = this->setInvisibleTask(trigger.role, split);
1022     if(ret != WMError::SUCCESS)
1023     {
1024         HMI_SEQ_ERROR(req_num, "Failed to set invisible task: %s", errorDescription(ret));
1025         return ret;
1026     }
1027
1028     /*  get new status from Policy Manager */
1029     HMI_SEQ_NOTICE(req_num, "ATM, Policy manager does't exist, then set WMAction as is");
1030     if(trigger.role == "homescreen")
1031     {
1032         // TODO : Remove when Policy Manager completed
1033         HMI_SEQ_NOTICE(req_num, "Hack. This process will be removed. Change HomeScreen code!!");
1034         req_area = "fullscreen";
1035     }
1036     TaskVisible task_visible =
1037         (trigger.task == Task::TASK_ALLOCATE) ? TaskVisible::VISIBLE : TaskVisible::INVISIBLE;
1038
1039     ret = g_app_list.setAction(req_num, trigger.appid, trigger.role, req_area, task_visible);
1040     g_app_list.reqDump();
1041
1042     return ret;
1043 }
1044
1045 WMError WindowManager::startTransition(unsigned req_num)
1046 {
1047     bool sync_draw_happen = false;
1048     bool found = false;
1049     WMError ret = WMError::SUCCESS;
1050     auto actions = g_app_list.getActions(req_num, &found);
1051     if (!found)
1052     {
1053         ret = WMError::NO_ENTRY;
1054         HMI_SEQ_ERROR(req_num,
1055             "Window Manager bug :%s : Action is not set", errorDescription(ret));
1056         return ret;
1057     }
1058
1059     for (const auto &action : actions)
1060     {
1061         if (action.visible != TaskVisible::INVISIBLE)
1062         {
1063             sync_draw_happen = true;
1064
1065             // TODO: application requests by old role,
1066             //       so convert role new to old for emitting event
1067             std::string old_role = this->rolenew2old[action.role];
1068
1069             this->emit_syncdraw(old_role, action.area);
1070             /* TODO: emit event for app not subscriber
1071             if(g_app_list.contains(y.appid))
1072                 g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
1073         }
1074     }
1075
1076     if (sync_draw_happen)
1077     {
1078         this->setTimer();
1079     }
1080     else
1081     {
1082         // deactivate only, no syncDraw
1083         // Make it deactivate here
1084         for (const auto &x : actions)
1085         {
1086             if (g_app_list.contains(x.appid))
1087             {
1088                 auto client = g_app_list.lookUpClient(x.appid);
1089                 this->deactivate(client->surfaceID(x.role));
1090             }
1091         }
1092         ret = NO_LAYOUT_CHANGE;
1093     }
1094     return ret;
1095 }
1096
1097 WMError WindowManager::setInvisibleTask(const std::string &role, bool split)
1098 {
1099     unsigned req_num = g_app_list.currentRequestNumber();
1100     HMI_SEQ_DEBUG(req_num, "set current visible app to invisible task");
1101     // This task is copied from original actiavete surface
1102     const char *drawing_name = this->rolenew2old[role].c_str();
1103     auto const &surface_id = this->lookup_id(role.c_str());
1104     auto layer_id = this->layers.get_layer_id(*surface_id);
1105     auto o_state = *this->layers.get_layout_state(*surface_id);
1106     struct LayoutState &state = *o_state;
1107     std::string add_name, add_role;
1108     std::string add_area = "";
1109     int surface;
1110     TaskVisible task_visible = TaskVisible::INVISIBLE;
1111     bool end_draw_finished = true;
1112     bool found = false;
1113
1114     for (auto const &l : this->layers.mapping)
1115     {
1116         if (l.second.layer_id <= *layer_id)
1117         {
1118             continue;
1119         }
1120         HMI_DEBUG("wm", "debug: main %d , sub : %d", l.second.state.main, l.second.state.sub);
1121         if (l.second.state.main != -1)
1122         {
1123             //this->deactivate(l.second.state.main);
1124             surface = l.second.state.main;
1125             add_role = *this->id_alloc.lookup(surface);
1126             add_name = g_app_list.getAppID(surface, add_role, &found);
1127             if(!found){
1128                 return WMError::NOT_REGISTERED;
1129             }
1130             HMI_SEQ_INFO(req_num, "Invisible %s", add_name.c_str());
1131             WMAction act{add_name, add_role, add_area, task_visible, end_draw_finished};
1132             g_app_list.setAction(req_num, act);
1133             l.second.state.main = -1;
1134         }
1135
1136         if (l.second.state.sub != -1)
1137         {
1138             //this->deactivate(l.second.state.sub);
1139             surface = l.second.state.sub;
1140             add_role = *this->id_alloc.lookup(surface);
1141             add_name = g_app_list.getAppID(surface, add_role, &found);
1142             if (!found)
1143             {
1144                 return WMError::NOT_REGISTERED;
1145             }
1146             HMI_SEQ_INFO(req_num, "Invisible %s", add_name.c_str());
1147             WMAction act{add_name, add_role, add_area, task_visible, end_draw_finished};
1148             g_app_list.setAction(req_num, act);
1149             l.second.state.sub = -1;
1150         }
1151     }
1152
1153     // change current state here, but this is hack
1154     auto layer = this->layers.get_layer(*layer_id);
1155
1156     if (state.main == -1)
1157     {
1158         HMI_DEBUG("wm", "Layout: %s", kNameLayoutNormal);
1159     }
1160     else
1161     {
1162         if (0 != strcmp(drawing_name, "HomeScreen"))
1163         {
1164             if (split)
1165             {
1166                 if (state.sub != *surface_id)
1167                 {
1168                     if (state.sub != -1)
1169                     {
1170                         //this->deactivate(state.sub);
1171                         WMAction deact_sub;
1172                         deact_sub.role =
1173                             std::move(*this->id_alloc.lookup(state.sub));
1174                         deact_sub.area = add_area;
1175                         deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found);
1176                         if (!found)
1177                         {
1178                             HMI_SEQ_ERROR(req_num, "App doesn't exist for role : %s",
1179                                             deact_sub.role.c_str());
1180                             return WMError::NOT_REGISTERED;
1181                         }
1182                         deact_sub.visible = task_visible;
1183                         deact_sub.end_draw_finished = end_draw_finished;
1184                         HMI_SEQ_DEBUG(req_num, "Set invisible task for %s", deact_sub.appid.c_str());
1185                         g_app_list.setAction(req_num, deact_sub);
1186                     }
1187                 }
1188                 //state = LayoutState{state.main, *surface_id};
1189             }
1190             else
1191             {
1192                 HMI_DEBUG("wm", "Layout: %s", kNameLayoutNormal);
1193
1194                 //this->surface_set_layout(*surface_id);
1195                 if (state.main != *surface_id)
1196                 {
1197                     // this->deactivate(state.main);
1198                     WMAction deact_main;
1199                     deact_main.role = std::move(*this->id_alloc.lookup(state.main));
1200                     ;
1201                     deact_main.area = add_area;
1202                     deact_main.appid = g_app_list.getAppID(state.main, deact_main.role, &found);
1203                     if (!found)
1204                     {
1205                         HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist");
1206                         return WMError::NOT_REGISTERED;
1207                     }
1208                     deact_main.visible = task_visible;
1209                     deact_main.end_draw_finished = end_draw_finished;
1210                     HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist");
1211                     g_app_list.setAction(req_num, deact_main);
1212                 }
1213                 if (state.sub != -1)
1214                 {
1215                     if (state.sub != *surface_id)
1216                     {
1217                         //this->deactivate(state.sub);
1218                         WMAction deact_sub;
1219                         deact_sub.role = std::move(*this->id_alloc.lookup(state.sub));
1220                         ;
1221                         deact_sub.area = add_area;
1222                         deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found);
1223                         if (!found)
1224                         {
1225                             HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist");
1226                             return WMError::NOT_REGISTERED;
1227                         }
1228                         deact_sub.visible = task_visible;
1229                         deact_sub.end_draw_finished = end_draw_finished;
1230                         HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist");
1231                         g_app_list.setAction(req_num, deact_sub);
1232                     }
1233                 }
1234                 //state = LayoutState{*surface_id};
1235             }
1236         }
1237     }
1238     return WMError::SUCCESS;
1239 }
1240
1241 WMError WindowManager::doEndDraw(unsigned req_num)
1242 {
1243     // get actions
1244     bool found;
1245     auto actions = g_app_list.getActions(req_num, &found);
1246     WMError ret = WMError::SUCCESS;
1247     if (!found)
1248     {
1249         ret = WMError::NO_ENTRY;
1250         return ret;
1251     }
1252
1253     HMI_SEQ_INFO(req_num, "do endDraw");
1254
1255     // layout change and make it visible
1256     for (const auto &act : actions)
1257     {
1258         // layout change
1259         if(!g_app_list.contains(act.appid)){
1260             ret = WMError::NOT_REGISTERED;
1261         }
1262         ret = this->layoutChange(act);
1263         if(ret != WMError::SUCCESS)
1264         {
1265             HMI_SEQ_WARNING(req_num,
1266                 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1267             return ret;
1268         }
1269         ret = this->visibilityChange(act);
1270         if (ret != WMError::SUCCESS)
1271         {
1272             HMI_SEQ_WARNING(req_num,
1273                 "Failed to manipulate surfaces while state change : %s", errorDescription(ret));
1274             return ret;
1275         }
1276         HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
1277         //this->lm_enddraw(act.role.c_str());
1278     }
1279
1280     // Change current state
1281     this->changeCurrentState(req_num);
1282
1283     HMI_SEQ_INFO(req_num, "emit flushDraw");
1284
1285     for(const auto &act_flush : actions)
1286     {
1287         if(act_flush.visible != TaskVisible::INVISIBLE)
1288         {
1289             // TODO: application requests by old role,
1290             //       so convert role new to old for emitting event
1291             std::string old_role = this->rolenew2old[act_flush.role];
1292
1293             this->emit_flushdraw(old_role.c_str());
1294         }
1295     }
1296
1297     return ret;
1298 }
1299
1300 WMError WindowManager::layoutChange(const WMAction &action)
1301 {
1302     if (action.visible == TaskVisible::INVISIBLE)
1303     {
1304         // Visibility is not change -> no redraw is required
1305         return WMError::SUCCESS;
1306     }
1307     auto client = g_app_list.lookUpClient(action.appid);
1308     unsigned surface = client->surfaceID(action.role);
1309     if (surface == 0)
1310     {
1311         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1312                       "client doesn't have surface with role(%s)", action.role.c_str());
1313         return WMError::NOT_REGISTERED;
1314     }
1315     // Layout Manager
1316     WMError ret = this->setSurfaceSize(surface, action.area);
1317     return ret;
1318 }
1319
1320 WMError WindowManager::visibilityChange(const WMAction &action)
1321 {
1322     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Change visibility");
1323     if(!g_app_list.contains(action.appid)){
1324         return WMError::NOT_REGISTERED;
1325     }
1326     auto client = g_app_list.lookUpClient(action.appid);
1327     unsigned surface = client->surfaceID(action.role);
1328     if(surface == 0)
1329     {
1330         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
1331                       "client doesn't have surface with role(%s)", action.role.c_str());
1332         return WMError::NOT_REGISTERED;
1333     }
1334
1335     if (action.visible != TaskVisible::INVISIBLE)
1336     {
1337         this->activate(surface); // Layout Manager task
1338     }
1339     else
1340     {
1341         this->deactivate(surface); // Layout Manager task
1342     }
1343     return WMError::SUCCESS;
1344 }
1345
1346 WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area)
1347 {
1348     this->surface_set_layout(surface, area);
1349
1350     return WMError::SUCCESS;
1351 }
1352
1353 WMError WindowManager::changeCurrentState(unsigned req_num)
1354 {
1355     HMI_SEQ_DEBUG(req_num, "Change current layout state");
1356     bool trigger_found = false, action_found = false;
1357     auto trigger = g_app_list.getRequest(req_num, &trigger_found);
1358     auto actions = g_app_list.getActions(req_num, &action_found);
1359     if (!trigger_found || !action_found)
1360     {
1361         HMI_SEQ_ERROR(req_num, "Action not found");
1362         return WMError::LAYOUT_CHANGE_FAIL;
1363     }
1364
1365     // Layout state reset
1366     struct LayoutState reset_state{-1, -1};
1367     HMI_SEQ_DEBUG(req_num,"Reset layout state");
1368     for (const auto &action : actions)
1369     {
1370         if(!g_app_list.contains(action.appid)){
1371             return WMError::NOT_REGISTERED;
1372         }
1373         auto client = g_app_list.lookUpClient(action.appid);
1374         auto pCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role));
1375         if(pCurState == nullptr)
1376         {
1377             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
1378             continue;
1379         }
1380         pCurState->main = reset_state.main;
1381         pCurState->sub = reset_state.sub;
1382     }
1383
1384     HMI_SEQ_DEBUG(req_num, "Change state");
1385     for (const auto &action : actions)
1386     {
1387         auto client = g_app_list.lookUpClient(action.appid);
1388         auto pLayerCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role));
1389         if (pLayerCurState == nullptr)
1390         {
1391             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
1392             continue;
1393         }
1394         int surface = -1;
1395
1396         if (action.visible != TaskVisible::INVISIBLE)
1397         {
1398             surface = (int)client->surfaceID(action.role);
1399             HMI_SEQ_INFO(req_num, "Change %s surface : %d, state visible area : %s",
1400                             action.role.c_str(), surface, action.area.c_str());
1401             // visible == true -> layout changes
1402             if(action.area == "normal.full" || action.area == "split.main")
1403             {
1404                 pLayerCurState->main = surface;
1405             }
1406             else if (action.area == "split.sub")
1407             {
1408                 pLayerCurState->sub = surface;
1409             }
1410             else
1411             {
1412                 // normalfull
1413                 pLayerCurState->main = surface;
1414             }
1415         }
1416     }
1417
1418     return WMError::SUCCESS;
1419 }
1420
1421 void WindowManager::emitScreenUpdated(unsigned req_num)
1422 {
1423     // Get visible apps
1424     HMI_SEQ_DEBUG(req_num, "emit screen updated");
1425     bool found = false;
1426     auto actions = g_app_list.getActions(req_num, &found);
1427
1428     // create json object
1429     json_object *j = json_object_new_object();
1430     json_object *jarray = json_object_new_array();
1431
1432     for(const auto& action: actions)
1433     {
1434         if(action.visible != TaskVisible::INVISIBLE)
1435         {
1436             json_object_array_add(jarray, json_object_new_string(action.appid.c_str()));
1437         }
1438     }
1439     json_object_object_add(j, kKeyIds, jarray);
1440     HMI_SEQ_INFO(req_num, "Visible app: %s", json_object_get_string(j));
1441
1442     int ret = afb_event_push(
1443         this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
1444     if (ret != 0)
1445     {
1446         HMI_DEBUG("wm", "afb_event_push failed: %m");
1447     }
1448     json_object_put(jarray);
1449 }
1450
1451 void WindowManager::setTimer()
1452 {
1453     HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate");
1454     if (g_timer_ev_src == nullptr)
1455     {
1456         // firsttime set into sd_event
1457         int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
1458             CLOCK_REALTIME, time(NULL) * (1000000UL) + kTimeOut, 1, processTimerHandler, this);
1459         if (ret < 0)
1460         {
1461             HMI_ERROR("wm", "Could't set timer");
1462         }
1463     }
1464     else
1465     {
1466         // update timer limitation after second time
1467         sd_event_source_set_time(g_timer_ev_src, time(NULL) * (1000000UL) + kTimeOut);
1468         sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT);
1469     }
1470 }
1471
1472 void WindowManager::stopTimer()
1473 {
1474     unsigned req_num = g_app_list.currentRequestNumber();
1475     HMI_SEQ_DEBUG(req_num, "Timer stop");
1476     int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF);
1477     if (rc < 0)
1478     {
1479         HMI_SEQ_ERROR(req_num, "Timer stop failed");
1480     }
1481 }
1482
1483 void WindowManager::processNextRequest()
1484 {
1485     g_app_list.next();
1486     g_app_list.reqDump();
1487     unsigned req_num = g_app_list.currentRequestNumber();
1488     if (g_app_list.haveRequest())
1489     {
1490         HMI_SEQ_DEBUG(req_num, "Process next request");
1491         WMError rc = doTransition(req_num);
1492         if (rc != WMError::SUCCESS)
1493         {
1494             HMI_SEQ_ERROR(req_num, errorDescription(rc));
1495         }
1496     }
1497     else
1498     {
1499         HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request");
1500     }
1501 }
1502
1503 const char* WindowManager::convertRoleOldToNew(char const *old_role)
1504 {
1505     const char *new_role = nullptr;
1506
1507     for (auto const &on : this->roleold2new)
1508     {
1509         std::regex regex = std::regex(on.first);
1510         if (std::regex_match(old_role, regex))
1511         {
1512             // role is old. So convert to new.
1513             new_role = on.second.c_str();
1514             break;
1515         }
1516     }
1517
1518     if (nullptr == new_role)
1519     {
1520         // role is new or fallback.
1521         new_role = old_role;
1522     }
1523
1524     HMI_DEBUG("wm", "old:%s -> new:%s", old_role, new_role);
1525
1526     return new_role;
1527 }
1528
1529 int WindowManager::loadOldRoleDb()
1530 {
1531     // Get afm application installed dir
1532     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
1533     HMI_DEBUG("wm", "afm_app_install_dir:%s", afm_app_install_dir);
1534
1535     std::string file_name;
1536     if (!afm_app_install_dir)
1537     {
1538         HMI_ERROR("wm", "AFM_APP_INSTALL_DIR is not defined");
1539     }
1540     else
1541     {
1542         file_name = std::string(afm_app_install_dir) + std::string("/etc/old_roles.db");
1543     }
1544
1545     // Load old_role.db
1546     json_object* json_obj;
1547     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
1548     if (0 > ret)
1549     {
1550         HMI_ERROR("wm", "Could not open old_role.db, so use default old_role information");
1551         json_obj = json_tokener_parse(kDefaultOldRoleDb);
1552     }
1553     HMI_DEBUG("wm", "json_obj dump:%s", json_object_get_string(json_obj));
1554
1555     // Perse apps
1556     json_object* json_cfg;
1557     if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
1558     {
1559         HMI_ERROR("wm", "Parse Error!!");
1560         return -1;
1561     }
1562
1563     int len = json_object_array_length(json_cfg);
1564     HMI_DEBUG("wm", "json_cfg len:%d", len);
1565     HMI_DEBUG("wm", "json_cfg dump:%s", json_object_get_string(json_cfg));
1566
1567     for (int i=0; i<len; i++)
1568     {
1569         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
1570
1571         const char* old_role = jh::getStringFromJson(json_tmp, "name");
1572         if (nullptr == old_role)
1573         {
1574             HMI_ERROR("wm", "Parse Error!!");
1575             return -1;
1576         }
1577
1578         const char* new_role = jh::getStringFromJson(json_tmp, "new");
1579         if (nullptr == new_role)
1580         {
1581             HMI_ERROR("wm", "Parse Error!!");
1582             return -1;
1583         }
1584
1585         this->roleold2new[old_role] = std::string(new_role);
1586     }
1587
1588     // Check
1589     for(auto itr = this->roleold2new.begin();
1590       itr != this->roleold2new.end(); ++itr)
1591     {
1592         HMI_DEBUG("wm", ">>> role old:%s new:%s",
1593                   itr->first.c_str(), itr->second.c_str());
1594     }
1595
1596     // Release json_object
1597     json_object_put(json_obj);
1598
1599     return 0;
1600 }
1601
1602 const char *WindowManager::check_surface_exist(const char *drawing_name)
1603 {
1604     auto const &surface_id = this->lookup_id(drawing_name);
1605     if (!surface_id)
1606     {
1607         return "Surface does not exist";
1608     }
1609
1610     if (!this->controller->surface_exists(*surface_id))
1611     {
1612         return "Surface does not exist in controller!";
1613     }
1614
1615     auto layer_id = this->layers.get_layer_id(*surface_id);
1616
1617     if (!layer_id)
1618     {
1619         return "Surface is not on any layer!";
1620     }
1621
1622     auto o_state = *this->layers.get_layout_state(*surface_id);
1623
1624     if (o_state == nullptr)
1625     {
1626         return "Could not find layer for surface";
1627     }
1628
1629     HMI_DEBUG("wm", "surface %d is detected", *surface_id);
1630     return nullptr;
1631 }
1632
1633 bool WindowManager::can_split(struct LayoutState const &state, int new_id)
1634 {
1635     if (state.main != -1 && state.main != new_id)
1636     {
1637         auto new_id_layer = this->layers.get_layer_id(new_id).value();
1638         auto current_id_layer = this->layers.get_layer_id(state.main).value();
1639
1640         // surfaces are on separate layers, don't bother.
1641         if (new_id_layer != current_id_layer)
1642         {
1643             return false;
1644         }
1645
1646         std::string const &new_id_str = this->lookup_name(new_id).value();
1647         std::string const &cur_id_str = this->lookup_name(state.main).value();
1648
1649         auto const &layer = this->layers.get_layer(new_id_layer);
1650
1651         HMI_DEBUG("wm", "layer info name: %s", layer->name.c_str());
1652
1653         if (layer->layouts.empty())
1654         {
1655             return false;
1656         }
1657
1658         for (auto i = layer->layouts.cbegin(); i != layer->layouts.cend(); i++)
1659         {
1660             HMI_DEBUG("wm", "%d main_match '%s'", new_id_layer, i->main_match.c_str());
1661             auto rem = std::regex(i->main_match);
1662             if (std::regex_match(cur_id_str, rem))
1663             {
1664                 // build the second one only if the first already matched
1665                 HMI_DEBUG("wm", "%d sub_match '%s'", new_id_layer, i->sub_match.c_str());
1666                 auto res = std::regex(i->sub_match);
1667                 if (std::regex_match(new_id_str, res))
1668                 {
1669                     HMI_DEBUG("wm", "layout matched!");
1670                     return true;
1671                 }
1672             }
1673         }
1674     }
1675
1676     return false;
1677 }
1678
1679 const char* WindowManager::kDefaultOldRoleDb = "{ \
1680     \"old_roles\": [ \
1681         { \
1682             \"name\": \"HomeScreen\", \
1683             \"new\": \"homescreen\" \
1684         }, \
1685         { \
1686             \"name\": \"Music\", \
1687             \"new\": \"music\" \
1688         }, \
1689         { \
1690             \"name\": \"MediaPlayer\", \
1691             \"new\": \"music\" \
1692         }, \
1693         { \
1694             \"name\": \"Video\", \
1695             \"new\": \"video\" \
1696         }, \
1697         { \
1698             \"name\": \"VideoPlayer\", \
1699             \"new\": \"video\" \
1700         }, \
1701         { \
1702             \"name\": \"WebBrowser\", \
1703             \"new\": \"browser\" \
1704         }, \
1705         { \
1706             \"name\": \"Radio\", \
1707             \"new\": \"radio\" \
1708         }, \
1709         { \
1710             \"name\": \"Phone\", \
1711             \"new\": \"phone\" \
1712         }, \
1713         { \
1714             \"name\": \"Navigation\", \
1715             \"new\": \"map\" \
1716         }, \
1717         { \
1718             \"name\": \"HVAC\", \
1719             \"new\": \"hvac\" \
1720         }, \
1721         { \
1722             \"name\": \"Settings\", \
1723             \"new\": \"settings\" \
1724         }, \
1725         { \
1726             \"name\": \"Dashboard\", \
1727             \"new\": \"dashboard\" \
1728         }, \
1729         { \
1730             \"name\": \"POI\", \
1731             \"new\": \"poi\" \
1732         }, \
1733         { \
1734             \"name\": \"Mixer\", \
1735             \"new\": \"mixer\" \
1736         }, \
1737         { \
1738             \"name\": \"Restriction\", \
1739             \"new\": \"restriction\" \
1740         }, \
1741         { \
1742             \"name\": \"^OnScreen.*\", \
1743             \"new\": \"on_screen\" \
1744         } \
1745     ] \
1746 }";
1747
1748 /**
1749  * controller_hooks
1750  */
1751 void controller_hooks::surface_created(uint32_t surface_id)
1752 {
1753     this->app->surface_created(surface_id);
1754 }
1755
1756 void controller_hooks::surface_removed(uint32_t surface_id)
1757 {
1758     this->app->surface_removed(surface_id);
1759 }
1760
1761 void controller_hooks::surface_visibility(uint32_t /*surface_id*/,
1762                                           uint32_t /*v*/) {}
1763
1764 void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/,
1765                                                      uint32_t /*x*/,
1766                                                      uint32_t /*y*/,
1767                                                      uint32_t /*w*/,
1768                                                      uint32_t /*h*/) {}
1769
1770 } // namespace wm