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