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