OnScreen app can be displayed for pop_up role
[apps/agl-service-windowmanager.git] / src / app.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 "app.hpp"
18 #include "json_helper.hpp"
19 #include "layers.hpp"
20 #include "layout.hpp"
21 #include "util.hpp"
22 #include "wayland_ivi_wm.hpp"
23
24 #include <cstdio>
25 #include <memory>
26
27 #include <cassert>
28
29 #include <json-c/json.h>
30
31 #include <algorithm>
32 #include <csignal>
33 #include <fstream>
34 #include <json.hpp>
35 #include <regex>
36 #include <thread>
37 #include <string>
38 #include <regex>
39
40
41 namespace wm {
42
43 /* DrawingArea name used by "{layout}.{area}" */
44 const char kNameLayoutNormal[] = "normal";
45 const char kNameLayoutSplit[]  = "split";
46 const char kNameAreaFull[]     = "full";
47 const char kNameAreaMain[]     = "main";
48 const char kNameAreaSub[]      = "sub";
49
50 /* Key for json obejct */
51 const char kKeyDrawingName[] = "drawing_name";
52 const char kKeyDrawingArea[] = "drawing_area";
53 const char kKeyDrawingRect[] = "drawing_rect";
54 const char kKeyX[]           = "x";
55 const char kKeyY[]           = "y";
56 const char kKeyWidth[]       = "width";
57 const char kKeyHeight[]      = "height";
58 const char kKeyWidthPixel[]  = "width_pixel";
59 const char kKeyHeightPixel[] = "height_pixel";
60 const char kKeyWidthMm[]     = "width_mm";
61 const char kKeyHeightMm[]    = "height_mm";
62
63
64 namespace {
65
66 using nlohmann::json;
67
68 result<json> file_to_json(char const *filename) {
69    json j;
70    std::ifstream i(filename);
71    if (i.fail()) {
72       HMI_DEBUG("wm", "Could not open config file, so use default layer information");
73       j = default_layers_json;
74    }
75    else {
76       i >> j;
77    }
78
79    return Ok(j);
80 }
81
82 struct result<layer_map> load_layer_map(char const *filename) {
83    HMI_DEBUG("wm", "loading IDs from %s", filename);
84
85    auto j = file_to_json(filename);
86    if (j.is_err()) {
87       return Err<layer_map>(j.unwrap_err());
88    }
89    json jids = j.unwrap();
90
91    return to_layer_map(jids);
92 }
93
94 }  // namespace
95
96
97 namespace rm {
98 App *context;
99 static void onStateTransitioned(json_object* json_out) {
100     context->updateWindowResources(json_out);
101 }
102
103 static void onError(json_object* json_out) {
104     HMI_DEBUG("wm", "error message from PolicyManager:%s",
105               json_object_get_string(json_out));
106 }
107 }  // namespace rm
108
109
110 void App::updateCarElements(json_object* json_out) {
111     json_object* json_car_ele;
112     if (!json_object_object_get_ex(json_out, "car_elements", &json_car_ele)) {
113         HMI_DEBUG("wm", "Not found key \"car_elements\"");
114         return;
115     }
116
117     int len = json_object_array_length(json_car_ele);
118     HMI_DEBUG("wm", "json_car_ele len:%d", len);
119
120     for (int i=0; i<len; i++) {
121         json_object* json_tmp = json_object_array_get_idx(json_car_ele, i);
122
123         std::string car_ele_name = jh::getStringFromJson(json_tmp, "name");
124         std::string state = jh::getStringFromJson(json_tmp, "state");
125         json_bool changed = jh::getBoolFromJson(json_tmp, "changed");
126         HMI_DEBUG("wm", "car_element:%s changed:%d", car_ele_name.c_str(), changed);
127
128         if (changed) {
129             if ("parking_brake" == car_ele_name) {
130                 if ("off" == state) {
131                     this->crr_car_info.parking_brake_stt = false;
132 #if 0 // FOR ALS: using lightstatus brake, so do not emit parking brake event
133                     this->emitParkingBrakeOff();
134 #endif
135                 }
136                 else if ("on" == state) {
137                     this->crr_car_info.parking_brake_stt = true;
138 #if 0 // FOR ALS: using lightstatus brake, so do not emit parking brake event
139                     this->emitParkingBrakeOn();
140 #endif
141                 }
142                 else {
143                     HMI_DEBUG("wm", "Unknown parking brake state: %s", state.c_str());
144                 }
145             }
146             else if ("accel_pedal" == car_ele_name) {
147                 if ("off" == state) {
148                     this->crr_car_info.accel_pedal_stt = false;
149                 }
150                 else if ("on" == state) {
151                     this->crr_car_info.accel_pedal_stt = true;
152                 }
153                 else {
154                     HMI_DEBUG("wm", "Unknown accel pedal state: %s", state.c_str());
155                 }
156             }
157             else if ("lightstatus_brake" == car_ele_name) {
158                 if ("off" == state) {
159                     this->crr_car_info.lightstatus_brake_stt = false;
160                     this->emitLightstatusBrakeOff();
161                 }
162                 else if ("on" == state) {
163                     this->crr_car_info.lightstatus_brake_stt = true;
164                     this->emitLightstatusBrakeOn();
165                 }
166                 else {
167                     HMI_DEBUG("wm", "Unknown lightstatus brake state: %s", state.c_str());
168                 }
169             }
170             else if ("running" == car_ele_name) {
171                 if ("stop" == state) {
172                     this->crr_car_info.running_stt = false;
173                     this->emitCarStop();
174                 }
175                 else if ("run" == state) {
176                     this->crr_car_info.running_stt = true;
177                     this->emitCarRun();
178                 }
179                 else {
180                     HMI_DEBUG("wm", "Unknown car state: %s", state.c_str());
181                 }
182             }
183             else if ("lamp" == car_ele_name) {
184                 if ("off" == state) {
185                     this->crr_car_info.headlamp_stt = false;
186                     this->emitHeadlampOff();
187                 }
188                 else if ("on" == state) {
189                     this->crr_car_info.headlamp_stt = true;
190                     this->emitHeadlampOn();
191                 }
192                 else {
193                     HMI_DEBUG("wm", "Unknown lamp state: %s", state.c_str());
194                 }
195             }
196             else {
197                 HMI_DEBUG("wm", "Unknown car element: %s", car_ele_name.c_str());
198             }
199         }
200     }
201 }
202
203 void App::updateLayers(json_object* json_out) {
204     // Get displayed roles from current layout
205     json_object* json_layers;
206     if (!json_object_object_get_ex(json_out, "layers", &json_layers)) {
207         HMI_DEBUG("wm", "Not found key \"layers\"");
208         return;
209     }
210
211     int len = json_object_array_length(json_layers);
212     HMI_DEBUG("wm", "json_layers len:%d", len);
213
214     for (int i=0; i<len; i++) {
215         json_object* json_tmp = json_object_array_get_idx(json_layers, i);
216
217         std::string layer_name = jh::getStringFromJson(json_tmp, "name");
218         json_bool changed = jh::getBoolFromJson(json_tmp, "changed");
219         HMI_DEBUG("wm", "layer:%s changed:%d", layer_name.c_str(), changed);
220
221         if (changed) {
222             json_object* json_areas;
223             if (!json_object_object_get_ex(json_tmp, "areas", &json_areas)) {
224                 HMI_DEBUG("wm", "Not found key \"areas\"");
225                 return;
226             }
227
228             int len = json_object_array_length(json_areas);
229             HMI_DEBUG("wm", "json_layers len:%d", len);
230
231             RoleState nxt_roles;
232             RoleState crr_roles = this->crr_layer_state[layer_name];
233             for (int j=0; j<len; j++) {
234                 json_object* json_tmp2 = json_object_array_get_idx(json_areas, j);
235
236                 std::string area_name = jh::getStringFromJson(json_tmp2, "name");
237                 std::string role_name = jh::getStringFromJson(json_tmp2, "role");
238
239                 nxt_roles[role_name] = area_name;
240
241                 auto i_crr = crr_roles.find(role_name);
242                 HMI_DEBUG("wm", "next role:%s area:%s",
243                           role_name.c_str(), area_name.c_str());
244
245                 // If next role does not exist in current
246                 if (crr_roles.end() == i_crr) {
247                     HMI_DEBUG("wm", "next role does not exist in current");
248
249                     // Set surface size
250                     this->setSurfaceSize(role_name.c_str(), area_name.c_str());
251                 }
252                 else {
253                     HMI_DEBUG("wm", "current role:%s area:%s",
254                               i_crr->first.c_str(), i_crr->second.c_str());
255
256                     // If next role exists in current and area is different with current
257                     if (area_name != i_crr->second) {
258                         HMI_DEBUG("wm", "next role exists in current and area is different with current");
259
260                         // Set surface size
261                         this->setSurfaceSize(role_name.c_str(), area_name.c_str());
262                     }
263
264                     // Remove role which exist in next list from current list
265                     crr_roles.erase(i_crr);
266                 }
267             }
268
269             // Deactivate roles which remains in current list
270             // because these are not displayed in next layout
271             for (auto i_crr : crr_roles) {
272                 HMI_DEBUG("wm", "Deactivate role:%s", i_crr.first.c_str());
273
274                 // Deactivate
275                 this->deactivate(i_crr.first.c_str());
276             }
277
278             // Update current role list
279             this->crr_layer_state[layer_name] = nxt_roles;
280         }
281     }
282 }
283
284 void App::updateWindowResources(json_object* json_out) {
285     HMI_DEBUG("wm", "json_out dump:%s", json_object_get_string(json_out));
286
287     // Update car elements
288     this->updateCarElements(json_out);
289
290     // Update layers
291     this->updateLayers(json_out);
292 }
293
294 /**
295  * App Impl
296  */
297 App::App(wl::display *d)
298    : chooks{this},
299      display{d},
300      controller{},
301      outputs(),
302      config(),
303      layers(),
304      id_alloc{},
305      pending_events(false),
306      policy{} {
307    try {
308       {
309          auto l = load_layer_map(
310             this->config.get_string("layers.json").value().c_str());
311          if (l.is_ok()) {
312             this->layers = l.unwrap();
313          } else {
314             HMI_ERROR("wm", "%s", l.err().value());
315          }
316       }
317    } catch (std::exception &e) {
318       HMI_ERROR("wm", "Loading of configuration failed: %s", e.what());
319    }
320
321    // Initialize current car info
322    this->crr_car_info.parking_brake_stt = true;
323    this->crr_car_info.accel_pedal_stt = false;
324    this->crr_car_info.accel_pedal_pos = 0;
325    this->crr_car_info.running_stt = false;
326    this->crr_car_info.headlamp_stt = false;
327 }
328
329 int App::init() {
330    if (!this->display->ok()) {
331       return -1;
332    }
333
334    if (this->layers.mapping.empty()) {
335       HMI_ERROR("wm", "No surface -> layer mapping loaded");
336       return -1;
337    }
338
339    // Store my context for calling callback for PolicyManager
340    rm::context = this;
341
342    // TODO: This process is necessary for checking right of requested role.
343    //       If other module check it, this process will be removed.
344    // Load app.db
345    this->loadAppDb();
346
347    // Initialize PolicyManager
348    this->pm.initialize();
349
350    // Register callback to PolicyManager
351    PolicyManager::CallbackTable callback;
352    callback.onStateTransitioned = rm::onStateTransitioned;
353    callback.onError = rm::onError;
354    this->pm.registerCallback(callback);
355
356    // Initialize LayoutManager
357    this->lm.initialize();
358
359    // Make afb event
360    for (int i=Event_Val_Min; i<=Event_Val_Max; i++) {
361       map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i]);
362    }
363
364    this->display->add_global_handler(
365       "wl_output", [this](wl_registry *r, uint32_t name, uint32_t v) {
366          this->outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
367       });
368
369    this->display->add_global_handler(
370       "ivi_wm", [this](wl_registry *r, uint32_t name, uint32_t v) {
371          this->controller =
372             std::make_unique<struct compositor::controller>(r, name, v);
373
374          // Init controller hooks
375          this->controller->chooks = &this->chooks;
376
377          // This protocol needs the output, so lets just add our mapping here...
378          this->controller->add_proxy_to_id_mapping(
379             this->outputs.back()->proxy.get(),
380             wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>(
381                this->outputs.back()->proxy.get())));
382
383          // Create screen
384          this->controller->create_screen(this->outputs.back()->proxy.get());
385
386          // Set display to controller
387          this->controller->display = this->display;
388       });
389
390    // First level objects
391    this->display->roundtrip();
392    // Second level objects
393    this->display->roundtrip();
394    // Third level objects
395    this->display->roundtrip();
396
397    return init_layers();
398 }
399
400 int App::dispatch_pending_events() {
401    if (this->pop_pending_events()) {
402       this->display->dispatch_pending();
403       return 0;
404    }
405    return -1;
406 }
407
408 bool App::pop_pending_events() {
409    bool x{true};
410    return this->pending_events.compare_exchange_strong(
411       x, false, std::memory_order_consume);
412 }
413
414 void App::set_pending_events() {
415    this->pending_events.store(true, std::memory_order_release);
416 }
417
418 optional<int> App::lookup_id(char const *name) {
419    return this->id_alloc.lookup(std::string(name));
420 }
421 optional<std::string> App::lookup_name(int id) {
422    return this->id_alloc.lookup(id);
423 }
424
425 /**
426  * init_layers()
427  */
428 int App::init_layers() {
429    if (!this->controller) {
430       HMI_ERROR("wm", "ivi_controller global not available");
431       return -1;
432    }
433
434    if (this->outputs.empty()) {
435       HMI_ERROR("wm", "no output was set up!");
436       return -1;
437    }
438
439    auto &c = this->controller;
440
441    auto &o = this->outputs.front();
442    auto &s = c->screens.begin()->second;
443    auto &layers = c->layers;
444
445    // Write output dimensions to ivi controller...
446    c->output_size = compositor::size{uint32_t(o->width), uint32_t(o->height)};
447    c->physical_size = compositor::size{uint32_t(o->physical_width),
448                                        uint32_t(o->physical_height)};
449
450    // Clear scene
451    layers.clear();
452
453    // Clear screen
454    s->clear();
455
456    // Quick and dirty setup of layers
457    for (auto const &i : this->layers.mapping) {
458       c->layer_create(i.second.layer_id, o->width, o->height);
459       auto &l = layers[i.second.layer_id];
460       l->set_destination_rectangle(0, 0, o->width, o->height);
461       l->set_visibility(1);
462       HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"",
463                i.second.name.c_str(), i.second.layer_id, i.second.role.c_str());
464    }
465
466    // Add layers to screen
467    s->set_render_order(this->layers.layers);
468
469    this->layout_commit();
470
471    return 0;
472 }
473
474 void App::layout_commit() {
475    this->controller->commit_changes();
476    this->display->flush();
477 }
478
479 const char* App::convertDrawingNameToRole(char const *drawing_name) {
480     const char* role = nullptr;
481
482     for (auto const &dr : this->drawingname2role) {
483         std::regex regex = std::regex(dr.first);
484         if (std::regex_match(drawing_name, regex)) {
485             // drawing_name is old role. So convert to new role.
486             role = dr.second.c_str();
487             break;
488         }
489     }
490
491     if (nullptr == role) {
492         // drawing_name is new role.
493         role = drawing_name;
494     }
495
496     HMI_DEBUG("wm", "drawing_name:%s -> role: %s", drawing_name, role);
497
498     return role;
499 }
500
501 void App::allocateWindowResource(char const *event, char const *drawing_name,
502                                  char const *drawing_area, const reply_func &reply) {
503     const char* new_role = nullptr;
504     const char* new_area = nullptr;
505
506     // Convert old role to new role
507     if ((nullptr != drawing_name) && (0 != strcmp("", drawing_name))) {
508         new_role = this->convertDrawingNameToRole(drawing_name);
509         HMI_DEBUG("wm", "new_role: %s", new_role);
510     }
511
512     if (0 == strcmp("activate", event)) {
513         // TODO:
514         // This process will be removed
515         // because the area "normal.full" and "normalfull" will be prohibited
516         {
517             if (0 == strcmp("restriction", new_role)) {
518                 new_area = drawing_area;
519             }
520             else {
521                 if (nullptr == drawing_area) {
522                     new_area = "normal";
523                 }
524                 else if (0 == strcmp("normal.full", drawing_area)) {
525                     new_area = "normal";
526                 }
527                 else if (0 == strcmp("restriction.split.sub", drawing_area)) {
528                     new_area = "restriction.split.sub";
529                 }
530                 else if (0 == strcmp("homescreen", new_role)) {
531                     // Now homescreen specifies "normalfull"
532                     new_area = "fullscreen";
533                 }
534                 else {
535                     new_area = "normal";
536                 }
537             }
538             HMI_DEBUG("wm", "drawing_area:%s, new_area: %s", drawing_area, new_area);
539         }
540     }
541     else if (0 == strcmp("deactivate", event)) {
542         new_area = "";
543     }
544
545     // TODO:
546     // Check role
547
548     // Input event to PolicyManager
549     json_object* json_in = json_object_new_object();
550     json_object_object_add(json_in, "event", json_object_new_string(event));
551     if (nullptr != new_role) {
552         json_object_object_add(json_in, "role", json_object_new_string(new_role));
553     }
554     if (nullptr != new_area) {
555         json_object_object_add(json_in, "area", json_object_new_string(new_area));
556     }
557
558     // Set input event data
559     this->pm.setInputEventData(json_in);
560
561     // Execute state transition
562     this->pm.executeStateTransition();
563
564     // Release json_object
565     json_object_put(json_in);
566
567     return;
568 }
569
570 void App::enqueue_flushdraw(int surface_id) {
571    this->check_flushdraw(surface_id);
572    HMI_DEBUG("wm", "Enqueuing EndDraw for surface_id %d", surface_id);
573    this->pending_end_draw.push_back(surface_id);
574 }
575
576 void App::check_flushdraw(int surface_id) {
577    auto i = std::find(std::begin(this->pending_end_draw),
578                       std::end(this->pending_end_draw), surface_id);
579    if (i != std::end(this->pending_end_draw)) {
580       auto n = this->lookup_name(surface_id);
581       HMI_ERROR("wm", "Application %s (%d) has pending EndDraw call(s)!",
582                n ? n->c_str() : "unknown-name", surface_id);
583       std::swap(this->pending_end_draw[std::distance(
584                    std::begin(this->pending_end_draw), i)],
585                 this->pending_end_draw.back());
586       this->pending_end_draw.resize(this->pending_end_draw.size() - 1);
587    }
588 }
589
590 void App::api_enddraw(char const *drawing_name) {
591    // Convert drawing_name to role
592    const char* role = this->convertDrawingNameToRole(drawing_name);
593
594    for (unsigned i = 0, iend = this->pending_end_draw.size(); i < iend; i++) {
595       auto n = this->lookup_name(this->pending_end_draw[i]);
596       int surface_id = this->pending_end_draw[i];
597
598       if (n && *n == role) {
599          std::swap(this->pending_end_draw[i], this->pending_end_draw[iend - 1]);
600          this->pending_end_draw.resize(iend - 1);
601          this->activate(surface_id);
602          this->emit_flushdraw(drawing_name);
603       }
604    }
605 }
606
607 void App::api_ping() { this->dispatch_pending_events(); }
608
609 void App::send_event(char const *evname){
610    HMI_DEBUG("wm", "%s: %s", __func__, evname);
611
612    int ret = afb_event_push(this->map_afb_event[evname], nullptr);
613    if (ret != 0) {
614       HMI_DEBUG("wm", "afb_event_push failed: %m");
615    }
616 }
617
618 void App::send_event(char const *evname, char const *label){
619    HMI_DEBUG("wm", "%s: %s(%s)", __func__, evname, label);
620
621    json_object *j = json_object_new_object();
622    json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
623
624    int ret = afb_event_push(this->map_afb_event[evname], j);
625    if (ret != 0) {
626       HMI_DEBUG("wm", "afb_event_push failed: %m");
627    }
628 }
629
630 void App::send_event(char const *evname, char const *label, char const *area,
631                              int x, int y, int w, int h) {
632    HMI_DEBUG("wm", "%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
633              __func__, evname, label, area, x, y, w, h);
634
635    json_object *j_rect = json_object_new_object();
636    json_object_object_add(j_rect, kKeyX,      json_object_new_int(x));
637    json_object_object_add(j_rect, kKeyY,      json_object_new_int(y));
638    json_object_object_add(j_rect, kKeyWidth,  json_object_new_int(w));
639    json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
640
641    json_object *j = json_object_new_object();
642    json_object_object_add(j, kKeyDrawingName, json_object_new_string(label));
643    json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area));
644    json_object_object_add(j, kKeyDrawingRect, j_rect);
645
646    int ret = afb_event_push(this->map_afb_event[evname], j);
647    if (ret != 0) {
648       HMI_DEBUG("wm", "afb_event_push failed: %m");
649    }
650 }
651
652 /**
653  * proxied events
654  */
655 void App::surface_created(uint32_t surface_id) {
656    auto layer_id = this->layers.get_layer_id(surface_id);
657    if (!layer_id) {
658       HMI_DEBUG("wm", "Newly created surfce %d is not associated with any layer!",
659                surface_id);
660       return;
661    }
662
663    HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", surface_id, *layer_id);
664
665    this->controller->layers[*layer_id]->add_surface(surface_id);
666    this->layout_commit();
667    // activate the main_surface right away
668    /*if (surface_id == static_cast<unsigned>(this->layers.main_surface)) {
669       HMI_DEBUG("wm", "Activating main_surface (%d)", surface_id);
670
671       this->api_activate_surface(
672          this->lookup_name(surface_id).value_or("unknown-name").c_str());
673    }*/
674 }
675
676 void App::surface_removed(uint32_t surface_id) {
677    HMI_DEBUG("wm", "surface_id is %u", surface_id);
678
679    // We cannot normally deactivate the main_surface, so be explicit
680    // about it:
681    if (int(surface_id) == this->layers.main_surface) {
682       this->deactivate_main_surface();
683    } else {
684       auto role = this->lookup_name(surface_id);
685       if (role) {
686          this->allocateWindowResource("deactivate",
687                                       role->c_str(), nullptr,
688                                       [](const char*){});
689       }
690    }
691
692    this->id_alloc.remove_id(surface_id);
693    this->layers.remove_surface(surface_id);
694 }
695
696 void App::emit_activated(char const *label) {
697    this->send_event(kListEventName[Event_Active], label);
698 }
699
700 void App::emit_deactivated(char const *label) {
701    this->send_event(kListEventName[Event_Inactive], label);
702 }
703
704 void App::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h) {
705    this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h);
706 }
707
708 void App::emit_flushdraw(char const *label) {
709    this->send_event(kListEventName[Event_FlushDraw], label);
710 }
711
712 void App::emit_visible(char const *label, bool is_visible) {
713    this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label);
714 }
715
716 void App::emit_invisible(char const *label) {
717    return emit_visible(label, false);
718 }
719
720 void App::emit_visible(char const *label) { return emit_visible(label, true); }
721
722 void App::emitHeadlampOff() {
723     // Send HeadlampOff event for all application
724     this->send_event(kListEventName[Event_HeadlampOff]);
725 }
726
727 void App::emitHeadlampOn() {
728     // Send HeadlampOn event for all application
729     this->send_event(kListEventName[Event_HeadlampOn]);
730 }
731
732 void App::emitParkingBrakeOff() {
733     // Send ParkingBrakeOff event for all application
734     this->send_event(kListEventName[Event_ParkingBrakeOff]);
735 }
736
737 void App::emitParkingBrakeOn() {
738     // Send ParkingBrakeOn event for all application
739     this->send_event(kListEventName[Event_ParkingBrakeOn]);
740 }
741
742 void App::emitLightstatusBrakeOff() {
743     // Send LightstatusBrakeOff event for all application
744     this->send_event(kListEventName[Event_LightstatusBrakeOff]);
745 }
746
747 void App::emitLightstatusBrakeOn() {
748     // Send LightstatusBrakeOn event for all application
749     this->send_event(kListEventName[Event_LightstatusBrakeOn]);
750 }
751
752 void App::emitCarStop() {
753     // Send CarStop event for all application
754     this->send_event(kListEventName[Event_CarStop]);
755 }
756
757 void App::emitCarRun() {
758     // Send CarRun event for all application
759     this->send_event(kListEventName[Event_CarRun]);
760 }
761
762 result<int> App::api_request_surface(char const *drawing_name) {
763    // Convert drawing_name to role
764    const char* role = this->convertDrawingNameToRole(drawing_name);
765
766    auto lid = this->layers.get_layer_id(std::string(role));
767    if (!lid) {
768       /**
769        * register drawing_name as fallback and make it displayed.
770        */
771       lid = this->layers.get_layer_id(std::string("Fallback"));
772       HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", drawing_name);
773       if(!lid){
774           return Err<int>("Drawing name does not match any role, Fallback is disabled");
775       }
776    }
777
778    auto rname = this->lookup_id(role);
779    if (!rname) {
780       // name does not exist yet, allocate surface id...
781       auto id = int(this->id_alloc.generate_id(role));
782       this->layers.add_surface(id, *lid);
783
784       // set the main_surface[_name] here and now
785       if (!this->layers.main_surface_name.empty() &&
786           this->layers.main_surface_name == drawing_name) {
787          this->layers.main_surface = id;
788          HMI_DEBUG("wm", "Set main_surface id to %u", id);
789       }
790
791       // Set map of (role, drawing_name)
792       this->role2drawingname[role] = std::string(drawing_name);
793
794       return Ok<int>(id);
795    }
796
797    // Check currently registered drawing names if it is already there.
798    return Err<int>("Surface already present");
799 }
800
801 char const *App::api_request_surface(char const *drawing_name,
802                                      char const *ivi_id) {
803    ST();
804    // Convert drawing_name to role
805    const char* role = this->convertDrawingNameToRole(drawing_name);
806
807    auto lid = this->layers.get_layer_id(std::string(role));
808    unsigned sid = std::stol(ivi_id);
809
810    if (!lid) {
811       /**
812        * register drawing_name as fallback and make it displayed.
813        */
814       lid = this->layers.get_layer_id(std::string("Fallback"));
815       HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", drawing_name);
816       if(!lid){
817           return "Drawing name does not match any role, Fallback is disabled";
818       }
819    }
820
821    auto rname = this->lookup_id(role);
822
823    if (rname) {
824        return "Surface already present";
825    }
826
827    // register pair drawing_name and ivi_id
828    this->id_alloc.register_name_id(role, sid);
829    this->layers.add_surface(sid, *lid);
830
831    // this surface is already created
832    HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", sid, *lid);
833
834    this->controller->layers[*lid]->add_surface(sid);
835    this->layout_commit();
836
837    return nullptr;
838 }
839
840 result<json_object *> App::api_get_display_info() {
841    // Check controller
842    if (!this->controller) {
843       return Err<json_object *>("ivi_controller global not available");
844    }
845
846    // Set display info
847    compositor::size o_size = this->controller->output_size;
848    compositor::size p_size = this->controller->physical_size;
849
850    json_object *object = json_object_new_object();
851    json_object_object_add(object, kKeyWidthPixel,  json_object_new_int(o_size.w));
852    json_object_object_add(object, kKeyHeightPixel, json_object_new_int(o_size.h));
853    json_object_object_add(object, kKeyWidthMm,     json_object_new_int(p_size.w));
854    json_object_object_add(object, kKeyHeightMm,    json_object_new_int(p_size.h));
855
856    return Ok<json_object *>(object);
857 }
858
859 result<json_object *> App::api_get_area_info(char const *drawing_name) {
860    HMI_DEBUG("wm", "called");
861
862    // Convert drawing_name to role
863    const char* role = this->convertDrawingNameToRole(drawing_name);
864
865    // Check drawing name, surface/layer id
866    auto const &surface_id = this->lookup_id(role);
867    if (!surface_id) {
868       return Err<json_object *>("Surface does not exist");
869    }
870
871    if (!this->controller->surface_exists(*surface_id)) {
872       return Err<json_object *>("Surface does not exist in controller!");
873    }
874
875    auto layer_id = this->layers.get_layer_id(*surface_id);
876    if (!layer_id) {
877       return Err<json_object *>("Surface is not on any layer!");
878    }
879
880    auto o_state = *this->layers.get_layout_state(*surface_id);
881    if (o_state == nullptr) {
882       return Err<json_object *>("Could not find layer for surface");
883    }
884
885    struct LayoutState &state = *o_state;
886    if ((state.main != *surface_id) && (state.sub != *surface_id)) {
887       return Err<json_object *>("Surface is inactive");
888    }
889
890    // Set area rectangle
891    compositor::rect area_info = this->area_info[*surface_id];
892    json_object *object = json_object_new_object();
893    json_object_object_add(object, kKeyX,      json_object_new_int(area_info.x));
894    json_object_object_add(object, kKeyY,      json_object_new_int(area_info.y));
895    json_object_object_add(object, kKeyWidth,  json_object_new_int(area_info.w));
896    json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h));
897
898    return Ok<json_object *>(object);
899 }
900
901 void App::activate(int id) {
902    auto ip = this->controller->sprops.find(id);
903    if (ip != this->controller->sprops.end()) {
904       this->controller->surfaces[id]->set_visibility(1);
905       char const *label =
906          this->lookup_name(id).value_or("unknown-name").c_str();
907
908       if ((0 == strcmp(label, "radio"))
909           || (0 == strcmp(label, "music"))
910           || (0 == strcmp(label, "map"))) {
911         for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i) {
912             if (id == *i) {
913                // Remove id
914                this->surface_bg.erase(i);
915
916                // Remove from BG layer (999)
917                HMI_DEBUG("wm", "Remove %s(%d) from BG layer", label, id);
918                this->controller->layers[999]->remove_surface(id);
919
920                // Add to FG layer (1001)
921                HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id);
922                this->controller->layers[1001]->add_surface(id);
923
924                for (int j : this->surface_bg) {
925                  HMI_DEBUG("wm", "Stored id:%d", j);
926                }
927                break;
928             }
929          }
930       }
931
932       this->layout_commit();
933
934       this->emit_visible(label);
935       this->emit_activated(label);
936    }
937 }
938
939 void App::deactivate(int id) {
940    auto ip = this->controller->sprops.find(id);
941    if (ip != this->controller->sprops.end()) {
942       char const *label =
943          this->lookup_name(id).value_or("unknown-name").c_str();
944
945       if ((0 == strcmp(label, "radio"))
946           || (0 == strcmp(label, "music"))
947           || (0 == strcmp(label, "map"))) {
948
949          // Store id
950          this->surface_bg.push_back(id);
951
952          // Remove from FG layer (1001)
953          HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id);
954          this->controller->layers[1001]->remove_surface(id);
955
956          // Add to BG layer (999)
957          HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id);
958          this->controller->layers[999]->add_surface(id);
959
960          for (int j : surface_bg) {
961             HMI_DEBUG("wm", "Stored id:%d", j);
962          }
963       }
964       else {
965          this->controller->surfaces[id]->set_visibility(0);
966       }
967
968       this->layout_commit();
969
970       this->emit_deactivated(label);
971       this->emit_invisible(label);
972    }
973 }
974
975 void App::deactivate(std::string role) {
976     auto const &id = this->lookup_id(role.c_str());
977     if (!id) {
978       HMI_ERROR("wm", "Surface does not exist");
979       return;
980     }
981     std::string drawing_name = this->role2drawingname[role];
982     HMI_DEBUG("wm", "Deactivate role:%s (drawing_name:%s)",
983               role.c_str(), drawing_name.c_str());
984
985     this->deactivate(*id);
986 }
987
988 void App::deactivate_main_surface() {
989    this->layers.main_surface = -1;
990    this->allocateWindowResource("deactivate",
991                                 this->layers.main_surface_name.c_str(), nullptr,
992                                 [](const char*){});
993 }
994
995 /**
996  * controller_hooks
997  */
998 void controller_hooks::surface_created(uint32_t surface_id) {
999    this->app->surface_created(surface_id);
1000 }
1001
1002 void controller_hooks::surface_removed(uint32_t surface_id) {
1003    this->app->surface_removed(surface_id);
1004 }
1005
1006 void controller_hooks::surface_visibility(uint32_t /*surface_id*/,
1007                                           uint32_t /*v*/) {}
1008
1009 void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/,
1010                                                      uint32_t /*x*/,
1011                                                      uint32_t /*y*/,
1012                                                      uint32_t /*w*/,
1013                                                      uint32_t /*h*/) {}
1014
1015 void App::setSurfaceSize(const char* role, const char* area) {
1016     HMI_DEBUG("wm", "role:%s area:%s", role, area);
1017
1018     // Get size of current area
1019     compositor::rect size = this->lm.getAreaSize(area);
1020
1021     // Set destination to the display rectangle
1022     auto const &surface_id = this->lookup_id(role);
1023     if (!this->controller->surface_exists(*surface_id)) {
1024         // Block until all pending request are processed by wayland display server
1025         // because waiting for the surface of new app is created
1026         this->display->roundtrip();
1027     }
1028     auto &s = this->controller->surfaces[*surface_id];
1029     s->set_destination_rectangle(size.x, size.y, size.w, size.h);
1030     this->layout_commit();
1031
1032     // Update area information
1033     this->area_info[*surface_id].x = size.x;
1034     this->area_info[*surface_id].y = size.y;
1035     this->area_info[*surface_id].w = size.w;
1036     this->area_info[*surface_id].h = size.h;
1037     HMI_DEBUG("wm", "Surface rect { %d, %d, %d, %d }",
1038               size.x, size.y, size.w, size.h);
1039
1040     // Emit syncDraw event
1041     const char* drawing_name = this->role2drawingname[role].c_str();
1042     this->emit_syncdraw(drawing_name, area,
1043                         size.x, size.y, size.w, size.h);
1044
1045     // Enqueue flushDraw event
1046     this->enqueue_flushdraw(*surface_id);
1047 }
1048
1049 void App::setAccelPedalPos(double val) {
1050     this->crr_car_info.accel_pedal_pos = val;
1051 }
1052
1053 extern const char* kDefaultAppDb;
1054 int App::loadAppDb() {
1055     HMI_DEBUG("wm", "Call");
1056
1057     // Get afm application installed dir
1058     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
1059     HMI_DEBUG("wm", "afm_app_install_dir:%s", afm_app_install_dir);
1060
1061     std::string file_name;
1062     if (!afm_app_install_dir) {
1063         HMI_ERROR("wm", "AFM_APP_INSTALL_DIR is not defined");
1064     }
1065     else {
1066         file_name = std::string(afm_app_install_dir) + std::string("/etc/app.db");
1067     }
1068
1069     // Load app.db
1070     json_object* json_obj;
1071     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
1072     if (0 > ret) {
1073         HMI_ERROR("wm", "Could not open app.db, so use default role information");
1074         json_obj = json_tokener_parse(kDefaultAppDb);
1075     }
1076     HMI_DEBUG("wm", "json_obj dump:%s", json_object_get_string(json_obj));
1077
1078     // Perse apps
1079     HMI_DEBUG("wm", "Perse apps");
1080     json_object* json_cfg;
1081     if (!json_object_object_get_ex(json_obj, "apps", &json_cfg)) {
1082         HMI_ERROR("wm", "Parse Error!!");
1083         return -1;
1084     }
1085
1086     int len = json_object_array_length(json_cfg);
1087     HMI_DEBUG("wm", "json_cfg len:%d", len);
1088     HMI_DEBUG("wm", "json_cfg dump:%s", json_object_get_string(json_cfg));
1089
1090     for (int i=0; i<len; i++) {
1091         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
1092         HMI_DEBUG("wm", "> json_tmp dump:%s", json_object_get_string(json_tmp));
1093
1094         const char* app = jh::getStringFromJson(json_tmp, "name");
1095         if (nullptr == app) {
1096             HMI_ERROR("wm", "Parse Error!!");
1097             return -1;
1098         }
1099         HMI_DEBUG("wm", "> app:%s", app);
1100
1101         const char* role = jh::getStringFromJson(json_tmp, "role");
1102         if (nullptr == role) {
1103             HMI_ERROR("wm", "Parse Error!!");
1104             return -1;
1105         }
1106         HMI_DEBUG("wm", "> role:%s", role);
1107
1108         this->drawingname2role[app] = std::string(role);
1109     }
1110
1111     // Check
1112     for(auto itr = this->drawingname2role.begin();
1113       itr != this->drawingname2role.end(); ++itr) {
1114         HMI_DEBUG("wm", "app:%s role:%s",
1115                   itr->first.c_str(), itr->second.c_str());
1116     }
1117
1118     // Release json_object
1119     json_object_put(json_obj);
1120
1121     return 0;
1122 }
1123
1124
1125 const char* kDefaultAppDb = "{ \
1126     \"apps\": [ \
1127         { \
1128             \"name\": \"HomeScreen\", \
1129             \"role\": \"homescreen\" \
1130         }, \
1131         { \
1132             \"name\": \"Music\", \
1133             \"role\": \"music\" \
1134         }, \
1135         { \
1136             \"name\": \"MediaPlayer\", \
1137             \"role\": \"music\" \
1138         }, \
1139         { \
1140             \"name\": \"Video\", \
1141             \"role\": \"video\" \
1142         }, \
1143         { \
1144             \"name\": \"VideoPlayer\", \
1145             \"role\": \"video\" \
1146         }, \
1147         { \
1148             \"name\": \"WebBrowser\", \
1149             \"role\": \"browser\" \
1150         }, \
1151         { \
1152             \"name\": \"Radio\", \
1153             \"role\": \"radio\" \
1154         }, \
1155         { \
1156             \"name\": \"Phone\", \
1157             \"role\": \"phone\" \
1158         }, \
1159         { \
1160             \"name\": \"Navigation\", \
1161             \"role\": \"map\" \
1162         }, \
1163         { \
1164             \"name\": \"HVAC\", \
1165             \"role\": \"hvac\" \
1166         }, \
1167         { \
1168             \"name\": \"Settings\", \
1169             \"role\": \"settings\" \
1170         }, \
1171         { \
1172             \"name\": \"Dashboard\", \
1173             \"role\": \"dashboard\" \
1174         }, \
1175         { \
1176             \"name\": \"POI\", \
1177             \"role\": \"poi\" \
1178         }, \
1179         { \
1180             \"name\": \"Mixer\", \
1181             \"role\": \"mixer\" \
1182         } \
1183     ] \
1184 }";
1185
1186
1187 }  // namespace wm