PolicyManager manage layout information (area, category, role)
[apps/agl-service-windowmanager.git] / src / policy_manager / policy_manager.cpp
1 /*
2  * Copyright (c) 2018 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 <fstream>
19 #include <sstream>
20 #include <istream>
21 #include <thread>
22 #include <map>
23 #include <systemd/sd-event.h>
24 #include <json-c/json.h>
25 #include "policy_manager.hpp"
26 #include "hmi-debug.h"
27
28 namespace stm {
29 extern "C" {
30 #include "dummy_stm.h"
31 }
32 } // namespace stm
33
34
35 namespace pm {
36 typedef struct AreaState {
37     std::string name;
38     std::string category;
39     std::string role;
40 } AreaState;
41
42 typedef struct LayoutState {
43     std::string name;
44     std::map<std::string, int> category_num;
45 //    int category_num[stm::gStmCategoryNoNum];
46     std::vector<AreaState> area_list;
47 } LayoutState;
48
49 typedef struct LayerState {
50     std::string name;
51     LayoutState layout_state;
52 } LayerState;
53
54 struct sd_event* event_loop;
55 std::map<int, struct sd_event_source*> event_source_list;
56 std::map<int, std::string> g_event_info_list;
57 PolicyManager::CallbackTable callback;
58
59 std::unordered_map<std::string, LayerState> g_prv_layers;
60 std::unordered_map<std::string, LayerState> g_crr_layers;
61 std::unordered_map<std::string, LayerState> g_prv_layers_car_stop;
62 std::unordered_map<std::string, LayoutState> g_default_layouts;
63 }  // namespace pm
64
65
66 PolicyManager::PolicyManager() :
67   eventname2no_(),
68   categoryname2no_(),
69   areaname2no_(),
70   role2category_(),
71   category2role_(),
72   role2defaultarea_()
73 {
74     HMI_DEBUG("wm:pm", "Call");
75 }
76
77 int PolicyManager::initialize() {
78     HMI_DEBUG("wm:pm", "Call");
79
80     int ret = 0;
81
82     // Create convert map
83     for (unsigned int i=0; i<STM_NUM_EVT; i++) {
84         HMI_DEBUG("wm:pm", "event name:%s no:%d", stm::gStmEventName[i], stm::gStmEventNo[i]);
85         this->eventname2no_[stm::gStmEventName[i]] = stm::gStmEventNo[i];
86     }
87
88     for (int i = stm::gStmCategoryNoMin; i <= stm::gStmCategoryNoMax; i++) {
89         HMI_DEBUG("wm:pm", "category name:%s no:%d", stm::gStmCategoryName[i], stm::gStmCategoryNo[i]);
90         this->categoryname2no_[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
91     }
92
93     for (unsigned int i=0; i<STM_NUM_ARA; i++) {
94         HMI_DEBUG("wm:pm", "area name:%s no:%d", stm::gStmAreaName[i], stm::gStmAreaNo[i]);
95         this->areaname2no_[stm::gStmAreaName[i]] = stm::gStmAreaNo[i];
96     }
97
98     // Load role.db
99     ret = this->loadRoleDb();
100     if (0 > ret) {
101         HMI_ERROR("wm:pm", "Load role.db Error!!");
102         return ret;
103     }
104
105     // Load layout.db
106     ret = this->loadLayoutDb();
107     if (0 > ret) {
108         HMI_ERROR("wm:pm", "Load layout.db Error!!");
109         return ret;
110     }
111
112     // Initialize current/previous state of layers
113     pm::AreaState init_area;
114     pm::LayoutState init_layout;
115     init_area.name     = "none";
116     init_area.category = "none";
117     init_area.role     = "none";
118     init_layout.area_list.push_back(init_area);
119
120     for (int i = stm::gStmLayerNoMin; i <= stm::gStmLayerNoMax; i++) {
121         const char* layer_name = stm::gStmLayerName[i];
122         pm::g_crr_layers[layer_name].name          = layer_name;
123         pm::g_crr_layers[layer_name].layout_state  = init_layout;
124     }
125
126     pm::g_prv_layers = pm::g_crr_layers;
127
128     // Initialize StateTransitioner
129     stm::stmInitialize();
130
131     // Initialize sd_event loop
132     ret = this->initializeSdEventLoop();
133     if (0 > ret) {
134         HMI_ERROR("wm:pm", "Failed to initializeSdEventLoop!!");
135         return ret;
136     }
137
138     return ret;
139 }
140
141 int PolicyManager::initializeSdEventLoop() {
142     // Get default event loop object
143     int ret = sd_event_new(&(pm::event_loop));
144     if (0 > ret) {
145         HMI_ERROR("wm:pm", "Faild to sd_event_default: errno:%d", ret);
146         return -1;
147     }
148
149     // Create thread for sd_event and detach
150     std::thread sd_event_loop([this]() {
151         while (1) {
152             sd_event_run(pm::event_loop, 1000);
153         }
154     });
155     sd_event_loop.detach();
156
157     return 0;
158 }
159
160 static void addStateToJson(
161   const char* key, int is_changed, const char* state, json_object** json_out) {
162     if ((nullptr == key) || (nullptr == state) || (nullptr == json_out)) {
163         HMI_ERROR("wm:pm", "Argument is nullptr!!!");
164         return;
165     }
166
167     json_object* json_obj = json_object_new_object();
168     json_object_object_add(json_obj, "is_changed", json_object_new_boolean(is_changed));
169     if (is_changed) {
170         HMI_DEBUG("wm:pm", "%s: state changed (%s)", key, state);
171         json_object_object_add(json_obj, "state", json_object_new_string(state));
172     }
173     json_object_object_add(*json_out, key, json_obj);
174 }
175
176 static int checkPolicyEntry(int event, uint64_t delay_ms, const char* role);
177 static int checkPolicy(sd_event_source *source, void *data) {
178     HMI_DEBUG("wm:pm", "Call");
179     HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
180
181     int event_data = *((int*)data);
182
183     int event_no, category_no, area_no;
184     event_no    = (event_data & STM_MSK_EVT_NO) - 1;
185     category_no = ((event_data & STM_MSK_CTG_NO) >> 8) - 1;
186     area_no     = ((event_data & STM_MSK_ARA_NO) >> 16) - 1;
187     HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
188               stm::gStmEventName[event_no],
189               stm::gStmCategoryName[category_no],
190               stm::gStmAreaName[area_no]);
191
192     // Transition state
193     stm::stm_state_t crr_state;
194     int ret = stm::stmTransitionState(event_data, &crr_state);
195     if (0 > ret) {
196         HMI_ERROR("wm:pm", "Error!!");
197         return -1;
198     }
199
200     HMI_DEBUG("wm:pm", "parking brake state     (is_changed:%d state:%d:%s)",
201               crr_state.parking_brake.is_changed,
202               crr_state.parking_brake.state,
203               stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state]);
204     HMI_DEBUG("wm:pm", "accelerator pedal state (is_changed:%d state:%d:%s)",
205               crr_state.accel_pedal.is_changed,
206               crr_state.accel_pedal.state,
207               stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state]);
208     HMI_DEBUG("wm:pm", "lightstatus brake state (is_changed:%d state:%d:%s)",
209               crr_state.lightstatus_brake.is_changed,
210               crr_state.lightstatus_brake.state,
211               stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state]);
212     HMI_DEBUG("wm:pm", "car state               (is_changed:%d state:%d:%s)",
213               crr_state.car.is_changed,
214               crr_state.car.state,
215               stm::gStmCarStateNo2Name[crr_state.car.state]);
216     HMI_DEBUG("wm:pm", "lamp state              (is_changed:%d state:%d:%s)",
217               crr_state.lamp.is_changed,
218               crr_state.lamp.state,
219               stm::gStmLampStateNo2Name[crr_state.lamp.state]);
220     HMI_DEBUG("wm:pm", "restriction mode state  (is_changed:%d state:%d:%s)",
221               crr_state.restriction_mode.is_changed,
222               crr_state.restriction_mode.state,
223               stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state]);
224     HMI_DEBUG("wm:pm", "homescreen state        (is_changed:%d state:%d:%s)",
225               crr_state.layer[stm::gStmLayerNoHomescreen].is_changed,
226               crr_state.layer[stm::gStmLayerNoHomescreen].state,
227               stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state]);
228     HMI_DEBUG("wm:pm", "apps state              (is_changed:%d state:%d:%s)",
229               crr_state.layer[stm::gStmLayerNoApps].is_changed,
230               crr_state.layer[stm::gStmLayerNoApps].state,
231               stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoApps].state]);
232     HMI_DEBUG("wm:pm", "restriction state       (is_changed:%d state:%d:%s)",
233               crr_state.layer[stm::gStmLayerNoRestriction].is_changed,
234               crr_state.layer[stm::gStmLayerNoRestriction].state,
235               stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoRestriction].state]);
236     HMI_DEBUG("wm:pm", "on_screen state         (is_changed:%d state:%d:%s)",
237               crr_state.layer[stm::gStmLayerNoOnScreen].is_changed,
238               crr_state.layer[stm::gStmLayerNoOnScreen].state,
239               stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoOnScreen].state]);
240
241 #if 1 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
242     // Store previous layers
243     pm::g_prv_layers = pm::g_crr_layers;
244
245     std::string role = pm::g_event_info_list[event_data];
246     std::string event = std::string(stm::gStmEventName[event_no]);
247     std::string category = std::string(stm::gStmCategoryName[category_no]);
248     std::string area = std::string(stm::gStmAreaName[area_no]);
249
250     for (int layer_no = stm::gStmLayerNoMin;
251          layer_no <= stm::gStmLayerNoMax; layer_no++) {
252         const char* layer_name = stm::gStmLayerName[layer_no];
253         HMI_DEBUG("wm:pm", "LAYER:%s", layer_name);
254
255 #if 1
256         // If restriction mode is changed off -> on,
257         // store current state for state of restriction mode off
258         if ((crr_state.restriction_mode.is_changed)
259             && (stm::gStmRestrictionModeStateNoOn == crr_state.restriction_mode.state)) {
260             HMI_DEBUG("wm:lm", "Store current state for state of restriction mode off");
261             pm::g_prv_layers_car_stop[layer_name] = pm::g_crr_layers[layer_name];
262         }
263 #else
264         // If car state is changed car_stop -> car_run,
265         // store current state for state of car stop
266         if ((crr_state.car.is_changed)
267             && (stm::gStmCarStateNoRun == crr_state.car.state)) {
268             HMI_DEBUG("wm:lm", "Store current state for state of car stop");
269             pm::g_prv_layers_car_stop[layer_name] = pm::g_crr_layers[layer_name];
270         }
271 #endif
272
273
274         // This layer is changed?
275         if (crr_state.layer[layer_no].is_changed) {
276             // Get previous layout name of this layer
277             pm::LayoutState prv_layout_state =  pm::g_prv_layers[layer_name].layout_state;
278             std::string prv_layout_name = prv_layout_state.name;
279
280             // Get current layout name of this layer
281             int crr_layout_state_no =  crr_state.layer[layer_no].state;
282             std::string crr_layout_name = std::string(stm::gStmLayoutNo2Name[crr_layout_state_no]);
283
284             pm::LayoutState crr_layout_state;
285 #if 1
286             if ((crr_state.restriction_mode.is_changed)
287                 && (stm::gStmRestrictionModeStateNoOff == crr_state.restriction_mode.state)) {
288                 // If restriction mode is changed on -> off,
289                 // restore state of restriction mode off
290                 HMI_DEBUG("wm:lm", "Restriction mode is changed on -> off, so restore state of restriction mode off");
291                 crr_layout_state = pm::g_prv_layers_car_stop[layer_name].layout_state;
292 #else
293             if ((crr_state.car.is_changed)
294                 && (stm::gStmCarStateNoStop == crr_state.car.state)) {
295                 // If car state is changed car_run -> car_stop,
296                 // restore state of car stop
297                 HMI_DEBUG("wm:lm", "Car state is changed car_run -> car_stop, so restore state of car stop");
298                 crr_layout_state = pm::g_prv_layers_car_stop[layer_name].layout_state;
299 #endif
300             }
301             else if ("none" == crr_layout_name) {
302                 // If current layout is "none",
303                 // current areas is set with "none"
304                 HMI_DEBUG("wm:pm", "Current layout is \"none\"");
305                 pm::AreaState crr_area_state;
306                 crr_area_state.name     = "none";
307                 crr_area_state.category = "none";
308                 crr_area_state.role     = "none";
309                 crr_layout_state.name = "none";
310                 crr_layout_state.area_list.push_back(crr_area_state);
311             }
312             else {
313                 if (prv_layout_name == crr_layout_name) {
314                     // If previous layout is same with current,
315                     // previous areas are copied to current
316                     HMI_DEBUG("wm:lm", "Previous layout is same with current");
317                     crr_layout_state = prv_layout_state;
318                 }
319                 else {
320                     // If previous layout is NOT same with current,
321                     // current areas is set with default value
322                     HMI_DEBUG("wm:lm", "Previous layout is NOT same with current");
323                     crr_layout_state = pm::g_default_layouts[crr_layout_name];
324                 }
325
326                 // Update role in new area
327 #if 1
328                 if (crr_state.restriction_mode.is_changed) {
329                     // Updating role is not necessary
330                     // because new_role is not specified
331                     // when restriction mode is changed
332                     HMI_DEBUG("wm:lm", "Updating role is not necessary because new_role is not specified when restriction mode is changed");
333 #else
334                 if (crr_state.car.is_changed) {
335                     // Updating role is not necessary
336                     // because new_role is not specified
337                     // when car state is changed
338                     HMI_DEBUG("wm:lm", "Updating role is not necessary because new_role is not specified when car state is changed");
339 #endif
340                 }
341                 else {
342
343                     std::map<std::string, std::vector<pm::AreaState>> ctg_list;
344                     for (int ctg_no=stm::gStmCategoryNoMin;
345                          ctg_no<=stm::gStmCategoryNoMax; ctg_no++) {
346                         const char* ctg = stm::gStmCategoryName[ctg_no];
347                         HMI_DEBUG("wm:pm", "ctg:%s", ctg);
348
349                         // Create area list of previous/current app
350                         std::vector<pm::AreaState> area_list;
351                         for (pm::AreaState area_state : prv_layout_state.area_list) {
352                             if (std::string(ctg) == area_state.category) {
353                                 HMI_DEBUG("wm:pm", "push area_state to prv list");
354                                 area_list.push_back(area_state);
355                             }
356                         }
357
358                         int prv_ctg_num = prv_layout_state.category_num[ctg];
359                         int crr_ctg_num = crr_layout_state.category_num[ctg];
360                         HMI_DEBUG("wm:pm", "crr_ctg_num:%d prv_ctg_num:%d", crr_ctg_num, prv_ctg_num);
361
362                         if (crr_ctg_num < prv_ctg_num) {
363                             HMI_DEBUG("wm:pm", "crr_ctg_num < prv_ctg_num");
364                             if (0 == strcmp(ctg, category.c_str())) {
365                                 HMI_DEBUG("wm:pm", "category of requested role is same");
366                                 for (auto i = area_list.begin(); i != area_list.end(); ++i) {
367                                     if ((role == i->role) && (area == i->name)) {
368                                         HMI_DEBUG("wm:pm", "remove requested role data");
369                                         area_list.erase(i);
370                                     }
371                                 }
372                             }
373                             else {
374                                 HMI_DEBUG("wm:pm", "remove the oldest area data");
375                                 area_list.erase(area_list.begin());
376                             }
377                         }
378                         else if (crr_ctg_num >= prv_ctg_num) {
379                             HMI_DEBUG("wm:pm", "crr_ctg_num >= prv_ctg_num");
380                             if (0 == strcmp(ctg, category.c_str())) {
381                                 HMI_DEBUG("wm:pm", "category of requested role is same");
382                                 if ((crr_ctg_num == prv_ctg_num) && (0 != prv_ctg_num)) {
383                                     HMI_DEBUG("wm:pm", "remove the oldest area data for adding requested role");
384                                     area_list.erase(area_list.begin());
385                                 }
386                             }
387                         }
388
389                         // Check
390                         for (pm::AreaState area_state : prv_layout_state.area_list) {
391                             HMI_DEBUG("wm:pm", "area_list name:%s category:%s role:%s",
392                                       area_state.name.c_str(),
393                                       area_state.category.c_str(),
394                                       area_state.role.c_str());
395                         }
396
397                         ctg_list[ctg] = area_list;
398                     }
399
400                     if (event == "activate") {
401                         // First, update area for requested role
402                         bool updated = false;
403                         for (pm::AreaState &as : crr_layout_state.area_list) {
404                             if ((as.category == category) && (as.name == area)) {
405                                 as.role = role;
406                                 updated = true;
407                                 break;
408                             }
409                         }
410
411                         // If NOT updated: there is not requested area in new layout, 
412                         // requested role is used later.
413                         if (!updated) {
414                             pm::AreaState area_state;
415                             area_state.name = area;
416                             area_state.category = category;
417                             area_state.role = role;
418                             ctg_list[category].push_back(area_state);
419                         }
420                     }
421
422                     // Update areas
423                     for (pm::AreaState &as : crr_layout_state.area_list) {
424
425                         // This conditional expression is useful in only activate
426                         if (as.role != role) {
427                             as.role = ctg_list[as.category].begin()->role;
428                             ctg_list[as.category].erase(ctg_list[as.category].begin());
429                         }
430                     }
431                 }
432             }
433             // Update current layout of this layer
434             pm::g_crr_layers[layer_name].layout_state = crr_layout_state;
435         }
436     }
437
438     // Check
439     for (auto itr : pm::g_crr_layers) {
440         pm::LayerState ls = itr.second;
441         HMI_DEBUG("wm:pm", ">>> LAYER:%s",ls.name.c_str());
442         HMI_DEBUG("wm:pm", ">>> >>> LAYOUT:%s", ls.layout_state.name.c_str());
443
444         for (pm::AreaState as : ls.layout_state.area_list) {
445             HMI_DEBUG("wm:pm", ">>> >>> >>> AREA:%s", as.name.c_str());
446             HMI_DEBUG("wm:pm", ">>> >>> >>> >>> CTG:%s", as.category.c_str());
447             HMI_DEBUG("wm:pm", ">>> >>> >>> >>> ROLE:%s", as.role.c_str());
448         }
449     }
450 #endif // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
451
452     json_object* json_out = json_object_new_object();
453
454     // Create result
455     // {
456     //     "parking_brake": {
457     //         "is_changed": <bool>,
458     //         "state": <const char*>
459     //     },
460     addStateToJson("parking_brake",
461                    crr_state.parking_brake.is_changed,
462                    stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state],
463                    &json_out);
464
465     //     "accel_pedal": {
466     //         "is_changed": <bool>,
467     //         "state": <const char*>
468     //     },
469     addStateToJson("accel_pedal",
470                    crr_state.accel_pedal.is_changed,
471                    stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state],
472                    &json_out);
473
474     //     "lightstatus_brake": {
475     //         "is_changed": <bool>,
476     //         "state": <const char*>
477     //     },
478     addStateToJson("lightstatus_brake",
479                    crr_state.lightstatus_brake.is_changed,
480                    stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state],
481                    &json_out);
482
483     //     "car": {
484     //         "is_changed": <bool>,
485     //         "state": <const char*>
486     //     },
487     addStateToJson("car",
488                    crr_state.car.is_changed,
489                    stm::gStmCarStateNo2Name[crr_state.car.state],
490                    &json_out);
491
492     //     "lamp": {
493     //         "is_changed": <bool>,
494     //         "state": <const char*>
495     //     },
496     addStateToJson("lamp",
497                    crr_state.lamp.is_changed,
498                    stm::gStmLampStateNo2Name[crr_state.lamp.state],
499                    &json_out);
500
501     //     "restriction_mode": {
502     //         "is_changed": <bool>,
503     //         "state": <const char*>
504     //     },
505     addStateToJson("restriction_mode",
506                    crr_state.restriction_mode.is_changed,
507                    stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
508                    &json_out);
509
510     //     "layers": [
511     json_object* json_layer = json_object_new_array();
512     json_object* json_tmp;
513
514     //         {
515     //             "homescreen": {
516     //                 "is_changed": <bool>,
517     //                 "state": <const char*>
518     //             }
519     //         },
520     //     ]
521     // }
522     json_tmp = json_object_new_object();
523     addStateToJson("homescreen",
524                    crr_state.layer[stm::gStmLayerNoHomescreen].is_changed,
525                    stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state],
526                    &json_tmp);
527     json_object_array_add(json_layer, json_tmp);
528
529     //         {
530     //             "apps": {
531     //                 "is_changed": <bool>,
532     //                 "state": <const char*>
533     //             }
534     //         },
535     json_tmp = json_object_new_object();
536     addStateToJson("apps",
537                    crr_state.layer[stm::gStmLayerNoApps].is_changed,
538                    stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoApps].state],
539                    &json_tmp);
540     json_object_array_add(json_layer, json_tmp);
541
542     //         {
543     //             "restriction": {
544     //                 "is_changed": <bool>,
545     //                 "state": <const char*>
546     //             }
547     //         },
548     json_tmp = json_object_new_object();
549     addStateToJson("restriction",
550                    crr_state.layer[stm::gStmLayerNoRestriction].is_changed,
551                    stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoRestriction].state],
552                    &json_tmp);
553     json_object_array_add(json_layer, json_tmp);
554
555     //         {
556     //             "on_screen": {
557     //                 "is_changed": <bool>,
558     //                 "state": <const char*>
559     //             }
560     //         },
561     json_tmp = json_object_new_object();
562     addStateToJson("on_screen",
563                    crr_state.layer[stm::gStmLayerNoOnScreen].is_changed,
564                    stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoOnScreen].state],
565                    &json_tmp);
566     json_object_array_add(json_layer, json_tmp);
567
568     // Add json array of layer
569     json_object_object_add(json_out, "layers", json_layer);
570
571     // Notify state is changed
572     if (nullptr != pm::callback.onStateTransitioned) {
573         pm::callback.onStateTransitioned(json_out);
574     }
575
576     if (crr_state.car.is_changed) {
577         if (stm::gStmCarStateNoRun == crr_state.car.state) {
578             // Set delay event(restriction mode on)
579             checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_ON, 3000, nullptr);
580         }
581         else if (stm::gStmCarStateNoStop == crr_state.car.state) {
582             // Set event(restriction mode off)
583             checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_OFF, 0, nullptr);
584
585             // Stop timer for restriction on event
586             if (pm::event_source_list.find(STM_EVT_NO_RESTRICTION_MODE_ON)
587               != pm::event_source_list.end()) {
588                 HMI_DEBUG("wm:pm", "Stop timer for restriction on");
589                 sd_event_source *event_source
590                     = pm::event_source_list[STM_EVT_NO_RESTRICTION_MODE_ON];
591                 int ret = sd_event_source_set_enabled(event_source, SD_EVENT_OFF);
592                 if (0 > ret) {
593                     HMI_ERROR("wm:pm", "Failed to stop timer");
594                 }
595             }
596         }
597     }
598
599     // Release json_object
600     json_object_put(json_out);
601
602     // Release data
603     delete (int*)data;
604
605     // Destroy sd_event_source object
606     sd_event_source_unref(source);
607
608     // Remove event source from list
609     if (pm::event_source_list.find(event_data) != pm::event_source_list.end()) {
610         pm::event_source_list.erase(event_data);
611     }
612
613     HMI_DEBUG("wm:pm", ">>>>>>>>>> FINISH CHECK POLICY");
614     return 0;
615 }
616
617 static int timerEvent(sd_event_source *source, uint64_t usec, void *data) {
618     int ret = checkPolicy(source, data);
619     return ret;
620 };
621
622 static int checkPolicyEntry(int event, uint64_t delay_ms, const char* role)
623 {
624     HMI_DEBUG("wm:pm", "Call");
625     HMI_DEBUG("wm:pm", "event:0x%x", event);
626
627     // Store event info
628     if (nullptr == role) {
629         pm::g_event_info_list[event] = std::string("");
630     }
631     else {
632         pm::g_event_info_list[event] = std::string(role);
633     }
634
635     if (0 == delay_ms) {
636         int ret = sd_event_add_defer(pm::event_loop, NULL,
637                                      &checkPolicy, new int(event));
638         if (0 > ret) {
639             HMI_ERROR("wm:pm", "Faild to sd_event_add_defer: errno:%d", ret);
640             pm::g_event_info_list.erase(event);
641             return -1;
642         }
643     }
644     else {
645         // Get current time
646         struct timespec time_spec;
647         clock_gettime(CLOCK_MONOTONIC, &time_spec);
648
649         // Calculate timer fired time
650         uint64_t usec = (time_spec.tv_sec * 1000000)
651             + (time_spec.tv_nsec / 1000)
652             + (delay_ms * 1000);
653
654         // Set timer
655         struct sd_event_source* event_source;
656         int ret = sd_event_add_time(pm::event_loop, &event_source, CLOCK_MONOTONIC, usec, 1,
657                                     &timerEvent, new int(event));
658         if (0 > ret) {
659             HMI_ERROR("wm:pm", "Faild to sd_event_add_time: errno:%d", ret);
660             pm::g_event_info_list.erase(event);
661             return -1;
662         }
663
664         // Store event source
665         pm::event_source_list[event] = event_source;
666     }
667
668     return 0;
669 }
670
671 void PolicyManager::registerCallback(CallbackTable callback) {
672     pm::callback.onStateTransitioned = callback.onStateTransitioned;
673     pm::callback.onError             = callback.onError;
674 }
675
676 int PolicyManager::inputEvent(json_object* json_in) {
677     HMI_DEBUG("wm:pm", "Call");
678
679     // Check arguments
680     if (nullptr == json_in) {
681         HMI_ERROR("wm:pm", "Argument is NULL!!");
682         return -1;
683     }
684
685     // Get event from json_object
686     const char* event = this->getStringFromJson(json_in, "event");
687     int event_no = 0;
688     if (nullptr != event) {
689         // Convert name to number
690         event_no = this->eventname2no_[event];
691         HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
692     }
693
694     // Get role from json_object
695     const char* role = this->getStringFromJson(json_in, "role");
696     int category_no = 0;
697     if (nullptr != role) {
698         HMI_DEBUG("wm:pm", "role(%s)", role);
699
700         // Convert role to category
701         const char* category = this->role2category_[role].c_str();
702         if (0 == strcmp("", category)) {
703             HMI_ERROR("wm:pm", "Error!!");
704             return -1;
705         }
706         HMI_DEBUG("wm:pm", "category(%s)", category);
707
708         // Convert name to number
709         category_no = categoryname2no_[category];
710         HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
711     }
712
713     // Get areat from json_object
714     const char* area = this->getStringFromJson(json_in, "area");
715     int area_no = 0;
716     if (nullptr != area) {
717         // Convert name to number
718         area_no = areaname2no_[area];
719         HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
720     }
721
722     // Check policy
723     checkPolicyEntry((event_no | category_no | area_no), 0, role);
724
725     return 0;
726 }
727
728 std::string PolicyManager::roleToCategory(const char* role) {
729     return this->role2category_[role];
730 }
731
732 extern const char* kDefaultRoleDb;
733 int PolicyManager::loadRoleDb() {
734     HMI_DEBUG("wm:pm", "Call");
735
736     std::string file_name;
737
738     // Get afm application installed dir
739     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
740     HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
741
742     if (!afm_app_install_dir) {
743         HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
744     }
745     else {
746         file_name = std::string(afm_app_install_dir) + std::string("/etc/role.db");
747     }
748
749     // Load role.db
750     json_object* json_obj;
751     int ret = this->inputJsonFilie(file_name.c_str(), &json_obj);
752     if (0 > ret) {
753         HMI_ERROR("wm:pm", "Could not open role.db, so use default role information");
754         json_obj = json_tokener_parse(kDefaultRoleDb);
755     }
756     HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
757
758     json_object* json_roles;
759     if (!json_object_object_get_ex(json_obj, "roles", &json_roles)) {
760         HMI_ERROR("wm:pm", "Parse Error!!");
761         return -1;
762     }
763
764     int len = json_object_array_length(json_roles);
765     HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
766     HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_roles));
767
768     json_object* json_tmp;
769     const char* category;
770     const char* roles;
771     const char* areas;
772     for (int i=0; i<len; i++) {
773         json_tmp = json_object_array_get_idx(json_roles, i);
774
775         category = this->getStringFromJson(json_tmp, "category");
776         roles =  this->getStringFromJson(json_tmp, "role");
777         areas =  this->getStringFromJson(json_tmp, "area");
778
779         if ((nullptr == category) || (nullptr == roles) || (nullptr == areas)) {
780             HMI_ERROR("wm:pm", "Parse Error!!");
781             return -1;
782         }
783
784         // Parse roles by '|'
785         std::vector<std::string> vct_roles;
786         vct_roles = this->parseString(std::string(roles), '|');
787
788         // Parse areas by '|'
789         std::vector<std::string> vct_areas;
790         vct_areas = this->parseString(std::string(areas), '|');
791
792         // Set role, category, default area
793         for (auto itr = vct_roles.begin(); itr != vct_roles.end(); ++itr) {
794             // Delete space from role and area name
795             std::string role = this->deleteSpace(*itr);
796             std::string area = this->deleteSpace(vct_areas[0]);
797
798             this->role2category_[role] = std::string(category);
799             this->role2defaultarea_[role] = area;
800         }
801
802         this->category2role_[std::string(category)] = std::string(roles);
803     }
804
805     // Check
806     HMI_DEBUG("wm:pm", "Check role2category_");
807     for (auto& x:this->role2category_){
808         HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
809     }
810
811     HMI_DEBUG("wm:pm", "Check role2defaultarea_");
812     for (auto& x:this->role2defaultarea_){
813         HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
814     }
815
816     HMI_DEBUG("wm:pm", "Check category2role_");
817     for (auto& x:this->category2role_){
818         HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
819     }
820
821     return 0;
822 }
823
824 extern const char* kDefaultLayoutDb;
825 int PolicyManager::loadLayoutDb() {
826     HMI_DEBUG("wm:lm", "Call");
827
828     // Get afm application installed dir
829     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
830     HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
831
832     std::string file_name;
833     if (!afm_app_install_dir) {
834         HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
835     }
836     else {
837         file_name = std::string(afm_app_install_dir) + std::string("/etc/layout.db");
838     }
839
840     // Load layout.db
841     json_object* json_obj;
842     int ret = this->inputJsonFilie(file_name.c_str(), &json_obj);
843     if (0 > ret) {
844         HMI_DEBUG("wm:pm", "Could not open layout.db, so use default layout information");
845         json_obj = json_tokener_parse(kDefaultLayoutDb);
846     }
847     HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
848
849     // Perse layouts
850     HMI_DEBUG("wm:pm", "Perse layouts");
851     json_object* json_cfg;
852     if (!json_object_object_get_ex(json_obj, "layouts", &json_cfg)) {
853         HMI_ERROR("wm:pm", "Parse Error!!");
854         return -1;
855     }
856
857     int len = json_object_array_length(json_cfg);
858     HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
859     HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_cfg));
860
861     const char* layout;
862     const char* role;
863     const char* category;
864     for (int i=0; i<len; i++) {
865         json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
866
867         layout = this->getStringFromJson(json_tmp, "name");
868         if (nullptr == layout) {
869             HMI_ERROR("wm:pm", "Parse Error!!");
870             return -1;
871         }
872         HMI_DEBUG("wm:pm", "> layout:%s", layout);
873
874         json_object* json_area_array;
875         if (!json_object_object_get_ex(json_tmp, "areas", &json_area_array)) {
876           HMI_ERROR("wm:pm", "Parse Error!!");
877           return -1;
878         }
879
880         int len_area = json_object_array_length(json_area_array);
881         HMI_DEBUG("wm:pm", "json_area_array len:%d", len_area);
882         HMI_DEBUG("wm:pm", "json_area_array dump:%s", json_object_get_string(json_area_array));
883
884         pm::LayoutState layout_state;
885         pm::AreaState area_state;
886         std::map<std::string, int> category_num;
887         for (int ctg_no = stm::gStmCategoryNoMin;
888              ctg_no <= stm::gStmCategoryNoMax; ctg_no++) {
889             const char* ctg_name = stm::gStmCategoryName[ctg_no];
890             category_num[ctg_name] = 0;
891         }
892
893         for (int j=0; j<len_area; j++) {
894             json_object* json_area = json_object_array_get_idx(json_area_array, j);
895
896             // Get area name
897             const char* area = this->getStringFromJson(json_area, "name");
898             if (nullptr == area) {
899               HMI_ERROR("wm:pm", "Parse Error!!");
900               return -1;
901             }
902             area_state.name = std::string(area);
903             HMI_DEBUG("wm:pm", ">> area:%s", area);
904
905             // Get app attribute of the area
906             category = this->getStringFromJson(json_area, "category");
907             if (nullptr == category) {
908                 HMI_ERROR("wm:pm", "Parse Error!!");
909                 return -1;
910             }
911             area_state.category = std::string(category);
912             category_num[category]++;
913             HMI_DEBUG("wm:pm", ">>> category:%s", category);
914
915             role = this->getStringFromJson(json_area, "role");
916             if (nullptr != role) {
917                 // Role is NOT essential here
918                 area_state.role = std::string(role);
919                 HMI_DEBUG("wm:pm", ">>> role:%s", role);
920             }
921
922             layout_state.area_list.push_back(area_state);
923
924         }
925
926         layout_state.name = layout;
927         layout_state.category_num = category_num;
928         pm::g_default_layouts[layout] = layout_state;
929     }
930
931     // Check
932     for(auto itr_layout = pm::g_default_layouts.begin();
933       itr_layout != pm::g_default_layouts.end(); ++itr_layout) {
934         HMI_DEBUG("wm:pm", ">>> layout:%s", itr_layout->first.c_str());
935
936         for (auto itr_area = itr_layout->second.area_list.begin();
937           itr_area != itr_layout->second.area_list.end(); ++itr_area) {
938             HMI_DEBUG("wm:pm", ">>> >>> area    :%s", itr_area->name.c_str());
939             HMI_DEBUG("wm:pm", ">>> >>> category:%s", itr_area->category.c_str());
940             HMI_DEBUG("wm:pm", ">>> >>> role    :%s", itr_area->role.c_str());
941 #if 0
942             for (auto itr_role = itr_area->second.begin();
943               itr_role != itr_area->second.end(); ++itr_role) {
944                 HMI_DEBUG("wm:pm", ">>> >>> >>> attribute:%s, name:%s",
945                           itr_role->first.c_str(), itr_role->second.c_str());
946             }
947 #endif
948         }
949     }
950
951     // Release json_object
952     json_object_put(json_obj);
953
954     return 0;
955 }
956
957 // TODO:
958 // This function will be removed because json_helper has same function.
959 // json_helper should be library.
960 const char* PolicyManager::getStringFromJson(json_object* obj, const char* key) {
961     if ((nullptr == obj) || (nullptr == key)) {
962         HMI_ERROR("wm:pm", "Argument is nullptr!!!");
963         return nullptr;
964     }
965
966     json_object* tmp;
967     if (!json_object_object_get_ex(obj, key, &tmp)) {
968         HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
969         return nullptr;
970     }
971
972     return json_object_get_string(tmp);
973 }
974
975 // TODO:
976 // This function will be removed because json_helper has same function.
977 // json_helper should be library.
978 int PolicyManager::inputJsonFilie(const char* file, json_object** obj) {
979     const int input_size = 128;
980     int ret = -1;
981
982     if ((nullptr == file) || (nullptr == obj)) {
983         HMI_ERROR("wm:jh", "Argument is nullptr!!!");
984         return ret;
985     }
986
987     HMI_DEBUG("wm:jh", "Input file: %s", file);
988
989     // Open json file
990     FILE *fp = fopen(file, "rb");
991     if (nullptr == fp) {
992         HMI_ERROR("wm:jh", "Could not open file");
993         return ret;
994     }
995
996     // Parse file data
997     struct json_tokener *tokener = json_tokener_new();
998     enum json_tokener_error json_error;
999     char buffer[input_size];
1000     int block_cnt = 1;
1001     while (1) {
1002         size_t len = fread(buffer, sizeof(char), input_size, fp);
1003         *obj = json_tokener_parse_ex(tokener, buffer, len);
1004         if (nullptr != *obj) {
1005             HMI_DEBUG("wm:jh", "File input is success");
1006             ret = 0;
1007             break;
1008         }
1009
1010         json_error = json_tokener_get_error(tokener);
1011         if ((json_tokener_continue != json_error)
1012             || (input_size > len)) {
1013             HMI_ERROR("wm:jh", "Failed to parse file (byte:%d err:%s)",
1014                       (input_size * block_cnt), json_tokener_error_desc(json_error));
1015             HMI_ERROR("wm:jh", "\n%s", buffer);
1016             *obj = nullptr;
1017             break;
1018         }
1019         block_cnt++;
1020     }
1021
1022     // Close json file
1023     fclose(fp);
1024
1025     // Free json_tokener
1026     json_tokener_free(tokener);
1027
1028     return ret;
1029 }
1030
1031 std::vector<std::string> PolicyManager::parseString(std::string str, char delimiter) {
1032     // Parse string by delimiter
1033     std::vector<std::string> vct;
1034     std::stringstream ss{str};
1035     std::string buf;
1036     while (std::getline(ss, buf, delimiter)) {
1037       if (!buf.empty()) {
1038         vct.push_back(buf);
1039       }
1040     }
1041     return vct;
1042 }
1043
1044 std::string PolicyManager::deleteSpace(std::string str) {
1045     std::string ret = str;
1046     size_t pos;
1047     while ((pos = ret.find_first_of(" ")) != std::string::npos) {
1048       ret.erase(pos, 1);
1049     }
1050     return ret;
1051 }
1052
1053 const char* kDefaultRoleDb = "{ \
1054     \"roles\":[ \
1055     { \
1056         \"category\": \"homescreen\", \
1057         \"role\": \"homescreen\", \
1058         \"area\": \"full\", \
1059     }, \
1060     { \
1061         \"category\": \"map\", \
1062         \"role\": \"map\", \
1063         \"area\": \"full | normal | split.main\", \
1064     }, \
1065     { \
1066         \"category\": \"general\", \
1067         \"role\": \"poi | music | video | browser | sdl | settings | mixer | radio | hvac | dashboard | debug\", \
1068         \"area\": \"normal\", \
1069     }, \
1070     { \
1071         \"category\": \"phone\", \
1072         \"role\": \"phone\", \
1073         \"area\": \"normal\", \
1074     }, \
1075     { \
1076         \"category\": \"splitable\", \
1077         \"role\": \"splitable1 | splitable2\", \
1078         \"area\": \"normal | split.main | split.sub\", \
1079     }, \
1080     { \
1081         \"category\": \"popup\", \
1082         \"role\": \"popup\", \
1083         \"area\": \"on_screen\", \
1084     }, \
1085     { \
1086         \"category\": \"system_alert\", \
1087         \"role\": \"system_alert\", \
1088         \"area\": \"on_screen\", \
1089     }, \
1090     { \
1091         \"category\": \"tbt\", \
1092         \"role\": \"tbt\", \
1093         \"area\": \"hud\", \
1094     } \
1095     ] \
1096 }";
1097
1098
1099 const char* kDefaultLayoutDb = "{ \
1100     \"layouts\": [ \
1101         { \
1102             \"name\": \"pu\", \
1103             \"layer\": \"on_screen\", \
1104             \"areas\": [ \
1105                 { \
1106                     \"name\": \"pop_up\", \
1107                     \"role\": \"incomming_call\" \
1108                 } \
1109             ] \
1110         }, \
1111         { \
1112             \"name\": \"sa\", \
1113             \"layer\": \"on_screen\", \
1114             \"areas\": [ \
1115                 { \
1116                     \"name\": \"system_alert\", \
1117                     \"role\": \"system_alert\" \
1118                 } \
1119             ] \
1120         }, \
1121         { \
1122             \"name\": \"m1\", \
1123             \"layer\": \"apps\", \
1124             \"areas\": [ \
1125                 { \
1126                     \"name\": \"normal\", \
1127                     \"role\": \"map\" \
1128                 } \
1129             ] \
1130         }, \
1131         { \
1132             \"name\": \"m2\", \
1133             \"layer\": \"apps\", \
1134             \"areas\": [ \
1135                 { \
1136                     \"name\": \"split.main\", \
1137                     \"role\": \"map\" \
1138                 }, \
1139                 { \
1140                     \"name\": \"split.sub\", \
1141                     \"category\": \"hvac\" \
1142                 } \
1143             ] \
1144         }, \
1145         { \
1146             \"name\": \"mf\", \
1147             \"layer\": \"apps\", \
1148             \"areas\": [ \
1149                 { \
1150                     \"name\": \"full\", \
1151                     \"role\": \"map\" \
1152                 } \
1153             ] \
1154         }, \
1155         { \
1156             \"name\": \"s1\", \
1157             \"layer\": \"apps\", \
1158             \"areas\": [ \
1159                 { \
1160                     \"name\": \"normal\", \
1161                     \"category\": \"splitable\" \
1162                 } \
1163             ] \
1164         }, \
1165         { \
1166             \"name\": \"s2\", \
1167             \"layer\": \"apps\", \
1168             \"areas\": [ \
1169                 { \
1170                     \"name\": \"split.main\", \
1171                     \"category\": \"splitable\" \
1172                 }, \
1173                 { \
1174                     \"name\": \"split.sub\", \
1175                     \"category\": \"splitable\" \
1176                 } \
1177             ] \
1178         }, \
1179         { \
1180             \"name\": \"g\", \
1181             \"layer\": \"apps\", \
1182             \"areas\": [ \
1183                 { \
1184                     \"name\": \"normal\", \
1185                     \"category\": \"general\" \
1186                 } \
1187             ] \
1188         }, \
1189         { \
1190             \"name\": \"hs\", \
1191             \"layer\": \"homescreen\", \
1192             \"areas\": [ \
1193                 { \
1194                     \"name\": \"full\", \
1195                     \"role\": \"homescreen\" \
1196                 } \
1197             ] \
1198         } \
1199     ], \
1200     \"areas\": [ \
1201         { \
1202             \"name\": \"normal\", \
1203             \"rect\": { \
1204                 \"x\": 0, \
1205                 \"y\": 218, \
1206                 \"w\": 1080, \
1207                 \"h\": 1488 \
1208             } \
1209         }, \
1210         { \
1211             \"name\": \"split.main\", \
1212             \"rect\": { \
1213                 \"x\": 0, \
1214                 \"y\": 218, \
1215                 \"w\": 1080, \
1216                 \"h\": 744 \
1217             } \
1218         }, \
1219         { \
1220             \"name\": \"split.sub\", \
1221             \"rect\": { \
1222                 \"x\": 0, \
1223                 \"y\": 962, \
1224                 \"w\": 1080, \
1225                 \"h\": 744 \
1226             } \
1227         }, \
1228         { \
1229             \"name\": \"full\", \
1230             \"rect\": { \
1231                 \"x\": 0, \
1232                 \"y\": 0, \
1233                 \"w\": 1080, \
1234                 \"h\": 1920 \
1235             } \
1236         }, \
1237         { \
1238             \"name\": \"pop_up\", \
1239             \"rect\": { \
1240                 \"x\": 0, \
1241                 \"y\": 640, \
1242                 \"w\": 1080, \
1243                 \"h\": 640 \
1244             } \
1245         }, \
1246         { \
1247             \"name\": \"system_alert\", \
1248             \"rect\": { \
1249                 \"x\": 0, \
1250                 \"y\": 640, \
1251                 \"w\": 1080, \
1252                 \"h\": 640 \
1253             } \
1254         } \
1255     ] \
1256 }";