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