#include <istream>
#include <thread>
#include <map>
+#include <queue>
#include <systemd/sd-event.h>
#include <json-c/json.h>
#include "policy_manager.hpp"
typedef struct LayoutState {
std::string name;
std::map<std::string, int> category_num;
-// int category_num[stm::gStmCategoryNoNum];
AreaList area_list;
std::map<std::string, std::vector<std::string>> role_history;
} LayoutState;
LayoutState layout_state;
} LayerState;
+typedef struct EventInfo {
+ int event;
+ std::string role;
+ uint64_t delay;
+} EventInfo;
+
struct sd_event* event_loop;
std::map<int, struct sd_event_source*> event_source_list;
-std::map<int, std::string> g_event_info_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, LayerState> g_prv_layers;
std::unordered_map<std::string, LayerState> g_crr_layers;
int ret = 0;
// Create convert map
- for (unsigned int i=0; i<STM_NUM_EVT; i++) {
+ 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->categoryname2no_[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
}
- for (unsigned int i=0; i<STM_NUM_ARA; 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];
}
json_object_object_add(*json_out, key, json_obj);
}
-static int checkPolicyEntry(int event, uint64_t delay_ms, const char* role);
-static int checkPolicy(sd_event_source *source, void *data) {
- HMI_DEBUG("wm:pm", "Call");
- HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
+static void addStateToJson(const char* layer_name, unsigned int changed,
+ pm::AreaList area_list, json_object** json_out) {
+ if ((nullptr == layer_name) || (1 < changed) || (nullptr == json_out)) {
+ HMI_ERROR("wm:pm", "Invalid argument!!!");
+ return;
+ }
- int event_data = *((int*)data);
+ json_object* json_areas = json_object_new_array();
+ json_object* json_tmp;
+ for (pm::AreaState as : area_list) {
+ json_tmp = json_object_new_object();
+ json_object_object_add(json_tmp, "name", json_object_new_string(as.name.c_str()));
+ json_object_object_add(json_tmp, "role", json_object_new_string(as.role.c_str()));
+ json_object_array_add(json_areas, json_tmp);
+ }
+
+ json_object_object_add(*json_out, "name", json_object_new_string(layer_name));
+ json_object_object_add(*json_out, "changed", json_object_new_boolean(changed));
+ json_object_object_add(*json_out, "areas", json_areas);
+}
+static void updateLocalState(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;
category_no = ((event_data & STM_MSK_CTG_NO) >> 8) - 1;
area_no = ((event_data & STM_MSK_ARA_NO) >> 16) - 1;
- HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
- stm::gStmEventName[event_no],
- stm::gStmCategoryName[category_no],
- stm::gStmAreaName[area_no]);
-
- // Transition state
- stm::stm_state_t crr_state;
- int ret = stm::stmTransitionState(event_data, &crr_state);
- if (0 > ret) {
- HMI_ERROR("wm:pm", "Error!!");
- 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]);
-#if 1 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // Store previous layers
- pm::g_prv_layers = pm::g_crr_layers;
-
- std::string req_role = pm::g_event_info_list[event_data];
std::string req_evt = std::string(stm::gStmEventName[event_no]);
std::string req_ctg = std::string(stm::gStmCategoryName[category_no]);
std::string req_area = std::string(stm::gStmAreaName[area_no]);
- HMI_DEBUG("wm:pm", "REQ: event:%s role%s category:%s area:%s",
+ std::string req_role = pm::g_req_role_list[event_data];
+ HMI_DEBUG("wm:pm", "REQ: event:%s role:%s category:%s area:%s",
req_evt.c_str(), req_role.c_str(), req_ctg.c_str(), req_area.c_str());
+ // Store previous layers
+ pm::g_prv_layers = pm::g_crr_layers;
+
// Update layers
for (int layer_no = stm::gStmLayerNoMin;
layer_no <= stm::gStmLayerNoMax; layer_no++) {
}
}
+ // Erase role for the event_data from list
+ pm::g_req_role_list.erase(event_data);
+
// Check
for (auto itr : pm::g_crr_layers) {
pm::LayerState ls = itr.second;
HMI_DEBUG("wm:pm", ">>> >>> >>> >>> ROLE:%s", as.role.c_str());
}
}
-#endif // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-
- json_object* json_out = json_object_new_object();
+}
+void createOutputInformation(stm::stm_state_t crr_state, json_object **json_out) {
// Create result
// {
// "parking_brake": {
addStateToJson("parking_brake",
crr_state.parking_brake.is_changed,
stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state],
- &json_out);
+ json_out);
// "accel_pedal": {
// "is_changed": <bool>,
addStateToJson("accel_pedal",
crr_state.accel_pedal.is_changed,
stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state],
- &json_out);
+ json_out);
// "lightstatus_brake": {
// "is_changed": <bool>,
addStateToJson("lightstatus_brake",
crr_state.lightstatus_brake.is_changed,
stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state],
- &json_out);
+ json_out);
// "car": {
// "is_changed": <bool>,
addStateToJson("car",
crr_state.car.is_changed,
stm::gStmCarStateNo2Name[crr_state.car.state],
- &json_out);
+ json_out);
// "lamp": {
// "is_changed": <bool>,
addStateToJson("lamp",
crr_state.lamp.is_changed,
stm::gStmLampStateNo2Name[crr_state.lamp.state],
- &json_out);
+ json_out);
// "restriction_mode": {
// "is_changed": <bool>,
addStateToJson("restriction_mode",
crr_state.restriction_mode.is_changed,
stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
- &json_out);
+ json_out);
+ // Create layout information
+ //
// "layers": [
+ // {
+ // "homescreen": {
+ // "changed": <bool>,
+ // "areas": [
+ // {
+ // "name":<const char*>,
+ // "role":<const char*>
+ // }.
+ // ...
+ // ]
+ // }
+ // },
+ // ...
json_object* json_layer = json_object_new_array();
json_object* json_tmp;
+ 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);
- // {
- // "homescreen": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // }
- // },
- // ]
- // }
- json_tmp = json_object_new_object();
- addStateToJson("homescreen",
- crr_state.layer[stm::gStmLayerNoHomescreen].is_changed,
-#if 1
- pm::g_crr_layers["homescreen"].layout_state.name.c_str(),
-#else
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state],
-#endif
- &json_tmp);
- json_object_array_add(json_layer, json_tmp);
-
- // {
- // "apps": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // }
- // },
- json_tmp = json_object_new_object();
- addStateToJson("apps",
- crr_state.layer[stm::gStmLayerNoApps].is_changed,
-#if 1
- pm::g_crr_layers["apps"].layout_state.name.c_str(),
-#else
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoApps].state],
-#endif
- &json_tmp);
- json_object_array_add(json_layer, json_tmp);
-
- // {
- // "restriction": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // }
- // },
- json_tmp = json_object_new_object();
- addStateToJson("restriction",
- crr_state.layer[stm::gStmLayerNoRestriction].is_changed,
-#if 1
- pm::g_crr_layers["restriction"].layout_state.name.c_str(),
-#else
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoRestriction].state],
-#endif
- &json_tmp);
- json_object_array_add(json_layer, json_tmp);
-
- // {
- // "on_screen": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // }
- // },
- json_tmp = json_object_new_object();
- addStateToJson("on_screen",
- crr_state.layer[stm::gStmLayerNoOnScreen].is_changed,
-#if 1
- pm::g_crr_layers["on_screen"].layout_state.name.c_str(),
-#else
- stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoOnScreen].state],
-#endif
- &json_tmp);
- json_object_array_add(json_layer, json_tmp);
+ json_tmp = json_object_new_object();
+ addStateToJson(layer_name,
+ crr_state.layer[layer_no].is_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);
+ json_object_object_add(*json_out, "layers", json_layer);
+}
+
+static int checkPolicyEntry(int event, uint64_t delay_ms, std::string role);
+static int checkPolicy(sd_event_source *source, void *data) {
+ HMI_DEBUG("wm:pm", "Call");
+ HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
+
+ int event_data = *((int*)data);
+
+ int event_no, category_no, area_no;
+ event_no = (event_data & STM_MSK_EVT_NO) - 1;
+ category_no = ((event_data & STM_MSK_CTG_NO) >> 8) - 1;
+ area_no = ((event_data & STM_MSK_ARA_NO) >> 16) - 1;
+ HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
+ stm::gStmEventName[event_no],
+ stm::gStmCategoryName[category_no],
+ stm::gStmAreaName[area_no]);
+
+ // Transition state
+ stm::stm_state_t crr_state;
+ int ret = stm::stmTransitionState(event_data, &crr_state);
+ if (0 > ret) {
+ HMI_ERROR("wm:pm", "Failed transition state");
+ if (nullptr != pm::callback.onError) {
+ json_object* json_out = json_object_new_object();
+ json_object_object_add(json_out, "message",
+ json_object_new_string("Failed to transition state"));
+ json_object_object_add(json_out, "event",
+ json_object_new_string(stm::gStmEventName[event_no]));
+ json_object_object_add(json_out, "role",
+ json_object_new_string(pm::g_req_role_list[event_data].c_str()));
+ json_object_object_add(json_out, "area",
+ json_object_new_string(stm::gStmAreaName[area_no]));
+ pm::callback.onError(json_out);
+ json_object_put(json_out);
+ }
+ 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);
+
+ // Create output information for ResourceManager
+ json_object* json_out = json_object_new_object();
+ createOutputInformation(crr_state, &json_out);
// Notify state is changed
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, nullptr);
+ 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, nullptr);
+ 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)
}
static int timerEvent(sd_event_source *source, uint64_t usec, void *data) {
+ HMI_DEBUG("wm:pm", "Call");
+
int ret = checkPolicy(source, data);
return ret;
-};
+}
-static int checkPolicyEntry(int event, uint64_t delay_ms, const char* role)
+static int checkPolicyEntry(int event, uint64_t delay_ms, std::string role)
{
HMI_DEBUG("wm:pm", "Call");
- HMI_DEBUG("wm:pm", "event:0x%x", event);
+ HMI_DEBUG("wm:pm", "event:0x%x delay:%d role:%s", event, delay_ms, role.c_str());
- // Store event info
- if (nullptr == role) {
- pm::g_event_info_list[event] = std::string("");
- }
- else {
- pm::g_event_info_list[event] = std::string(role);
- }
+ // Store requested role
+ pm::g_req_role_list[event] = role;
if (0 == delay_ms) {
int ret = sd_event_add_defer(pm::event_loop, NULL,
&checkPolicy, new int(event));
if (0 > ret) {
HMI_ERROR("wm:pm", "Faild to sd_event_add_defer: errno:%d", ret);
- pm::g_event_info_list.erase(event);
+ pm::g_req_role_list.erase(event);
return -1;
}
}
&timerEvent, new int(event));
if (0 > ret) {
HMI_ERROR("wm:pm", "Faild to sd_event_add_time: errno:%d", ret);
- pm::g_event_info_list.erase(event);
+ pm::g_req_role_list.erase(event);
return -1;
}
}
void PolicyManager::registerCallback(CallbackTable callback) {
+ HMI_DEBUG("wm:pm", "Call");
+
pm::callback.onStateTransitioned = callback.onStateTransitioned;
pm::callback.onError = callback.onError;
}
-int PolicyManager::inputEvent(json_object* json_in) {
+int PolicyManager::setInputEventData(json_object* json_in) {
HMI_DEBUG("wm:pm", "Call");
// Check arguments
HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
}
- // Check policy
- checkPolicyEntry((event_no | category_no | area_no), 0, role);
+ // Set event info to the queue
+ pm::EventInfo event_info;
+ event_info.event = (event_no | category_no | area_no);
+ if (nullptr == role) {
+ event_info.role = std::string("");
+ }
+ else {
+ event_info.role = std::string(role);
+ }
+ event_info.delay = 0;
+ pm::g_event_info_queue.push(event_info);
return 0;
}
-std::string PolicyManager::roleToCategory(const char* role) {
- return this->role2category_[role];
+int PolicyManager::executeStateTransition() {
+ HMI_DEBUG("wm:pm", "Call");
+
+ int ret;
+ pm::EventInfo event_info;
+
+ while (!pm::g_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();
+
+ // Set event info for checking policy
+ ret = checkPolicyEntry(event_info.event, event_info.delay, event_info.role);
+ }
+ return ret;
+}
+
+void PolicyManager::undoState() {
+ HMI_DEBUG("wm:pm", "Call");
+
+ // Undo state of STM
+ stm::stmUndoState();
+
+ pm::g_crr_layers = pm::g_prv_layers;
}
extern const char* kDefaultRoleDb;
HMI_DEBUG("wm:pm", ">>> >>> area :%s", itr_area->name.c_str());
HMI_DEBUG("wm:pm", ">>> >>> category:%s", itr_area->category.c_str());
HMI_DEBUG("wm:pm", ">>> >>> role :%s", itr_area->role.c_str());
-#if 0
- for (auto itr_role = itr_area->second.begin();
- itr_role != itr_area->second.end(); ++itr_role) {
- HMI_DEBUG("wm:pm", ">>> >>> >>> attribute:%s, name:%s",
- itr_role->first.c_str(), itr_role->second.c_str());
- }
-#endif
}
}