Add policy of switchng accel pedal status to dummy stm
[apps/agl-service-windowmanager.git] / src / layout_manager / layout.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
18 #include <json-c/json.h>
19 #include "layout.hpp"
20 #include "json_helper.hpp"
21 #include "hmi-debug.h"
22
23
24 LayoutManager::LayoutManager() {
25     HMI_DEBUG("wm:lm", "Call");
26 }
27
28 int LayoutManager::initialize() {
29     HMI_DEBUG("wm:lm", "Call");
30
31     int ret = 0;
32
33     // Load layout.db
34     ret = this->loadLayoutDb();
35     if (0 > ret) {
36         HMI_ERROR("wm:lm", "Load layout.db Error!!");
37         return ret;
38     }
39
40     TypeLayouts layout;
41     TypeAreas area;
42     TypeRolCtg rol_ctg;
43
44     rol_ctg["none"] = "none";
45     area["none"]    = rol_ctg;
46     layout["none"]  = area;
47
48     this->prv_layers_["on_screen"]  = layout;
49     this->prv_layers_["apps"]       = layout;
50     this->prv_layers_["homescreen"] = layout;
51     this->prv_layers_["restriction"] = layout;
52
53     this->crr_layers_["on_screen"]  = layout;
54     this->crr_layers_["apps"]       = layout;
55     this->crr_layers_["homescreen"] = layout;
56     this->crr_layers_["restriction"] = layout;
57
58     this->prv_layers_car_stop_["on_screen"]  = layout;
59     this->prv_layers_car_stop_["apps"]       = layout;
60     this->prv_layers_car_stop_["homescreen"] = layout;
61     this->prv_layers_car_stop_["restriction"] = layout;
62
63     return ret;
64 }
65
66 bool LayoutManager::updateLayout(json_object* obj,
67                                      const char* new_role, const char* category) {
68     HMI_DEBUG("wm:lm", "Call");
69
70     bool ret = false;
71
72     // Check accelerator pedal state change
73     json_object* json_accel_pedal;
74     if (!json_object_object_get_ex(obj, "accel_pedal", &json_accel_pedal)) {
75         HMI_ERROR("wm:lm", "Parse Error!!");
76         return -1;
77     }
78
79     json_bool is_accel_pedal_state_changed;
80     std::string accel_pedal_state = "";
81     is_accel_pedal_state_changed = jh::getBoolFromJson(json_accel_pedal, "is_changed");
82     if (is_accel_pedal_state_changed) {
83         // If car state is changed, get car state
84         accel_pedal_state = jh::getStringFromJson(json_accel_pedal, "state");
85     }
86
87     // Check car state change
88     json_object* json_car;
89     if (!json_object_object_get_ex(obj, "car", &json_car)) {
90         HMI_ERROR("wm:lm", "Parse Error!!");
91         return -1;
92     }
93
94     json_bool is_car_state_changed;
95     std::string car_state = "";
96     is_car_state_changed = jh::getBoolFromJson(json_car, "is_changed");
97     if (is_car_state_changed) {
98         // If car state is changed, get car state
99         car_state = jh::getStringFromJson(json_car, "state");
100     }
101
102     // Update layout of all layers
103     json_object* json_layers;
104     if (!json_object_object_get_ex(obj, "layers", &json_layers)) {
105         HMI_ERROR("wm:lm", "Parse Error!!");
106         return -1;
107     }
108
109     int len = json_object_array_length(json_layers);
110     HMI_DEBUG("wm:lm", "json_layers len:%d", len);
111     HMI_DEBUG("wm:lm", "json_layers dump:%s", json_object_get_string(json_layers));
112
113     for (int i=0; i<len; i++) {
114         json_object* json_tmp = json_object_array_get_idx(json_layers, i);
115
116         // Get layer name and json_object
117         const char* layer;
118         json_object* json_layer;
119         json_object_object_foreach(json_tmp, key, val) {
120             layer = key;
121             json_layer = val;
122             HMI_DEBUG("wm:lm", "Try to update %s layer state", layer);
123         }
124
125         // Store previous state
126         this->prv_layers_[layer] = this->crr_layers_[layer];
127         std::string prv_layout_name = this->prv_layers_[layer].begin()->first;
128
129         // If car state is changed car_stop -> car_run,
130         // OR accel pedal state is changed accel_pedal_off -> accel_pedal_on,
131         // store current state for state of car stop
132         if (((is_car_state_changed) && ("car_run" == car_state))
133             || ((is_accel_pedal_state_changed)
134                 && ("accel_pedal_on" == accel_pedal_state))) {
135             HMI_DEBUG("wm:lm", "Store current state for state of car stop");
136             this->prv_layers_car_stop_[layer] = this->crr_layers_[layer];
137         }
138
139         json_object* json_is_changed;
140         if (!json_object_object_get_ex(json_layer, "is_changed", &json_is_changed)) {
141             HMI_ERROR("wm:lm", "Not found key \"is_changed\"");
142            return false;
143         }
144
145         // If layer state is changed
146         if (json_object_get_boolean(json_is_changed)) {
147             // Set layout changed flag
148             this->is_layout_changed_[layer] = true;
149
150             json_object* json_state;
151             if (!json_object_object_get_ex(json_layer, "state", &json_state)) {
152                 HMI_ERROR("wm:lm", "Not found key \"state\"");
153                 return false;
154             }
155
156             const char* crr_layout_name = json_object_get_string(json_state);
157             HMI_DEBUG("wm:lm", "crr state: %s", crr_layout_name);
158
159             TypeLayouts crr_layout;
160             if (((is_car_state_changed) && ("car_stop" == car_state))
161                 || ((is_accel_pedal_state_changed)
162                     && ("accel_pedal_off" == accel_pedal_state))) {
163                 // If car state is changed car_run -> car_stop,
164                 // OR accel pedal state is changed accel_pedal_on -> accel_pedal_off,
165                 // restore state of car stop
166                 HMI_DEBUG("wm:lm", "Restore state of car stop");
167                 crr_layout = this->prv_layers_car_stop_[layer];
168             }
169             else if ("none" == std::string(crr_layout_name)) {
170               // If current layout is "none",
171               // current areas is set with "none"
172               TypeAreas area;
173               TypeRolCtg rol_ctg;
174               rol_ctg["none"] = "none";
175               area["none"] = rol_ctg;
176               crr_layout["none"] = area;
177             }
178             else {
179                 if (std::string(crr_layout_name) == prv_layout_name) {
180                     // If previous layout is same with current,
181                     // previous areas are copied to current
182                     crr_layout[crr_layout_name] = this->prv_layers_[layer][crr_layout_name];
183                 }
184                 else {
185                     // If previous layout is NOT same with current,
186                     // current areas is set with default value
187                     crr_layout[crr_layout_name] = this->layout_define_[crr_layout_name];
188                 }
189
190                 // Update role in new area
191                 if (is_car_state_changed || is_accel_pedal_state_changed) {
192                     // Updating role is not necessary
193                     // because new_role is not specified
194                     // when car or accel pedal state is changed
195                 }
196                 else {
197                     // Get new_area for new role
198                     std::string new_area = this->getAreaName(this->layout_define_[crr_layout_name],
199                                                              new_role, category);
200
201                     TypeRolCtg crr_role;
202                     crr_role["role"] = std::string(new_role);
203                     crr_layout[crr_layout_name][new_area] = crr_role;
204                 }
205             }
206
207             // Update layer state
208             this->crr_layers_[layer] = crr_layout;
209
210             // Check
211             for (auto itr_layout = this->crr_layers_[layer].begin();
212                  itr_layout != this->crr_layers_[layer].end(); ++itr_layout) {
213               for (auto itr_area = itr_layout->second.begin();
214                    itr_area != itr_layout->second.end(); ++itr_area) {
215                 for (auto itr_role = itr_area->second.begin();
216                      itr_role != itr_area->second.end(); ++itr_role) {
217                   HMI_DEBUG("wm:lm", "layout:%s, area:%s, rol_ctg:%s, name:%s",
218                             itr_layout->first.c_str(), itr_area->first.c_str(),
219                             itr_role->first.c_str(), itr_role->second.c_str());
220                 }
221               }
222             }
223
224             ret = true;
225         }
226         else {
227             // Clear layout changed flag
228             this->is_layout_changed_[layer] = false;
229         }
230     }
231     return ret;
232 }
233
234 // TODO: This API is for workaround, so this will be removed
235 void LayoutManager::updateArea(const char* layer, const char* role, const char* area) {
236     this->crr_layers_[layer].begin()->second[area]["role"] = std::string(role);
237 }
238
239 LayoutManager::TypeLayers LayoutManager::getCurrentLayers() {
240     return this->crr_layers_;
241 }
242
243 LayoutManager::TypeLayers LayoutManager::getPreviousLayers() {
244     return this->prv_layers_;
245 }
246
247 compositor::rect LayoutManager::getAreaSize(const char* area) {
248     return this->area2size_[area];
249 }
250
251 std::string LayoutManager::getAreaName(TypeAreas areas, const char* role, const char* category) {
252     for (auto itr_area = areas.begin(); itr_area != areas.end(); ++itr_area) {
253         std::string area_name = itr_area->first;
254         TypeRolCtg rol_ctg = itr_area->second;
255
256         if ("role" == rol_ctg.begin()->first) {
257             if (std::string(role) == rol_ctg.begin()->second) {
258                 return area_name;
259             }
260         }
261         else if ("category" == rol_ctg.begin()->first) {
262             if (std::string(category) == rol_ctg.begin()->second) {
263                 return area_name;
264             }
265         }
266         else {
267             return std::string("none");
268         }
269     }
270     return std::string("none");
271 }
272
273
274 bool LayoutManager::isLayoutChanged(const char* layer) {
275     return this->is_layout_changed_[layer];
276 }
277
278
279 extern const char* kDefaultLayoutDb;
280 int LayoutManager::loadLayoutDb() {
281     HMI_DEBUG("wm:lm", "Call");
282
283     // Get afm application installed dir
284     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
285     HMI_DEBUG("wm:lm", "afm_app_install_dir:%s", afm_app_install_dir);
286
287     std::string file_name;
288     if (!afm_app_install_dir) {
289         HMI_ERROR("wm:lm", "AFM_APP_INSTALL_DIR is not defined");
290     }
291     else {
292         file_name = std::string(afm_app_install_dir) + std::string("/etc/layout.db");
293     }
294
295     // Load layout.db
296     json_object* json_obj;
297     int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
298     if (0 > ret) {
299         HMI_DEBUG("wm:lm", "Could not open layout.db, so use default layout information");
300         json_obj = json_tokener_parse(kDefaultLayoutDb);
301     }
302     HMI_DEBUG("wm:lm", "json_obj dump:%s", json_object_get_string(json_obj));
303
304     // Perse layouts
305     HMI_DEBUG("wm:lm", "Perse layouts");
306     json_object* json_cfg;
307     if (!json_object_object_get_ex(json_obj, "layouts", &json_cfg)) {
308         HMI_ERROR("wm:lm", "Parse Error!!");
309         return -1;
310     }
311
312     int len = json_object_array_length(json_cfg);
313     HMI_DEBUG("wm:lm", "json_cfg len:%d", len);
314     HMI_DEBUG("wm:lm", "json_cfg dump:%s", json_object_get_string(json_cfg));
315
316     const char* layout;
317     const char* role;
318     const char* category;
319     for (int i=0; i<len; i++) {
320         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
321
322         layout = jh::getStringFromJson(json_tmp, "name");
323         if (nullptr == layout) {
324             HMI_ERROR("wm:lm", "Parse Error!!");
325             return -1;
326         }
327         HMI_DEBUG("wm:lm", "> layout:%s", layout);
328
329         json_object* json_area_array;
330         if (!json_object_object_get_ex(json_tmp, "areas", &json_area_array)) {
331           HMI_ERROR("wm:lm", "Parse Error!!");
332           return -1;
333         }
334
335         int len_area = json_object_array_length(json_area_array);
336         HMI_DEBUG("wm:lm", "json_area_array len:%d", len_area);
337         HMI_DEBUG("wm:lm", "json_area_array dump:%s", json_object_get_string(json_area_array));
338
339         TypeAreas areas;
340         for (int j=0; j<len_area; j++) {
341             json_object* json_area = json_object_array_get_idx(json_area_array, j);
342
343             const char* area = jh::getStringFromJson(json_area, "name");
344             if (nullptr == area) {
345               HMI_ERROR("wm:lm", "Parse Error!!");
346               return -1;
347             }
348             HMI_DEBUG("wm:lm", ">> area:%s", area);
349
350             TypeRolCtg rol_ctg_name;
351             role = jh::getStringFromJson(json_area, "role");
352             if (nullptr == role) {
353                 category = jh::getStringFromJson(json_area, "category");
354                 if (nullptr == category) {
355                   HMI_ERROR("wm:lm", "Parse Error!!");
356                   return -1;
357                 }
358                 rol_ctg_name["category"] = std::string(category);
359                 HMI_DEBUG("wm:lm", ">>> category:%s", category);
360             }
361             else {
362                 rol_ctg_name["role"] = std::string(role);
363                 HMI_DEBUG("wm:lm", ">>> role:%s", role);
364             }
365
366             areas[area] = rol_ctg_name;
367         }
368
369         this->layout_define_[layout] = areas;
370     }
371
372     // Check
373     for(auto itr_layout = this->layout_define_.begin();
374       itr_layout != this->layout_define_.end(); ++itr_layout) {
375         for (auto itr_area = itr_layout->second.begin();
376           itr_area != itr_layout->second.end(); ++itr_area) {
377             for (auto itr_role = itr_area->second.begin();
378               itr_role != itr_area->second.end(); ++itr_role) {
379                 HMI_DEBUG("wm:lm", "layout:%s, area:%s, rol_ctg:%s, name:%s",
380                           itr_layout->first.c_str(), itr_area->first.c_str(),
381                           itr_role->first.c_str(), itr_role->second.c_str());
382             }
383         }
384     }
385
386     // Perse areas
387     HMI_DEBUG("wm:lm", "Perse areas");
388     if (!json_object_object_get_ex(json_obj, "areas", &json_cfg)) {
389         HMI_ERROR("wm:lm", "Parse Error!!");
390         return -1;
391     }
392
393     len = json_object_array_length(json_cfg);
394     HMI_DEBUG("wm:lm", "json_cfg len:%d", len);
395     HMI_DEBUG("wm:lm", "json_cfg dump:%s", json_object_get_string(json_cfg));
396
397     const char* area;
398     for (int i=0; i<len; i++) {
399         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
400         HMI_DEBUG("wm:lm", "> json_tmp dump:%s", json_object_get_string(json_tmp));
401
402         area = jh::getStringFromJson(json_tmp, "name");
403         if (nullptr == area) {
404             HMI_ERROR("wm:lm", "Parse Error!!");
405             return -1;
406         }
407         HMI_DEBUG("wm:lm", "> area:%s", area);
408
409         json_object* json_rect;
410         if (!json_object_object_get_ex(json_tmp, "rect", &json_rect)) {
411           HMI_ERROR("wm:lm", "Parse Error!!");
412           return -1;
413         }
414         HMI_DEBUG("wm:lm", "> json_rect dump:%s", json_object_get_string(json_rect));
415
416         compositor::rect area_size;
417         area_size.x = jh::getIntFromJson(json_rect, "x");
418         area_size.y = jh::getIntFromJson(json_rect, "y");
419         area_size.w = jh::getIntFromJson(json_rect, "w");
420         area_size.h = jh::getIntFromJson(json_rect, "h");
421
422         this->area2size_[area] = area_size;
423     }
424
425     // Check
426     for(auto itr = this->area2size_.begin();
427       itr != this->area2size_.end(); ++itr) {
428         HMI_DEBUG("wm:lm", "area:%s x:%d y:%d w:%d h:%d",
429                   itr->first.c_str(), itr->second.x, itr->second.y,
430                   itr->second.w, itr->second.h);
431     }
432
433     // Release json_object
434     json_object_put(json_obj);
435
436     return 0;
437 }
438
439 const char* kDefaultLayoutDb = "{ \
440     \"layouts\": [ \
441         { \
442             \"name\": \"pu\", \
443             \"layer\": \"on_screen\", \
444             \"areas\": [ \
445                 { \
446                     \"name\": \"pop_up\", \
447                     \"role\": \"incomming_call\" \
448                 } \
449             ] \
450         }, \
451         { \
452             \"name\": \"sa\", \
453             \"layer\": \"on_screen\", \
454             \"areas\": [ \
455                 { \
456                     \"name\": \"system_alert\", \
457                     \"role\": \"system_alert\" \
458                 } \
459             ] \
460         }, \
461         { \
462             \"name\": \"m1\", \
463             \"layer\": \"apps\", \
464             \"areas\": [ \
465                 { \
466                     \"name\": \"normal\", \
467                     \"role\": \"map\" \
468                 } \
469             ] \
470         }, \
471         { \
472             \"name\": \"m2\", \
473             \"layer\": \"apps\", \
474             \"areas\": [ \
475                 { \
476                     \"name\": \"split.main\", \
477                     \"role\": \"map\" \
478                 }, \
479                 { \
480                     \"name\": \"split.sub\", \
481                     \"category\": \"hvac\" \
482                 } \
483             ] \
484         }, \
485         { \
486             \"name\": \"mf\", \
487             \"layer\": \"apps\", \
488             \"areas\": [ \
489                 { \
490                     \"name\": \"full\", \
491                     \"role\": \"map\" \
492                 } \
493             ] \
494         }, \
495         { \
496             \"name\": \"s1\", \
497             \"layer\": \"apps\", \
498             \"areas\": [ \
499                 { \
500                     \"name\": \"normal\", \
501                     \"category\": \"splitable\" \
502                 } \
503             ] \
504         }, \
505         { \
506             \"name\": \"s2\", \
507             \"layer\": \"apps\", \
508             \"areas\": [ \
509                 { \
510                     \"name\": \"split.main\", \
511                     \"category\": \"splitable\" \
512                 }, \
513                 { \
514                     \"name\": \"split.sub\", \
515                     \"category\": \"splitable\" \
516                 } \
517             ] \
518         }, \
519         { \
520             \"name\": \"g\", \
521             \"layer\": \"apps\", \
522             \"areas\": [ \
523                 { \
524                     \"name\": \"normal\", \
525                     \"category\": \"general\" \
526                 } \
527             ] \
528         }, \
529         { \
530             \"name\": \"hs\", \
531             \"layer\": \"homescreen\", \
532             \"areas\": [ \
533                 { \
534                     \"name\": \"full\", \
535                     \"role\": \"homescreen\" \
536                 } \
537             ] \
538         } \
539     ], \
540     \"areas\": [ \
541         { \
542             \"name\": \"normal\", \
543             \"rect\": { \
544                 \"x\": 0, \
545                 \"y\": 218, \
546                 \"w\": 1080, \
547                 \"h\": 1488 \
548             } \
549         }, \
550         { \
551             \"name\": \"split.main\", \
552             \"rect\": { \
553                 \"x\": 0, \
554                 \"y\": 218, \
555                 \"w\": 1080, \
556                 \"h\": 744 \
557             } \
558         }, \
559         { \
560             \"name\": \"split.sub\", \
561             \"rect\": { \
562                 \"x\": 0, \
563                 \"y\": 962, \
564                 \"w\": 1080, \
565                 \"h\": 744 \
566             } \
567         }, \
568         { \
569             \"name\": \"full\", \
570             \"rect\": { \
571                 \"x\": 0, \
572                 \"y\": 0, \
573                 \"w\": 1080, \
574                 \"h\": 1920 \
575             } \
576         }, \
577         { \
578             \"name\": \"pop_up\", \
579             \"rect\": { \
580                 \"x\": 0, \
581                 \"y\": 640, \
582                 \"w\": 1080, \
583                 \"h\": 640 \
584             } \
585         }, \
586         { \
587             \"name\": \"system_alert\", \
588             \"rect\": { \
589                 \"x\": 0, \
590                 \"y\": 640, \
591                 \"w\": 1080, \
592                 \"h\": 640 \
593             } \
594         } \
595     ] \
596 }";