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