2 * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <json-c/json.h>
22 #include "policy_manager.hpp"
23 #include "hmi-debug.h"
27 #include "dummy_stm.h"
32 PolicyManager::PolicyManager() :
40 HMI_DEBUG("wm:pm", "Call");
43 int PolicyManager::initialize() {
44 HMI_DEBUG("wm:pm", "Call");
49 for (unsigned int i=0; i<STM_NUM_EVT; i++) {
50 HMI_DEBUG("wm:pm", "event name:%s no:%d", stm::gStmEventName[i], stm::gStmEventNo[i]);
51 this->eventname2no_[stm::gStmEventName[i]] = stm::gStmEventNo[i];
54 for (unsigned int i=0; i<STM_NUM_CTG; i++) {
55 HMI_DEBUG("wm:pm", "category name:%s no:%d", stm::gStmCategoryName[i], stm::gStmCategoryNo[i]);
56 this->categoryname2no_[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
59 for (unsigned int i=0; i<STM_NUM_ARA; i++) {
60 HMI_DEBUG("wm:pm", "area name:%s no:%d", stm::gStmAreaName[i], stm::gStmAreaNo[i]);
61 this->areaname2no_[stm::gStmAreaName[i]] = stm::gStmAreaNo[i];
67 HMI_ERROR("wm:pm", "Load role.db Error!!");
71 // Initialize StateTransitioner
77 int PolicyManager::checkPolicy(json_object* json_in, json_object** json_out) {
78 HMI_DEBUG("wm:pm", "Call");
81 if ((nullptr == json_in) || (nullptr == json_out)) {
82 HMI_ERROR("wm:pm", "Argument is NULL!!");
86 // Get event from json_object
87 const char* event = this->getStringFromJson(json_in, "event");
89 if (nullptr != event) {
90 // Convert name to number
91 event_no = this->eventname2no_[event];
92 HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
95 // Get role from json_object
96 const char* role = this->getStringFromJson(json_in, "role");
98 if (nullptr != role) {
99 HMI_DEBUG("wm:pm", "role(%s)", role);
101 // Convert role to category
102 const char* category = this->role2category_[role].c_str();
103 if (0 == strcmp("", category)) {
104 HMI_ERROR("wm:pm", "Error!!");
107 HMI_DEBUG("wm:pm", "category(%s)", category);
109 // Convert name to number
110 category_no = categoryname2no_[category];
111 HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
114 // Get areat from json_object
115 const char* area = this->getStringFromJson(json_in, "area");
117 if (nullptr != area) {
118 // Convert name to number
119 area_no = areaname2no_[area];
120 HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
123 HMI_DEBUG("wm:pm", "set event:0x%x", (event_no | category_no | area_no));
126 stm::stm_state_t crr_state;
127 int ret = stm::stmTransitionState((event_no | category_no | area_no), &crr_state);
129 HMI_ERROR("wm:pm", "Error!!");
135 // "parking_brake": {
136 // "is_changed": <bool>,
137 // "state": <const char*>
139 HMI_DEBUG("wm", "parking brake state (is_changed:%d state:%d:%s)",
140 crr_state.parking_brake.is_changed,
141 crr_state.parking_brake.state,
142 stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state]);
143 this->addStateToJson("parking_brake",
144 crr_state.parking_brake.is_changed,
145 stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state],
149 // "is_changed": <bool>,
150 // "state": <const char*>
152 HMI_DEBUG("wm", "accelerator pedal state (is_changed:%d state:%d:%s)",
153 crr_state.accel_pedal.is_changed,
154 crr_state.accel_pedal.state,
155 stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state]);
156 this->addStateToJson("accel_pedal",
157 crr_state.accel_pedal.is_changed,
158 stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state],
162 // "is_changed": <bool>,
163 // "state": <const char*>
165 HMI_DEBUG("wm", "car state (is_changed:%d state:%d:%s)",
166 crr_state.car.is_changed,
168 stm::gStmCarStateNo2Name[crr_state.car.state]);
169 this->addStateToJson("car",
170 crr_state.car.is_changed,
171 stm::gStmCarStateNo2Name[crr_state.car.state],
175 // "is_changed": <bool>,
176 // "state": <const char*>
178 HMI_DEBUG("wm", "lamp state (is_changed:%d state:%d:%s)",
179 crr_state.lamp.is_changed,
180 crr_state.lamp.state,
181 stm::gStmLampStateNo2Name[crr_state.lamp.state]);
182 this->addStateToJson("lamp",
183 crr_state.lamp.is_changed,
184 stm::gStmLampStateNo2Name[crr_state.lamp.state],
188 json_object* json_layer = json_object_new_array();
189 json_object* json_tmp;
193 // "is_changed": <bool>,
194 // "state": <const char*>
199 HMI_DEBUG("wm", "homescreen state (is_changed:%d state:%d:%s)",
200 crr_state.layer.homescreen.is_changed,
201 crr_state.layer.homescreen.state,
202 stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state]);
203 json_tmp = json_object_new_object();
204 this->addStateToJson("homescreen",
205 crr_state.layer.homescreen.is_changed,
206 stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state],
208 json_object_array_add(json_layer, json_tmp);
212 // "is_changed": <bool>,
213 // "state": <const char*>
216 HMI_DEBUG("wm", "apps state (is_changed:%d state:%d:%s)",
217 crr_state.layer.apps.is_changed,
218 crr_state.layer.apps.state,
219 stm::gStmLayoutNo2Name[crr_state.layer.apps.state]);
220 json_tmp = json_object_new_object();
221 this->addStateToJson("apps",
222 crr_state.layer.apps.is_changed,
223 stm::gStmLayoutNo2Name[crr_state.layer.apps.state],
225 json_object_array_add(json_layer, json_tmp);
229 // "is_changed": <bool>,
230 // "state": <const char*>
233 HMI_DEBUG("wm", "restriction state (is_changed:%d state:%d:%s)",
234 crr_state.layer.restriction.is_changed,
235 crr_state.layer.restriction.state,
236 stm::gStmLayoutNo2Name[crr_state.layer.restriction.state]);
237 json_tmp = json_object_new_object();
238 this->addStateToJson("restriction",
239 crr_state.layer.restriction.is_changed,
240 stm::gStmLayoutNo2Name[crr_state.layer.restriction.state],
242 json_object_array_add(json_layer, json_tmp);
246 // "is_changed": <bool>,
247 // "state": <const char*>
250 HMI_DEBUG("wm", "on_screen state (is_changed:%d state:%d:%s)",
251 crr_state.layer.on_screen.is_changed,
252 crr_state.layer.on_screen.state,
253 stm::gStmLayoutNo2Name[crr_state.layer.on_screen.state]);
254 json_tmp = json_object_new_object();
255 this->addStateToJson("on_screen",
256 crr_state.layer.on_screen.is_changed,
257 stm::gStmLayoutNo2Name[crr_state.layer.on_screen.state],
259 json_object_array_add(json_layer, json_tmp);
261 // Add json array of layer
262 json_object_object_add(*json_out, "layers", json_layer);
267 std::string PolicyManager::roleToCategory(const char* role) {
268 return this->role2category_[role];
271 extern const char* kDefaultRoleDb;
272 int PolicyManager::loadRoleDb() {
273 HMI_DEBUG("wm:pm", "Call");
275 std::string file_name;
277 // Get afm application installed dir
278 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
279 HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
281 if (!afm_app_install_dir) {
282 HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
285 file_name = std::string(afm_app_install_dir) + std::string("/etc/role.db");
289 json_object* json_obj;
290 int ret = this->inputJsonFilie(file_name.c_str(), &json_obj);
292 HMI_ERROR("wm:pm", "Could not open role.db, so use default role information");
293 json_obj = json_tokener_parse(kDefaultRoleDb);
295 HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
297 json_object* json_roles;
298 if (!json_object_object_get_ex(json_obj, "roles", &json_roles)) {
299 HMI_ERROR("wm:pm", "Parse Error!!");
303 int len = json_object_array_length(json_roles);
304 HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
305 HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_roles));
307 json_object* json_tmp;
308 const char* category;
311 for (int i=0; i<len; i++) {
312 json_tmp = json_object_array_get_idx(json_roles, i);
314 category = this->getStringFromJson(json_tmp, "category");
315 roles = this->getStringFromJson(json_tmp, "role");
316 areas = this->getStringFromJson(json_tmp, "area");
318 if ((nullptr == category) || (nullptr == roles) || (nullptr == areas)) {
319 HMI_ERROR("wm:pm", "Parse Error!!");
323 // Parse roles by '|'
324 std::vector<std::string> vct_roles;
325 vct_roles = this->parseString(std::string(roles), '|');
327 // Parse areas by '|'
328 std::vector<std::string> vct_areas;
329 vct_areas = this->parseString(std::string(areas), '|');
331 // Set role, category, default area
332 for (auto itr = vct_roles.begin(); itr != vct_roles.end(); ++itr) {
333 // Delete space from role and area name
334 std::string role = this->deleteSpace(*itr);
335 std::string area = this->deleteSpace(vct_areas[0]);
337 this->role2category_[role] = std::string(category);
338 this->role2defaultarea_[role] = area;
341 this->category2role_[std::string(category)] = std::string(roles);
345 HMI_DEBUG("wm:pm", "Check role2category_");
346 for (auto& x:this->role2category_){
347 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
350 HMI_DEBUG("wm:pm", "Check role2defaultarea_");
351 for (auto& x:this->role2defaultarea_){
352 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
355 HMI_DEBUG("wm:pm", "Check category2role_");
356 for (auto& x:this->category2role_){
357 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
364 // This function will be removed because json_helper has same function.
365 // json_helper should be library.
366 const char* PolicyManager::getStringFromJson(json_object* obj, const char* key) {
367 if ((nullptr == obj) || (nullptr == key)) {
368 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
373 if (!json_object_object_get_ex(obj, key, &tmp)) {
374 HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
378 return json_object_get_string(tmp);
382 // This function will be removed because json_helper has same function.
383 // json_helper should be library.
384 int PolicyManager::inputJsonFilie(const char* file, json_object** obj) {
385 const int input_size = 128;
388 if ((nullptr == file) || (nullptr == obj)) {
389 HMI_ERROR("wm:jh", "Argument is nullptr!!!");
393 HMI_DEBUG("wm:jh", "Input file: %s", file);
396 FILE *fp = fopen(file, "rb");
398 HMI_ERROR("wm:jh", "Could not open file");
403 struct json_tokener *tokener = json_tokener_new();
404 enum json_tokener_error json_error;
405 char buffer[input_size];
408 size_t len = fread(buffer, sizeof(char), input_size, fp);
409 *obj = json_tokener_parse_ex(tokener, buffer, len);
410 if (nullptr != *obj) {
411 HMI_DEBUG("wm:jh", "File input is success");
416 json_error = json_tokener_get_error(tokener);
417 if ((json_tokener_continue != json_error)
418 || (input_size > len)) {
419 HMI_ERROR("wm:jh", "Failed to parse file (byte:%d err:%s)",
420 (input_size * block_cnt), json_tokener_error_desc(json_error));
421 HMI_ERROR("wm:jh", "\n%s", buffer);
432 json_tokener_free(tokener);
437 void PolicyManager::addStateToJson(
438 const char* key, int is_changed, const char* state, json_object** json_out) {
439 if ((nullptr == key) || (nullptr == state) || (nullptr == json_out)) {
440 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
444 json_object* json_obj = json_object_new_object();
445 json_object_object_add(json_obj, "is_changed", json_object_new_boolean(is_changed));
447 HMI_DEBUG("wm:pm", "%s: state changed (%s)", key, state);
448 json_object_object_add(json_obj, "state", json_object_new_string(state));
450 json_object_object_add(*json_out, key, json_obj);
453 std::vector<std::string> PolicyManager::parseString(std::string str, char delimiter) {
454 // Parse string by delimiter
455 std::vector<std::string> vct;
456 std::stringstream ss{str};
458 while (std::getline(ss, buf, delimiter)) {
466 std::string PolicyManager::deleteSpace(std::string str) {
467 std::string ret = str;
469 while ((pos = ret.find_first_of(" ")) != std::string::npos) {
475 const char* kDefaultRoleDb = "{ \
478 \"category\": \"homescreen\", \
479 \"role\": \"homescreen\", \
480 \"area\": \"full\", \
483 \"category\": \"map\", \
485 \"area\": \"full | normal | split.main\", \
488 \"category\": \"general\", \
489 \"role\": \"poi | music | video | browser | sdl | settings | mixer | radio | hvac | dashboard | debug\", \
490 \"area\": \"normal\", \
493 \"category\": \"phone\", \
494 \"role\": \"phone\", \
495 \"area\": \"normal\", \
498 \"category\": \"splitable\", \
499 \"role\": \"splitable1 | splitable2\", \
500 \"area\": \"normal | split.main | split.sub\", \
503 \"category\": \"popup\", \
504 \"role\": \"popup\", \
505 \"area\": \"on_screen\", \
508 \"category\": \"system_alert\", \
509 \"role\": \"system_alert\", \
510 \"area\": \"on_screen\", \
513 \"category\": \"tbt\", \