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