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 "dummy_stm.h"
24 #include "hmi-debug.h"
29 static const char* kEventName[] = {
39 static const int kEventNo[] = {
41 STM_EVT_NO_DEACTIVATE,
44 STM_EVT_NO_TIMER_EXPIRED,
49 static const char* kCategoryName[] = {
58 static const int kCategoryNo[] = {
59 STM_CTG_NO_HOMESCREEN,
64 STM_CTG_NO_SYSTEM_ALERT
67 static const char* kAreaName[] = {
75 static const int kAreaNo[] = {
78 STM_ARA_NO_SPLIT_MAIN,
84 const char* gStmCarStateNo2Name[] = {
89 const char* gStmLampStateNo2Name[] = {
94 const char* gStmLayoutNo2Name[] = {
109 PolicyManager::PolicyManager() :
118 HMI_DEBUG("wm:pm", "Call");
121 int PolicyManager::initialize() {
122 HMI_DEBUG("wm:pm", "Call");
126 // Create convert map
127 for (unsigned int i=0; i<(sizeof(kEventNo)/sizeof(int)); i++) {
128 HMI_DEBUG("wm:pm", "event name:%s no:%d", kEventName[i], kEventNo[i]);
129 this->eventname2no_[kEventName[i]] = kEventNo[i];
132 for (unsigned int i=0; i<(sizeof(kCategoryNo)/sizeof(int)); i++) {
133 HMI_DEBUG("wm:pm", "category name:%s no:%d", kCategoryName[i], kCategoryNo[i]);
134 this->categoryname2no_[kCategoryName[i]] = kCategoryNo[i];
137 for (unsigned int i=0; i<(sizeof(kAreaNo)/sizeof(int)); i++) {
138 HMI_DEBUG("wm:pm", "area name:%s no:%d", kAreaName[i], kAreaNo[i]);
139 this->areaname2no_[kAreaName[i]] = kAreaNo[i];
145 HMI_ERROR("wm:pm", "Load role.db Error!!");
150 // Initialize StateTransitioner
156 int PolicyManager::checkPolicy(json_object* json_in, json_object** json_out) {
157 HMI_DEBUG("wm:pm", "Call");
160 if ((nullptr == json_in) || (nullptr == json_out)) {
161 HMI_ERROR("wm:pm", "Argument is NULL!!");
165 // Get event from json_object
166 const char* event = getStringFromJson(json_in, "event");
168 if (nullptr != event) {
169 // Convert name to number
170 event_no = this->eventname2no_[event];
171 HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
174 // Get role from json_object
175 const char* role = getStringFromJson(json_in, "role");
177 if (nullptr != role) {
178 HMI_DEBUG("wm:pm", "role(%s)", role);
180 // Convert role to category
181 const char* category = this->role2category_[role].c_str();
182 if (0 == strcmp("", category)) {
183 HMI_ERROR("wm:pm", "Error!!");
186 HMI_DEBUG("wm:pm", "category(%s)", category);
188 // Convert name to number
189 category_no = categoryname2no_[category];
190 HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
193 // Get areat from json_object
194 const char* area = getStringFromJson(json_in, "area");
196 if (nullptr != area) {
197 // Convert name to number
198 area_no = areaname2no_[area];
199 HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
203 HMI_DEBUG("wm:pm", "set event:0x%x", (event_no | category_no | area_no));
204 int ret = stmTransitionState((event_no | category_no | area_no),
205 &(this->current_state_));
207 HMI_ERROR("wm:pm", "Error!!");
214 // "is_changed": <bool>,
215 // "state": <const char*>
217 HMI_DEBUG("wm", "@@@@@ car state (is_changed:%d state:%d:%s)",
218 this->current_state_.car.is_changed,
219 this->current_state_.car.state,
220 gStmCarStateNo2Name[this->current_state_.car.state]);
221 this->addStateToJson("car",
222 this->current_state_.car.is_changed,
223 gStmCarStateNo2Name[this->current_state_.car.state],
227 // "is_changed": <bool>,
228 // "state": <const char*>
230 HMI_DEBUG("wm", "@@@@@ lamp state (is_changed:%d state:%d:%s)",
231 this->current_state_.lamp.is_changed,
232 this->current_state_.lamp.state,
233 gStmLampStateNo2Name[this->current_state_.lamp.state]);
234 this->addStateToJson("lamp",
235 this->current_state_.lamp.is_changed,
236 gStmLampStateNo2Name[this->current_state_.lamp.state],
242 // "is_changed": <bool>,
243 // "state": <const char*>
246 json_object* json_layer = json_object_new_array();
247 json_object* json_tmp = json_object_new_object();
248 this->addStateToJson("on_screen",
249 this->current_state_.layer.on_screen.is_changed,
250 gStmLayoutNo2Name[this->current_state_.layer.on_screen.state],
252 json_object_array_add(json_layer, json_tmp);
256 // "is_changed": <bool>,
257 // "state": <const char*>
260 json_tmp = json_object_new_object();
261 this->addStateToJson("apps",
262 this->current_state_.layer.apps.is_changed,
263 gStmLayoutNo2Name[this->current_state_.layer.apps.state],
265 json_object_array_add(json_layer, json_tmp);
269 // "is_changed": <bool>,
270 // "state": <const char*>
275 json_tmp = json_object_new_object();
276 this->addStateToJson("homescreen",
277 this->current_state_.layer.homescreen.is_changed,
278 gStmLayoutNo2Name[this->current_state_.layer.homescreen.state],
280 json_object_array_add(json_layer, json_tmp);
282 // Add json array of layer
283 json_object_object_add(*json_out, "layers", json_layer);
285 HMI_DEBUG("wm:pm", "json_out.dump:%s", json_object_get_string(*json_out));
290 std::string PolicyManager::roleToCategory(const char* role) {
291 return this->role2category_[role];
294 extern const char* kDefaultRoleDb;
295 int PolicyManager::loadRoleDb() {
296 HMI_DEBUG("wm:pm", "Call");
298 std::string file_name;
300 // Get afm application installed dir
301 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
302 HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
304 if (!afm_app_install_dir) {
305 HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
308 file_name = std::string(afm_app_install_dir) + std::string("/etc/role.db");
312 HMI_DEBUG("wm:pm", "file_name:%s", file_name.c_str());
313 json_object* json_obj = json_object_from_file(file_name.c_str());
314 if (nullptr == json_obj) {
315 HMI_ERROR("wm:pm", "Could not open role.db, so use default role information");
316 json_obj = json_tokener_parse(kDefaultRoleDb);
318 HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
320 json_object* json_roles;
321 if (!json_object_object_get_ex(json_obj, "roles", &json_roles)) {
322 HMI_ERROR("wm:pm", "Parse Error!!");
326 int len = json_object_array_length(json_roles);
327 HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
328 HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_roles));
330 json_object* json_tmp;
331 const char* category;
334 for (int i=0; i<len; i++) {
335 json_tmp = json_object_array_get_idx(json_roles, i);
337 category = this->getStringFromJson(json_tmp, "category");
338 roles = this->getStringFromJson(json_tmp, "role");
339 areas = this->getStringFromJson(json_tmp, "area");
341 if ((nullptr == category) || (nullptr == roles) || (nullptr == areas)) {
342 HMI_ERROR("wm:pm", "Parse Error!!");
346 // Parse roles by '|'
347 std::vector<std::string> vct_roles;
348 vct_roles = this->parseString(std::string(roles), '|');
350 // Parse areas by '|'
351 std::vector<std::string> vct_areas;
352 vct_areas = this->parseString(std::string(areas), '|');
354 // Set role, category, default area
355 for (auto itr = vct_roles.begin(); itr != vct_roles.end(); ++itr) {
356 // Delete space from role and area name
357 std::string role = this->deleteSpace(*itr);
358 std::string area = this->deleteSpace(vct_areas[0]);
360 this->role2category_[role] = std::string(category);
361 this->role2defaultarea_[role] = area;
364 this->category2role_[std::string(category)] = std::string(roles);
368 HMI_DEBUG("wm:pm", "Check role2category_");
369 for (auto& x:this->role2category_){
370 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
373 HMI_DEBUG("wm:pm", "Check role2defaultarea_");
374 for (auto& x:this->role2defaultarea_){
375 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
378 HMI_DEBUG("wm:pm", "Check category2role_");
379 for (auto& x:this->category2role_){
380 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
386 const char* PolicyManager::getStringFromJson(json_object* obj, const char* key) {
387 if ((nullptr == obj) || (nullptr == key)) {
388 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
393 if (!json_object_object_get_ex(obj, key, &tmp)) {
394 HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
398 return json_object_get_string(tmp);
401 int PolicyManager::getIntFromJson(json_object* obj, const char* key) {
402 if ((nullptr == obj) || (nullptr == key)) {
403 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
408 if (!json_object_object_get_ex(obj, key, &tmp)) {
409 HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
413 return json_object_get_int(tmp);
416 void PolicyManager::addStateToJson(
417 const char* key, int is_changed, const char* state, json_object** json_out) {
418 if ((nullptr == key) || (nullptr == state) || (nullptr == json_out)) {
419 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
423 json_object* json_obj = json_object_new_object();
424 json_object_object_add(json_obj, "is_changed", json_object_new_boolean(is_changed));
426 HMI_DEBUG("wm:pm", "%s: state changed (%s)", key, state);
427 json_object_object_add(json_obj, "state", json_object_new_string(state));
429 json_object_object_add(*json_out, key, json_obj);
432 std::vector<std::string> PolicyManager::parseString(std::string str, char delimiter) {
433 // Parse string by delimiter
434 std::vector<std::string> vct;
435 std::stringstream ss{str};
437 while (std::getline(ss, buf, delimiter)) {
445 std::string PolicyManager::deleteSpace(std::string str) {
446 std::string ret = str;
448 while ((pos = ret.find_first_of(" ")) != std::string::npos) {
454 const char* kDefaultRoleDb = "{ \
457 \"category\": \"homescreen\", \
458 \"role\": \"homescreen\", \
459 \"area\": \"full\", \
462 \"category\": \"map\", \
464 \"area\": \"full | normal | split.main\", \
467 \"category\": \"general\", \
468 \"role\": \"poi | music | video | browser | sdl | settings | mixer | radio | hvac | dashboard | debug\", \
469 \"area\": \"normal\", \
472 \"category\": \"phone\", \
473 \"role\": \"phone\", \
474 \"area\": \"normal\", \
477 \"category\": \"splitable\", \
478 \"role\": \"splitable1 | splitable2\", \
479 \"area\": \"normal | split.main | split.sub\", \
482 \"category\": \"popup\", \
483 \"role\": \"popup\", \
484 \"area\": \"on_screen\", \
487 \"category\": \"system_alert\", \
488 \"role\": \"system_alert\", \
489 \"area\": \"on_screen\", \
492 \"category\": \"tbt\", \