aboutsummaryrefslogtreecommitdiffstats
path: root/src/policy_manager/policy_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/policy_manager/policy_manager.cpp')
-rw-r--r--src/policy_manager/policy_manager.cpp497
1 files changed, 497 insertions, 0 deletions
diff --git a/src/policy_manager/policy_manager.cpp b/src/policy_manager/policy_manager.cpp
new file mode 100644
index 0000000..61d1d7c
--- /dev/null
+++ b/src/policy_manager/policy_manager.cpp
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <fstream>
+#include <sstream>
+#include <istream>
+#include <json-c/json.h>
+#include "policy_manager.hpp"
+#include "dummy_stm.h"
+#include "hmi-debug.h"
+
+
+namespace {
+
+static const char* kEventName[] = {
+ "activate",
+ "deactivate",
+ "car_stop",
+ "car_run",
+ "timer_expired",
+ "lamp_off",
+ "lamp_on"
+};
+
+static const int kEventNo[] = {
+ STM_EVT_NO_ACTIVATE,
+ STM_EVT_NO_DEACTIVATE,
+ STM_EVT_NO_CAR_STOP,
+ STM_EVT_NO_CAR_RUN,
+ STM_EVT_NO_TIMER_EXPIRED,
+ STM_EVT_NO_LAMP_OFF,
+ STM_EVT_NO_LAMP_ON
+};
+
+static const char* kCategoryName[] = {
+ "homescreen",
+ "map",
+ "general",
+ "splitable",
+ "popup",
+ "system_alert"
+};
+
+static const int kCategoryNo[] = {
+ STM_CTG_NO_HOMESCREEN,
+ STM_CTG_NO_MAP,
+ STM_CTG_NO_GENERAL,
+ STM_CTG_NO_SPLITABLE,
+ STM_CTG_NO_POPUP,
+ STM_CTG_NO_SYSTEM_ALERT
+};
+
+static const char* kAreaName[] = {
+ "full",
+ "normal",
+ "split.main",
+ "split.sub",
+ "onscreen"
+};
+
+static const int kAreaNo[] = {
+ STM_ARA_NO_FULL,
+ STM_ARA_NO_NORMAL,
+ STM_ARA_NO_SPLIT_MAIN,
+ STM_ARA_NO_SPLIT_SUB,
+ STM_ARA_NO_ON_SCREEN
+};
+
+// String for state
+const char* gStmCarStateNo2Name[] = {
+ "car_stop",
+ "car_run"
+};
+
+const char* gStmLampStateNo2Name[] = {
+ "lamp_off",
+ "lamp_on"
+};
+
+const char* gStmLayoutNo2Name[] = {
+ "none",
+ "pu",
+ "sa",
+ "m1",
+ "m2",
+ "mf",
+ "s1",
+ "s2",
+ "g",
+ "hs",
+};
+
+} // namespace
+
+PolicyManager::PolicyManager() :
+ eventname2no_(),
+ categoryname2no_(),
+ areaname2no_(),
+ role2category_(),
+ category2role_(),
+ role2defaultarea_(),
+ current_state_()
+{
+ HMI_DEBUG("wm:pm", "Call");
+}
+
+int PolicyManager::initialize() {
+ HMI_DEBUG("wm:pm", "Call");
+
+ int ret = 0;
+
+ // Create convert map
+ for (unsigned int i=0; i<(sizeof(kEventNo)/sizeof(int)); i++) {
+ HMI_DEBUG("wm:pm", "event name:%s no:%d", kEventName[i], kEventNo[i]);
+ this->eventname2no_[kEventName[i]] = kEventNo[i];
+ }
+
+ for (unsigned int i=0; i<(sizeof(kCategoryNo)/sizeof(int)); i++) {
+ HMI_DEBUG("wm:pm", "category name:%s no:%d", kCategoryName[i], kCategoryNo[i]);
+ this->categoryname2no_[kCategoryName[i]] = kCategoryNo[i];
+ }
+
+ for (unsigned int i=0; i<(sizeof(kAreaNo)/sizeof(int)); i++) {
+ HMI_DEBUG("wm:pm", "area name:%s no:%d", kAreaName[i], kAreaNo[i]);
+ this->areaname2no_[kAreaName[i]] = kAreaNo[i];
+ }
+
+ // Load role.db
+ ret = loadRoleDb();
+ if (0 > ret) {
+ HMI_ERROR("wm:pm", "Load role.db Error!!");
+ return ret;
+ }
+
+ // TODO:
+ // Initialize StateTransitioner
+ // stmInitialize();
+
+ return ret;
+}
+
+int PolicyManager::checkPolicy(json_object* json_in, json_object** json_out) {
+ HMI_DEBUG("wm:pm", "Call");
+
+ // Check arguments
+ if ((nullptr == json_in) || (nullptr == json_out)) {
+ HMI_ERROR("wm:pm", "Argument is NULL!!");
+ return -1;
+ }
+
+ // Get event from json_object
+ const char* event = getStringFromJson(json_in, "event");
+ int event_no = 0;
+ if (nullptr != event) {
+ // Convert name to number
+ event_no = this->eventname2no_[event];
+ HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
+ }
+
+ // Get role from json_object
+ const char* role = getStringFromJson(json_in, "role");
+ int category_no = 0;
+ if (nullptr != role) {
+ HMI_DEBUG("wm:pm", "role(%s)", role);
+
+ // Convert role to category
+ const char* category = this->role2category_[role].c_str();
+ if (0 == strcmp("", category)) {
+ HMI_ERROR("wm:pm", "Error!!");
+ return -1;
+ }
+ HMI_DEBUG("wm:pm", "category(%s)", category);
+
+ // Convert name to number
+ category_no = categoryname2no_[category];
+ HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
+ }
+
+ // Get areat from json_object
+ const char* area = getStringFromJson(json_in, "area");
+ int area_no = 0;
+ if (nullptr != area) {
+ // Convert name to number
+ area_no = areaname2no_[area];
+ HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
+ }
+
+ // Transition state
+ HMI_DEBUG("wm:pm", "set event:0x%x", (event_no | category_no | area_no));
+ int ret = stmTransitionState((event_no | category_no | area_no),
+ &(this->current_state_));
+ if (0 > ret) {
+ HMI_ERROR("wm:pm", "Error!!");
+ return -1;
+ }
+
+ // Create result
+ // {
+ // "car": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // },
+ HMI_DEBUG("wm", "@@@@@ car state (is_changed:%d state:%d:%s)",
+ this->current_state_.car.is_changed,
+ this->current_state_.car.state,
+ gStmCarStateNo2Name[this->current_state_.car.state]);
+ this->addStateToJson("car",
+ this->current_state_.car.is_changed,
+ gStmCarStateNo2Name[this->current_state_.car.state],
+ json_out);
+
+ // "lamp": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // },
+ HMI_DEBUG("wm", "@@@@@ lamp state (is_changed:%d state:%d:%s)",
+ this->current_state_.lamp.is_changed,
+ this->current_state_.lamp.state,
+ gStmLampStateNo2Name[this->current_state_.lamp.state]);
+ this->addStateToJson("lamp",
+ this->current_state_.lamp.is_changed,
+ gStmLampStateNo2Name[this->current_state_.lamp.state],
+ json_out);
+
+ // "layers": [
+ // {
+ // "on_screen": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // }
+ // },
+ json_object* json_layer = json_object_new_array();
+ json_object* json_tmp = json_object_new_object();
+ this->addStateToJson("on_screen",
+ this->current_state_.layer.on_screen.is_changed,
+ gStmLayoutNo2Name[this->current_state_.layer.on_screen.state],
+ &json_tmp);
+ json_object_array_add(json_layer, json_tmp);
+
+ // {
+ // "apps": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // }
+ // },
+ json_tmp = json_object_new_object();
+ this->addStateToJson("apps",
+ this->current_state_.layer.apps.is_changed,
+ gStmLayoutNo2Name[this->current_state_.layer.apps.state],
+ &json_tmp);
+ json_object_array_add(json_layer, json_tmp);
+
+ // {
+ // "homescreen": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // }
+ // },
+ // ]
+ // }
+ json_tmp = json_object_new_object();
+ this->addStateToJson("homescreen",
+ this->current_state_.layer.homescreen.is_changed,
+ gStmLayoutNo2Name[this->current_state_.layer.homescreen.state],
+ &json_tmp);
+ json_object_array_add(json_layer, json_tmp);
+
+ // Add json array of layer
+ json_object_object_add(*json_out, "layers", json_layer);
+
+ HMI_DEBUG("wm:pm", "json_out.dump:%s", json_object_get_string(*json_out));
+
+ return 0;
+}
+
+std::string PolicyManager::roleToCategory(const char* role) {
+ return this->role2category_[role];
+}
+
+extern const char* kDefaultRoleDb;
+int PolicyManager::loadRoleDb() {
+ HMI_DEBUG("wm:pm", "Call");
+
+ std::string file_name;
+
+ // Get afm application installed dir
+ char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
+ HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
+
+ if (!afm_app_install_dir) {
+ HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
+ }
+ else {
+ file_name = std::string(afm_app_install_dir) + std::string("/etc/role.db");
+ }
+
+ // Load role.db
+ HMI_DEBUG("wm:pm", "file_name:%s", file_name.c_str());
+ json_object* json_obj = json_object_from_file(file_name.c_str());
+ if (nullptr == json_obj) {
+ HMI_ERROR("wm:pm", "Could not open role.db, so use default role information");
+ json_obj = json_tokener_parse(kDefaultRoleDb);
+ }
+ HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
+
+ json_object* json_roles;
+ if (!json_object_object_get_ex(json_obj, "roles", &json_roles)) {
+ HMI_ERROR("wm:pm", "Parse Error!!");
+ return -1;
+ }
+
+ int len = json_object_array_length(json_roles);
+ HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
+ HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_roles));
+
+ json_object* json_tmp;
+ const char* category;
+ const char* roles;
+ const char* areas;
+ for (int i=0; i<len; i++) {
+ json_tmp = json_object_array_get_idx(json_roles, i);
+
+ category = this->getStringFromJson(json_tmp, "category");
+ roles = this->getStringFromJson(json_tmp, "role");
+ areas = this->getStringFromJson(json_tmp, "area");
+
+ if ((nullptr == category) || (nullptr == roles) || (nullptr == areas)) {
+ HMI_ERROR("wm:pm", "Parse Error!!");
+ return -1;
+ }
+
+ // Parse roles by '|'
+ std::vector<std::string> vct_roles;
+ vct_roles = this->parseString(std::string(roles), '|');
+
+ // Parse areas by '|'
+ std::vector<std::string> vct_areas;
+ vct_areas = this->parseString(std::string(areas), '|');
+
+ // Set role, category, default area
+ for (auto itr = vct_roles.begin(); itr != vct_roles.end(); ++itr) {
+ // Delete space from role and area name
+ std::string role = this->deleteSpace(*itr);
+ std::string area = this->deleteSpace(vct_areas[0]);
+
+ this->role2category_[role] = std::string(category);
+ this->role2defaultarea_[role] = area;
+ }
+
+ this->category2role_[std::string(category)] = std::string(roles);
+ }
+
+ // Check
+ HMI_DEBUG("wm:pm", "Check role2category_");
+ for (auto& x:this->role2category_){
+ HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
+ }
+
+ HMI_DEBUG("wm:pm", "Check role2defaultarea_");
+ for (auto& x:this->role2defaultarea_){
+ HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
+ }
+
+ HMI_DEBUG("wm:pm", "Check category2role_");
+ for (auto& x:this->category2role_){
+ HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
+ }
+
+ return 0;
+}
+
+const char* PolicyManager::getStringFromJson(json_object* obj, const char* key) {
+ if ((nullptr == obj) || (nullptr == key)) {
+ HMI_ERROR("wm:pm", "Argument is nullptr!!!");
+ return nullptr;
+ }
+
+ json_object* tmp;
+ if (!json_object_object_get_ex(obj, key, &tmp)) {
+ HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
+ return nullptr;
+ }
+
+ return json_object_get_string(tmp);
+}
+
+int PolicyManager::getIntFromJson(json_object* obj, const char* key) {
+ if ((nullptr == obj) || (nullptr == key)) {
+ HMI_ERROR("wm:pm", "Argument is nullptr!!!");
+ return 0;
+ }
+
+ json_object* tmp;
+ if (!json_object_object_get_ex(obj, key, &tmp)) {
+ HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
+ return 0;
+ }
+
+ return json_object_get_int(tmp);
+}
+
+void PolicyManager::addStateToJson(
+ const char* key, int is_changed, const char* state, json_object** json_out) {
+ if ((nullptr == key) || (nullptr == state) || (nullptr == json_out)) {
+ HMI_ERROR("wm:pm", "Argument is nullptr!!!");
+ return;
+ }
+
+ json_object* json_obj = json_object_new_object();
+ json_object_object_add(json_obj, "is_changed", json_object_new_boolean(is_changed));
+ if (is_changed) {
+ HMI_DEBUG("wm:pm", "%s: state changed (%s)", key, state);
+ json_object_object_add(json_obj, "state", json_object_new_string(state));
+ }
+ json_object_object_add(*json_out, key, json_obj);
+}
+
+std::vector<std::string> PolicyManager::parseString(std::string str, char delimiter) {
+ // Parse string by delimiter
+ std::vector<std::string> vct;
+ std::stringstream ss{str};
+ std::string buf;
+ while (std::getline(ss, buf, delimiter)) {
+ if (!buf.empty()) {
+ vct.push_back(buf);
+ }
+ }
+ return vct;
+}
+
+std::string PolicyManager::deleteSpace(std::string str) {
+ std::string ret = str;
+ size_t pos;
+ while ((pos = ret.find_first_of(" ")) != std::string::npos) {
+ ret.erase(pos, 1);
+ }
+ return ret;
+}
+
+const char* kDefaultRoleDb = "{ \
+ \"roles\":[ \
+ { \
+ \"category\": \"homescreen\", \
+ \"role\": \"homescreen\", \
+ \"area\": \"full\", \
+ }, \
+ { \
+ \"category\": \"map\", \
+ \"role\": \"map\", \
+ \"area\": \"full | normal | split.main\", \
+ }, \
+ { \
+ \"category\": \"general\", \
+ \"role\": \"poi | music | video | browser | sdl | settings | mixer | radio | hvac | dashboard | debug\", \
+ \"area\": \"normal\", \
+ }, \
+ { \
+ \"category\": \"phone\", \
+ \"role\": \"phone\", \
+ \"area\": \"normal\", \
+ }, \
+ { \
+ \"category\": \"splitable\", \
+ \"role\": \"splitable1 | splitable2\", \
+ \"area\": \"normal | split.main | split.sub\", \
+ }, \
+ { \
+ \"category\": \"popup\", \
+ \"role\": \"popup\", \
+ \"area\": \"on_screen\", \
+ }, \
+ { \
+ \"category\": \"system_alert\", \
+ \"role\": \"system_alert\", \
+ \"area\": \"on_screen\", \
+ }, \
+ { \
+ \"category\": \"tbt\", \
+ \"role\": \"tbt\", \
+ \"area\": \"hud\", \
+ } \
+ ] \
+}";