aboutsummaryrefslogtreecommitdiffstats
path: root/src/layout_manager/layout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout_manager/layout.cpp')
-rw-r--r--src/layout_manager/layout.cpp570
1 files changed, 570 insertions, 0 deletions
diff --git a/src/layout_manager/layout.cpp b/src/layout_manager/layout.cpp
new file mode 100644
index 0000000..dc73cbf
--- /dev/null
+++ b/src/layout_manager/layout.cpp
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2017 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 <json-c/json.h>
+#include "layout.hpp"
+#include "json_helper.hpp"
+#include "hmi-debug.h"
+
+
+LayoutManager::LayoutManager() {
+ HMI_DEBUG("wm:lm", "Call");
+}
+
+int LayoutManager::initialize() {
+ HMI_DEBUG("wm:lm", "Call");
+
+ int ret = 0;
+
+ // Load layout.db
+ ret = this->loadLayoutDb();
+ if (0 > ret) {
+ HMI_ERROR("wm:lm", "Load layout.db Error!!");
+ return ret;
+ }
+
+ TypeLayouts layout;
+ TypeAreas area;
+ TypeRolCtg rol_ctg;
+
+ rol_ctg["none"] = "none";
+ area["none"] = rol_ctg;
+ layout["none"] = area;
+
+ this->prv_layers_["on_screen"] = layout;
+ this->prv_layers_["apps"] = layout;
+ this->prv_layers_["homescreen"] = layout;
+
+ this->crr_layers_["on_screen"] = layout;
+ this->crr_layers_["apps"] = layout;
+ this->crr_layers_["homescreen"] = layout;
+
+ this->prv_layers_car_stop_["on_screen"] = layout;
+ this->prv_layers_car_stop_["apps"] = layout;
+ this->prv_layers_car_stop_["homescreen"] = layout;
+
+ return ret;
+}
+
+bool LayoutManager::updateLayout(json_object* obj,
+ const char* new_role, const char* category) {
+ HMI_DEBUG("wm:lm", "Call");
+
+ bool ret = false;
+
+ // Check car state change
+ json_object* json_car;
+ if (!json_object_object_get_ex(obj, "car", &json_car)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+
+ json_bool is_car_state_changed;
+ std::string car_state = "";
+ is_car_state_changed = jh::getBoolFromJson(json_car, "is_changed");
+ if (is_car_state_changed) {
+ // If car state is changed, get car state
+ car_state = jh::getStringFromJson(json_car, "state");
+ }
+
+ // Update layout of all layers
+ json_object* json_layers;
+ if (!json_object_object_get_ex(obj, "layers", &json_layers)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+
+ int len = json_object_array_length(json_layers);
+ HMI_DEBUG("wm:lm", "json_layers len:%d", len);
+ HMI_DEBUG("wm:lm", "json_layers dump:%s", json_object_get_string(json_layers));
+
+ for (int i=0; i<len; i++) {
+ json_object* json_tmp = json_object_array_get_idx(json_layers, i);
+
+ // Get layer name and json_object
+ const char* layer;
+ json_object* json_layer;
+ json_object_object_foreach(json_tmp, key, val) {
+ layer = key;
+ json_layer = val;
+ HMI_DEBUG("wm:lm", "Update %s layer state", layer);
+ }
+
+ // Store previous state
+ this->prv_layers_[layer] = this->crr_layers_[layer];
+ std::string prv_layout_name = this->prv_layers_[layer].begin()->first;
+
+ // If car state is changed car_stop -> car_run,
+ // store current state for state of car stop
+ if ((is_car_state_changed) && ("car_run" == car_state)) {
+ HMI_DEBUG("wm:lm", "Store current state for state of car stop");
+ this->prv_layers_car_stop_[layer] = this->crr_layers_[layer];
+ }
+
+ json_object* json_is_changed;
+ if (!json_object_object_get_ex(json_layer, "is_changed", &json_is_changed)) {
+ HMI_ERROR("wm:lm", "Not found key \"is_changed\"");
+ return false;
+ }
+
+ // If layer state is changed
+ if (json_object_get_boolean(json_is_changed)) {
+ // Set layout changed flag
+ this->is_layout_changed_[layer] = true;
+
+ json_object* json_state;
+ if (!json_object_object_get_ex(json_layer, "state", &json_state)) {
+ HMI_ERROR("wm:lm", "Not found key \"state\"");
+ return false;
+ }
+
+ const char* crr_layout_name = json_object_get_string(json_state);
+ HMI_DEBUG("wm:lm", "crr state: %s", crr_layout_name);
+
+ TypeLayouts crr_layout;
+ if ((is_car_state_changed) && ("car_stop" == car_state)) {
+ // If car state is changed car_run -> car_stop,
+ // restore state of car stop
+ HMI_DEBUG("wm:lm", "Restore state of car stop");
+ crr_layout = this->prv_layers_car_stop_[layer];
+ }
+ else if ("none" == std::string(crr_layout_name)) {
+ // If current layout is "none",
+ // current areas is set with "none"
+ TypeAreas area;
+ TypeRolCtg rol_ctg;
+ rol_ctg["none"] = "none";
+ area["none"] = rol_ctg;
+ crr_layout["none"] = area;
+ }
+ else {
+ if (std::string(crr_layout_name) == prv_layout_name) {
+ // If previous layout is same with current,
+ // previous areas are copied to current
+ crr_layout[crr_layout_name] = this->prv_layers_[layer][crr_layout_name];
+ }
+ else {
+ // If previous layout is NOT same with current,
+ // current areas is set with default value
+ crr_layout[crr_layout_name] = this->layout_define_[crr_layout_name];
+ }
+
+ if (is_car_state_changed) {
+ // Updating role is not necessary
+ // because new_role is not specified when car state is changed
+ }
+ else {
+ // Get new_area for new role
+ std::string new_area = this->getAreaName(this->layout_define_[crr_layout_name],
+ new_role, category);
+
+ // Update role in new area
+ TypeRolCtg crr_role;
+ crr_role["role"] = std::string(new_role);
+ crr_layout[crr_layout_name][new_area] = crr_role;
+ }
+ }
+
+ // Update layer state
+ this->crr_layers_[layer] = crr_layout;
+
+ // Check
+ for (auto itr_layout = this->crr_layers_[layer].begin();
+ itr_layout != this->crr_layers_[layer].end(); ++itr_layout) {
+ for (auto itr_area = itr_layout->second.begin();
+ itr_area != itr_layout->second.end(); ++itr_area) {
+ for (auto itr_role = itr_area->second.begin();
+ itr_role != itr_area->second.end(); ++itr_role) {
+ HMI_DEBUG("wm:lm", "layout:%s, area:%s, rol_ctg:%s, name:%s",
+ itr_layout->first.c_str(), itr_area->first.c_str(),
+ itr_role->first.c_str(), itr_role->second.c_str());
+ }
+ }
+ }
+
+ ret = true;
+ }
+ else {
+ // Clear layout changed flag
+ this->is_layout_changed_[layer] = false;
+ }
+ }
+ return ret;
+}
+
+// TODO: This API is for workaround, so this will be removed
+void LayoutManager::updateArea(const char* layer, const char* role, const char* area) {
+ this->crr_layers_[layer].begin()->second[area]["role"] = std::string(role);
+}
+
+LayoutManager::TypeLayers LayoutManager::getCurrentLayers() {
+ return this->crr_layers_;
+}
+
+LayoutManager::TypeLayers LayoutManager::getPreviousLayers() {
+ return this->prv_layers_;
+}
+
+compositor::rect LayoutManager::getAreaSize(const char* area) {
+ return this->area2size_[area];
+}
+
+std::string LayoutManager::getAreaName(TypeAreas areas, const char* role, const char* category) {
+ for (auto itr_area = areas.begin(); itr_area != areas.end(); ++itr_area) {
+ std::string area_name = itr_area->first;
+ TypeRolCtg rol_ctg = itr_area->second;
+
+ if ("role" == rol_ctg.begin()->first) {
+ if (std::string(role) == rol_ctg.begin()->second) {
+ return area_name;
+ }
+ }
+ else if ("category" == rol_ctg.begin()->first) {
+ if (std::string(category) == rol_ctg.begin()->second) {
+ return area_name;
+ }
+ }
+ else {
+ return std::string("none");
+ }
+ }
+ return std::string("none");
+}
+
+
+bool LayoutManager::isLayoutChanged(const char* layer) {
+ return this->is_layout_changed_[layer];
+}
+
+extern const char* kDefaultLayoutDb;
+int LayoutManager::loadLayoutDb() {
+ HMI_DEBUG("wm:lm", "Call");
+
+ // Get afm application installed dir
+ char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
+ HMI_DEBUG("wm:lm", "afm_app_install_dir:%s", afm_app_install_dir);
+
+ std::string file_name;
+ if (!afm_app_install_dir) {
+ HMI_ERROR("wm:lm", "AFM_APP_INSTALL_DIR is not defined");
+ }
+ else {
+ file_name = std::string(afm_app_install_dir) + std::string("/etc/layout.db");
+ }
+
+ // Load layout.db
+ HMI_DEBUG("wm:lm", "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:lm", "Could not open layout.db, so use default role information");
+ json_obj = json_tokener_parse(kDefaultLayoutDb);
+ }
+ HMI_DEBUG("wm:lm", "json_obj dump:%s", json_object_get_string(json_obj));
+
+ // Perse layouts
+ HMI_DEBUG("wm:lm", "Perse layouts");
+ json_object* json_cfg;
+ if (!json_object_object_get_ex(json_obj, "layouts", &json_cfg)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+
+ int len = json_object_array_length(json_cfg);
+ HMI_DEBUG("wm:lm", "json_cfg len:%d", len);
+ HMI_DEBUG("wm:lm", "json_cfg dump:%s", json_object_get_string(json_cfg));
+
+ const char* layout;
+ const char* role;
+ const char* category;
+ for (int i=0; i<len; i++) {
+ json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
+
+ layout = jh::getStringFromJson(json_tmp, "name");
+ if (nullptr == layout) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+ HMI_DEBUG("wm:lm", "> layout:%s", layout);
+
+ json_object* json_area_array;
+ if (!json_object_object_get_ex(json_tmp, "areas", &json_area_array)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+
+ int len_area = json_object_array_length(json_area_array);
+ HMI_DEBUG("wm:lm", "json_area_array len:%d", len_area);
+ HMI_DEBUG("wm:lm", "json_area_array dump:%s", json_object_get_string(json_area_array));
+
+ TypeAreas areas;
+ for (int j=0; j<len_area; j++) {
+ json_object* json_area = json_object_array_get_idx(json_area_array, j);
+
+ const char* area = jh::getStringFromJson(json_area, "name");
+ if (nullptr == area) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+ HMI_DEBUG("wm:lm", ">> area:%s", area);
+
+ TypeRolCtg rol_ctg_name;
+ role = jh::getStringFromJson(json_area, "role");
+ if (nullptr == role) {
+ category = jh::getStringFromJson(json_area, "category");
+ if (nullptr == category) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+ rol_ctg_name["category"] = std::string(category);
+ HMI_DEBUG("wm:lm", ">>> category:%s", category);
+ }
+ else {
+ rol_ctg_name["role"] = std::string(role);
+ HMI_DEBUG("wm:lm", ">>> role:%s", role);
+ }
+
+ areas[area] = rol_ctg_name;
+ }
+
+ this->layout_define_[layout] = areas;
+ }
+
+ // Check
+ for(auto itr_layout = this->layout_define_.begin();
+ itr_layout != this->layout_define_.end(); ++itr_layout) {
+ for (auto itr_area = itr_layout->second.begin();
+ itr_area != itr_layout->second.end(); ++itr_area) {
+ for (auto itr_role = itr_area->second.begin();
+ itr_role != itr_area->second.end(); ++itr_role) {
+ HMI_DEBUG("wm:lm", "layout:%s, area:%s, rol_ctg:%s, name:%s",
+ itr_layout->first.c_str(), itr_area->first.c_str(),
+ itr_role->first.c_str(), itr_role->second.c_str());
+ }
+ }
+ }
+
+ // Perse areas
+ HMI_DEBUG("wm:lm", "Perse areas");
+ if (!json_object_object_get_ex(json_obj, "areas", &json_cfg)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+
+ len = json_object_array_length(json_cfg);
+ HMI_DEBUG("wm:lm", "json_cfg len:%d", len);
+ HMI_DEBUG("wm:lm", "json_cfg dump:%s", json_object_get_string(json_cfg));
+
+ const char* area;
+ for (int i=0; i<len; i++) {
+ json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
+ HMI_DEBUG("wm:lm", "> json_tmp dump:%s", json_object_get_string(json_tmp));
+
+ area = jh::getStringFromJson(json_tmp, "name");
+ if (nullptr == area) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+ HMI_DEBUG("wm:lm", "> area:%s", area);
+
+ json_object* json_rect;
+ if (!json_object_object_get_ex(json_tmp, "rect", &json_rect)) {
+ HMI_ERROR("wm:lm", "Parse Error!!");
+ return -1;
+ }
+ HMI_DEBUG("wm:lm", "> json_rect dump:%s", json_object_get_string(json_rect));
+
+ compositor::rect area_size;
+ area_size.x = jh::getIntFromJson(json_rect, "x");
+ area_size.y = jh::getIntFromJson(json_rect, "y");
+ area_size.w = jh::getIntFromJson(json_rect, "w");
+ area_size.h = jh::getIntFromJson(json_rect, "h");
+
+ this->area2size_[area] = area_size;
+ }
+
+ // Check
+ for(auto itr = this->area2size_.begin();
+ itr != this->area2size_.end(); ++itr) {
+ HMI_DEBUG("wm:lm", "area:%s x:%d y:%d w:%d h:%d",
+ itr->first.c_str(), itr->second.x, itr->second.y,
+ itr->second.w, itr->second.h);
+ }
+
+ // Release json_object
+ json_object_put(json_obj);
+
+ return 0;
+}
+
+const char* kDefaultLayoutDb = "{ \
+ \"layouts\": [ \
+ { \
+ \"name\": \"pu\", \
+ \"layer\": \"on_screen\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"pop_up\", \
+ \"role\": \"incomming_call\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"sa\", \
+ \"layer\": \"on_screen\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"system_alert\", \
+ \"role\": \"system_alert\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"m1\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"normal\", \
+ \"role\": \"map\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"m2\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"split.main\", \
+ \"role\": \"map\" \
+ }, \
+ { \
+ \"name\": \"split.sub\", \
+ \"category\": \"hvac\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"mf\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"full\", \
+ \"role\": \"map\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"s1\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"normal\", \
+ \"category\": \"splitable\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"s2\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"split.main\", \
+ \"category\": \"splitable\" \
+ }, \
+ { \
+ \"name\": \"split.sub\", \
+ \"category\": \"splitable\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"g\", \
+ \"layer\": \"apps\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"normal\", \
+ \"category\": \"general\" \
+ } \
+ ] \
+ }, \
+ { \
+ \"name\": \"hs\", \
+ \"layer\": \"homescreen\", \
+ \"areas\": [ \
+ { \
+ \"name\": \"full\", \
+ \"role\": \"homescreen\" \
+ } \
+ ] \
+ } \
+ ], \
+ \"areas\": [ \
+ { \
+ \"name\": \"normal\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 218, \
+ \"w\": 1080, \
+ \"h\": 1488 \
+ } \
+ }, \
+ { \
+ \"name\": \"split.main\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 218, \
+ \"w\": 1080, \
+ \"h\": 744 \
+ } \
+ }, \
+ { \
+ \"name\": \"split.sub\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 962, \
+ \"w\": 1080, \
+ \"h\": 744 \
+ } \
+ }, \
+ { \
+ \"name\": \"full\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 0, \
+ \"w\": 1080, \
+ \"h\": 1920 \
+ } \
+ }, \
+ { \
+ \"name\": \"pop_up\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 640, \
+ \"w\": 1080, \
+ \"h\": 640 \
+ } \
+ }, \
+ { \
+ \"name\": \"system_alert\", \
+ \"rect\": { \
+ \"x\": 0, \
+ \"y\": 640, \
+ \"w\": 1080, \
+ \"h\": 640 \
+ } \
+ } \
+ ] \
+}";