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