#include <istream>
#include <thread>
#include <map>
-#include <queue>
#include <systemd/sd-event.h>
#include <json-c/json.h>
#include "policy_manager.hpp"
typedef struct LayerState {
std::string name;
LayoutState layout_state;
+ int changed;
} LayerState;
-typedef struct EventInfo {
- int event;
- std::string role;
- uint64_t delay;
-} EventInfo;
+typedef struct CarElement {
+ std::string state;
+ int changed;
+} CarElement;
struct sd_event* event_loop;
std::map<int, struct sd_event_source*> event_source_list;
std::map<int, std::string> g_req_role_list;
PolicyManager::CallbackTable callback;
-std::queue<EventInfo> g_event_info_queue;
+
+std::unordered_map<std::string, CarElement> g_prv_car_elements;
+std::unordered_map<std::string, CarElement> g_crr_car_elements;
std::unordered_map<std::string, LayerState> g_prv_layers;
std::unordered_map<std::string, LayerState> g_crr_layers;
+
std::unordered_map<std::string, LayerState> g_prv_layers_car_stop;
+
std::unordered_map<std::string, LayoutState> g_default_layouts;
} // namespace pm
PolicyManager::PolicyManager() :
- eventname2no_(),
- categoryname2no_(),
- areaname2no_(),
- role2category_(),
- category2role_(),
- role2defaultarea_()
+ eventname2no(),
+ categoryname2no(),
+ areaname2no(),
+ role2category(),
+ category2role(),
+ role2defaultarea()
{
HMI_DEBUG("wm:pm", "Call");
}
// Create convert map
for (int i = stm::gStmEventNoMin; i <= stm::gStmEventNoMax; i++) {
HMI_DEBUG("wm:pm", "event name:%s no:%d", stm::gStmEventName[i], stm::gStmEventNo[i]);
- this->eventname2no_[stm::gStmEventName[i]] = stm::gStmEventNo[i];
+ this->eventname2no[stm::gStmEventName[i]] = stm::gStmEventNo[i];
}
for (int i = stm::gStmCategoryNoMin; i <= stm::gStmCategoryNoMax; i++) {
HMI_DEBUG("wm:pm", "category name:%s no:%d", stm::gStmCategoryName[i], stm::gStmCategoryNo[i]);
- this->categoryname2no_[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
+ this->categoryname2no[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
}
for (int i = stm::gStmAreaNoMin; i <= stm::gStmAreaNoMax; i++) {
HMI_DEBUG("wm:pm", "area name:%s no:%d", stm::gStmAreaName[i], stm::gStmAreaNo[i]);
- this->areaname2no_[stm::gStmAreaName[i]] = stm::gStmAreaNo[i];
+ this->areaname2no[stm::gStmAreaName[i]] = stm::gStmAreaNo[i];
}
// Load role.db
return ret;
}
- // Initialize current/previous state of layers
+ // Initialize state which is managed by PolicyManager
+ this->initializeLocalState();
+
+ // Initialize StateTransitioner
+ stm::stmInitialize();
+
+ // Initialize sd_event loop
+ ret = this->initializeSdEventLoop();
+ if (0 > ret) {
+ HMI_ERROR("wm:pm", "Failed to initializeSdEventLoop!!");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void initializeLocalCarElementState() {
+ pm::CarElement init_car_ele;
+ init_car_ele.state = "none";
+ init_car_ele.changed = 0;
+
+ for (int i = stm::gStmCarElementNoMin; i <= stm::gStmCarElementNoMax; i++) {
+ const char* car_ele_name = stm::gStmCarElementName[i];
+ pm::g_crr_car_elements[car_ele_name] = init_car_ele;
+ }
+
+ pm::g_prv_car_elements = pm::g_crr_car_elements;
+}
+
+static void initializeLocalLayerState() {
pm::AreaState init_area;
pm::LayoutState init_layout;
init_area.name = "none";
init_area.category = "none";
init_area.role = "none";
+ init_layout.name = "none";
init_layout.area_list.push_back(init_area);
for (int i = stm::gStmLayerNoMin; i <= stm::gStmLayerNoMax; i++) {
const char* layer_name = stm::gStmLayerName[i];
- pm::g_crr_layers[layer_name].name = layer_name;
- pm::g_crr_layers[layer_name].layout_state = init_layout;
+ pm::g_crr_layers[layer_name].name = layer_name;
+ pm::g_crr_layers[layer_name].layout_state = init_layout;
+ pm::g_crr_layers[layer_name].changed = 0;
}
pm::g_prv_layers = pm::g_crr_layers;
+}
- // Initialize StateTransitioner
- stm::stmInitialize();
-
- // Initialize sd_event loop
- ret = this->initializeSdEventLoop();
- if (0 > ret) {
- HMI_ERROR("wm:pm", "Failed to initializeSdEventLoop!!");
- return ret;
- }
-
- return ret;
+void PolicyManager::initializeLocalState() {
+ initializeLocalCarElementState();
+ initializeLocalLayerState();
}
int PolicyManager::initializeSdEventLoop() {
}
static void 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!!!");
+ const char* name, int changed, std::string state, json_object** json_out) {
+ if ((nullptr == name) || (1 < changed) || (nullptr == json_out)) {
+ HMI_ERROR("wm:pm", "Invalid argument!!!");
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);
+ json_object_object_add(*json_out, "name", json_object_new_string(name));
+ json_object_object_add(*json_out, "state", json_object_new_string(state.c_str()));
+ json_object_object_add(*json_out, "changed", json_object_new_boolean(changed));
}
static void addStateToJson(const char* layer_name, unsigned int changed,
json_object_object_add(*json_out, "areas", json_areas);
}
-static void updateLocalState(int event_data, stm::stm_state_t crr_state) {
+static void updateLocalCarElementState(stm::stm_state_t crr_state) {
+ int car_state_no;
+ std::string car_state;
+ bool changed;
+
+ // Store previous layers
+ pm::g_prv_car_elements = pm::g_crr_car_elements;
+
+ // Update car elements
+ HMI_DEBUG("wm:pm", ">>> CAR ELEMENT");
+ for (int car_ele_no = stm::gStmCarElementNoMin;
+ car_ele_no <= stm::gStmCarElementNoMax; car_ele_no++) {
+ const char* car_ele_name = stm::gStmCarElementName[car_ele_no];
+
+ car_state_no = crr_state.car_element[car_ele_no].state;
+ car_state = stm::gStmCarStateNameList[car_ele_no][car_state_no];
+ changed = crr_state.car_element[car_ele_no].is_changed;
+
+ pm::g_crr_car_elements[car_ele_name].state = car_state;
+ pm::g_crr_car_elements[car_ele_name].changed = changed;
+
+ HMI_DEBUG("wm:pm", ">>> >>> NAME: %s", car_ele_name);
+ HMI_DEBUG("wm:pm", ">>> >>> >>> STATE:%s", car_state.c_str());
+ HMI_DEBUG("wm:pm", ">>> >>> >>> CHANGED:%d", changed);
+ }
+}
+
+static void updateLocalLayerState(int event_data, stm::stm_state_t crr_state) {
int event_no, category_no, area_no;
event_no = (event_data & STM_MSK_EVT_NO) - 1;
#if 1
// If restriction mode is changed off -> on,
// store current state for state of restriction mode off
- if ((crr_state.restriction_mode.is_changed)
- && (stm::gStmRestrictionModeStateNoOn == crr_state.restriction_mode.state)) {
+ if ((crr_state.car_element[stm::gStmCarElementNoRestrictionMode].is_changed)
+ && (stm::gStmRestrictionModeStateNoOn == crr_state.car_element[stm::gStmCarElementNoRestrictionMode].state)) {
HMI_DEBUG("wm:lm", "Store current state for state of restriction mode off");
pm::g_prv_layers_car_stop[layer_name] = pm::g_crr_layers[layer_name];
}
// If car state is changed car_stop -> car_run,
// store current state for state of car stop
if ((crr_state.car.is_changed)
- && (stm::gStmCarStateNoRun == crr_state.car.state)) {
+ && (stm::gStmRunningNoRun == crr_state.car.state)) {
HMI_DEBUG("wm:lm", "Store current state for state of car stop");
pm::g_prv_layers_car_stop[layer_name] = pm::g_crr_layers[layer_name];
}
pm::LayoutState crr_layout_state;
#if 1
- if ((crr_state.restriction_mode.is_changed)
- && (stm::gStmRestrictionModeStateNoOff == crr_state.restriction_mode.state)) {
+ if ((crr_state.car_element[stm::gStmCarElementNoRestrictionMode].is_changed)
+ && (stm::gStmRestrictionModeStateNoOff == crr_state.car_element[stm::gStmCarElementNoRestrictionMode].state)) {
// If restriction mode is changed on -> off,
// restore state of restriction mode off
HMI_DEBUG("wm:lm", "Restriction mode is changed on -> off, so restore state of restriction mode off");
crr_layout_state = pm::g_prv_layers_car_stop[layer_name].layout_state;
#else
- if ((crr_state.car.is_changed)
- && (stm::gStmCarStateNoStop == crr_state.car.state)) {
+ if ((crr_state.car_element[gStmCarElementNoRunning].is_changed)
+ && (stm::gStmCarElementNoStop == crr_state.car_element[gStmCarElementNoRunning].state)) {
// If car state is changed car_run -> car_stop,
// restore state of car stop
HMI_DEBUG("wm:lm", "Car state is changed car_run -> car_stop, so restore state of car stop");
}
// Update current layout of this layer
pm::g_crr_layers[layer_name].layout_state = crr_layout_state;
+ pm::g_crr_layers[layer_name].changed = crr_state.layer[layer_no].is_changed;
}
}
HMI_DEBUG("wm:pm", ">>> >>> >>> >>> CTG:%s", as.category.c_str());
HMI_DEBUG("wm:pm", ">>> >>> >>> >>> ROLE:%s", as.role.c_str());
}
+ HMI_DEBUG("wm:pm", ">>> >>> CHANGED:%d", ls.changed);
}
}
-void createOutputInformation(stm::stm_state_t crr_state, json_object **json_out) {
- // Create result
+static void updateLocalState(int event_data, stm::stm_state_t crr_state) {
+ updateLocalCarElementState(crr_state);
+ updateLocalLayerState(event_data, crr_state);
+}
+
+static void createOutputInformation(stm::stm_state_t crr_state, json_object **json_out) {
+ json_object* json_tmp;
+
+ // Create car element information
// {
- // "parking_brake": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // },
- addStateToJson("parking_brake",
- crr_state.parking_brake.is_changed,
- stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state],
- json_out);
-
- // "accel_pedal": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // },
- addStateToJson("accel_pedal",
- crr_state.accel_pedal.is_changed,
- stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state],
- json_out);
-
- // "lightstatus_brake": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // },
- addStateToJson("lightstatus_brake",
- crr_state.lightstatus_brake.is_changed,
- stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state],
- json_out);
-
- // "car": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // },
- addStateToJson("car",
- crr_state.car.is_changed,
- stm::gStmCarStateNo2Name[crr_state.car.state],
- json_out);
-
- // "lamp": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // },
- addStateToJson("lamp",
- crr_state.lamp.is_changed,
- stm::gStmLampStateNo2Name[crr_state.lamp.state],
- json_out);
-
- // "restriction_mode": {
- // "is_changed": <bool>,
- // "state": <const char*>
+ // "car_elements": [
+ // {
+ // "parking_brake": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // },
+ // ...
// },
- addStateToJson("restriction_mode",
- crr_state.restriction_mode.is_changed,
- stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
- json_out);
+ json_object* json_car_ele = json_object_new_array();
+ const char* car_ele_name;
+ for (int car_ele_no = stm::gStmCarElementNoMin;
+ car_ele_no <= stm::gStmCarElementNoMax; car_ele_no++) {
+ car_ele_name = stm::gStmCarElementName[car_ele_no];
+ json_tmp = json_object_new_object();
+ addStateToJson(car_ele_name,
+ pm::g_crr_car_elements[car_ele_name].changed,
+ pm::g_crr_car_elements[car_ele_name].state,
+ &json_tmp);
+ json_object_array_add(json_car_ele, json_tmp);
+ }
+ json_object_object_add(*json_out, "car_elements", json_car_ele);
// Create layout information
//
// },
// ...
json_object* json_layer = json_object_new_array();
- json_object* json_tmp;
+ const char* layer_name;
for (int layer_no = stm::gStmLayerNoMin;
layer_no <= stm::gStmLayerNoMax; layer_no++) {
- const char* layer_name = stm::gStmLayerName[layer_no];
- HMI_DEBUG("wm:pm", "LAYER:%s", layer_name);
-
+ layer_name = stm::gStmLayerName[layer_no];
json_tmp = json_object_new_object();
addStateToJson(layer_name,
- crr_state.layer[layer_no].is_changed,
+ pm::g_crr_layers[layer_name].changed,
pm::g_crr_layers[layer_name].layout_state.area_list,
&json_tmp);
json_object_array_add(json_layer, json_tmp);
}
-
- // Add json array of layer
json_object_object_add(*json_out, "layers", json_layer);
}
static int checkPolicyEntry(int event, uint64_t delay_ms, std::string role);
+static void controlTimerEvent(stm::stm_state_t crr_state) {
+ if (crr_state.car_element[stm::gStmCarElementNoRunning].is_changed) {
+ if (stm::gStmRunningNoRun == crr_state.car_element[stm::gStmCarElementNoRunning].state) {
+ // Set delay event(restriction mode on)
+ checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_ON, 3000, "");
+ }
+ else if (stm::gStmRunningNoStop == crr_state.car_element[stm::gStmCarElementNoRunning].state) {
+ // Stop timer for restriction on event
+ if (pm::event_source_list.find(STM_EVT_NO_RESTRICTION_MODE_ON)
+ != pm::event_source_list.end()) {
+ HMI_DEBUG("wm:pm", "Stop timer for restriction on");
+ sd_event_source *event_source
+ = pm::event_source_list[STM_EVT_NO_RESTRICTION_MODE_ON];
+ int ret = sd_event_source_set_enabled(event_source, SD_EVENT_OFF);
+ if (0 > ret) {
+ HMI_ERROR("wm:pm", "Failed to stop timer");
+ }
+ }
+
+ // Set event(restriction mode off)
+ checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_OFF, 0, "");
+ }
+ }
+}
+
static int checkPolicy(sd_event_source *source, void *data) {
HMI_DEBUG("wm:pm", "Call");
HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
return -1;
}
- HMI_DEBUG("wm:pm", "parking brake state (is_changed:%d state:%d:%s)",
- crr_state.parking_brake.is_changed,
- crr_state.parking_brake.state,
- stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state]);
- HMI_DEBUG("wm:pm", "accelerator pedal state (is_changed:%d state:%d:%s)",
- crr_state.accel_pedal.is_changed,
- crr_state.accel_pedal.state,
- stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state]);
- HMI_DEBUG("wm:pm", "lightstatus brake state (is_changed:%d state:%d:%s)",
- crr_state.lightstatus_brake.is_changed,
- crr_state.lightstatus_brake.state,
- stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state]);
- HMI_DEBUG("wm:pm", "car state (is_changed:%d state:%d:%s)",
- crr_state.car.is_changed,
- crr_state.car.state,
- stm::gStmCarStateNo2Name[crr_state.car.state]);
- HMI_DEBUG("wm:pm", "lamp state (is_changed:%d state:%d:%s)",
- crr_state.lamp.is_changed,
- crr_state.lamp.state,
- stm::gStmLampStateNo2Name[crr_state.lamp.state]);
- HMI_DEBUG("wm:pm", "restriction mode state (is_changed:%d state:%d:%s)",
- crr_state.restriction_mode.is_changed,
- crr_state.restriction_mode.state,
- stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state]);
- HMI_DEBUG("wm:pm", "homescreen state (is_changed:%d state:%d:%s)",
- crr_state.layer[stm::gStmLayerNoHomescreen].is_changed,
- crr_state.layer[stm::gStmLayerNoHomescreen].state,
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state]);
- HMI_DEBUG("wm:pm", "apps state (is_changed:%d state:%d:%s)",
- crr_state.layer[stm::gStmLayerNoApps].is_changed,
- crr_state.layer[stm::gStmLayerNoApps].state,
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoApps].state]);
- HMI_DEBUG("wm:pm", "restriction state (is_changed:%d state:%d:%s)",
- crr_state.layer[stm::gStmLayerNoRestriction].is_changed,
- crr_state.layer[stm::gStmLayerNoRestriction].state,
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoRestriction].state]);
- HMI_DEBUG("wm:pm", "on_screen state (is_changed:%d state:%d:%s)",
- crr_state.layer[stm::gStmLayerNoOnScreen].is_changed,
- crr_state.layer[stm::gStmLayerNoOnScreen].state,
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoOnScreen].state]);
-
// Update state which is managed by PolicyManager
updateLocalState(event_data, crr_state);
json_object* json_out = json_object_new_object();
createOutputInformation(crr_state, &json_out);
- // Notify state is changed
+ // Notify changed state
if (nullptr != pm::callback.onStateTransitioned) {
pm::callback.onStateTransitioned(json_out);
}
- // Start/Stop timer event
- if (crr_state.car.is_changed) {
- if (stm::gStmCarStateNoRun == crr_state.car.state) {
- // Set delay event(restriction mode on)
- checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_ON, 3000, "");
- }
- else if (stm::gStmCarStateNoStop == crr_state.car.state) {
- // Set event(restriction mode off)
- checkPolicyEntry(STM_EVT_NO_RESTRICTION_MODE_OFF, 0, "");
-
- // Stop timer for restriction on event
- if (pm::event_source_list.find(STM_EVT_NO_RESTRICTION_MODE_ON)
- != pm::event_source_list.end()) {
- HMI_DEBUG("wm:pm", "Stop timer for restriction on");
- sd_event_source *event_source
- = pm::event_source_list[STM_EVT_NO_RESTRICTION_MODE_ON];
- int ret = sd_event_source_set_enabled(event_source, SD_EVENT_OFF);
- if (0 > ret) {
- HMI_ERROR("wm:pm", "Failed to stop timer");
- }
- }
- }
- }
+ // Start/Stop timer events
+ controlTimerEvent(crr_state);
// Release json_object
json_object_put(json_out);
int event_no = 0;
if (nullptr != event) {
// Convert name to number
- event_no = this->eventname2no_[event];
+ event_no = this->eventname2no[event];
HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
}
HMI_DEBUG("wm:pm", "role(%s)", role);
// Convert role to category
- const char* category = this->role2category_[role].c_str();
+ 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];
+ category_no = categoryname2no[category];
HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
}
int area_no = 0;
if (nullptr != area) {
// Convert name to number
- area_no = areaname2no_[area];
+ area_no = areaname2no[area];
HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
}
// Set event info to the queue
- pm::EventInfo event_info;
+ EventInfo event_info;
event_info.event = (event_no | category_no | area_no);
if (nullptr == role) {
event_info.role = std::string("");
event_info.role = std::string(role);
}
event_info.delay = 0;
- pm::g_event_info_queue.push(event_info);
+ this->event_info_queue.push(event_info);
return 0;
}
HMI_DEBUG("wm:pm", "Call");
int ret;
- pm::EventInfo event_info;
+ EventInfo event_info;
- while (!pm::g_event_info_queue.empty()) {
+ while (!this->event_info_queue.empty()) {
// Get event info from queue and delete
- event_info = pm::g_event_info_queue.front();
- pm::g_event_info_queue.pop();
+ event_info = this->event_info_queue.front();
+ this->event_info_queue.pop();
// Set event info for checking policy
ret = checkPolicyEntry(event_info.event, event_info.delay, event_info.role);
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->role2category[role] = std::string(category);
+ this->role2defaultarea[role] = area;
}
- this->category2role_[std::string(category)] = std::string(roles);
+ this->category2role[std::string(category)] = std::string(roles);
}
// Check
- HMI_DEBUG("wm:pm", "Check role2category_");
- for (auto& x:this->role2category_){
+ 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", "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", "Check category2role");
+ for (auto& x:this->category2role){
HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
}