namespace pm {
+typedef std::unordered_map<std::string, std::string> AppAttribute;
+typedef std::unordered_map<std::string, AppAttribute> AreasState;
+typedef std::unordered_map<std::string, AreasState> LayoutState;
+typedef std::unordered_map<std::string, LayoutState> LayersState;
struct sd_event* event_loop;
-struct sd_event_source* event_source;
-
-struct EventData {
- PolicyManager *ctx;
- int event;
- PolicyManager::Handler handler;
-};
-
-std::map<int, EventData> event_data_list;
-
+std::map<int, struct sd_event_source*> event_source_list;
+PolicyManager::CallbackTable callback;
+LayersState g_prv_layers;
+LayersState g_crr_layers;
} // namespace pm
+
PolicyManager::PolicyManager() :
eventname2no_(),
categoryname2no_(),
return ret;
}
+ // Initialize current/previous state of layers
+ pm::AppAttribute init_app;
+ pm::AreasState init_area;
+ pm::LayoutState init_layout;
+ init_app["role"] = "none";
+ init_area["none"] = init_app;
+ init_layout["none"] = init_area;
+
+ pm::g_crr_layers["homescreen"] = init_layout;
+ pm::g_crr_layers["apps"] = init_layout;
+ pm::g_crr_layers["restriction"] = init_layout;
+ pm::g_crr_layers["on_screen"] = init_layout;
+ pm::g_prv_layers = pm::g_crr_layers;
+
// Initialize StateTransitioner
stm::stmInitialize();
json_object_object_add(*json_out, key, json_obj);
}
-static int checkPolicyEntry(PolicyManager* ctx, int event, uint64_t delay_ms,
- PolicyManager::Handler handler);
+static int checkPolicyEntry(int event, uint64_t delay_ms);
static int checkPolicy(sd_event_source *source, void *data) {
HMI_DEBUG("wm:pm", "Call");
HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
int event = *((int*)data);
- pm::EventData event_data;
- if (pm::event_data_list.find(event) != pm::event_data_list.end()) {
- event_data = pm::event_data_list[event];
-
- int event_no, category_no, area_no;
- event_no = event & STM_MSK_EVT_NO;
- category_no = event & STM_MSK_CTG_NO;
- area_no = event & STM_MSK_ARA_NO;
- HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
- stm::gStmEventName[event_no - 1],
- stm::gStmCategoryName[(category_no >> 8) - 1],
- stm::gStmAreaName[(area_no >> 16) - 1]);
-
- // Transition state
- stm::stm_state_t crr_state;
- int ret = stm::stmTransitionState(event_data.event, &crr_state);
- if (0 > ret) {
- HMI_ERROR("wm:pm", "Error!!");
- return -1;
- }
+ int event_no, category_no, area_no;
+ event_no = event & STM_MSK_EVT_NO;
+ category_no = event & STM_MSK_CTG_NO;
+ area_no = event & STM_MSK_ARA_NO;
+ HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
+ stm::gStmEventName[event_no - 1],
+ stm::gStmCategoryName[(category_no >> 8) - 1],
+ stm::gStmAreaName[(area_no >> 16) - 1]);
+
+ // Transition state
+ stm::stm_state_t crr_state;
+ int ret = stm::stmTransitionState(event, &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.homescreen.is_changed,
- crr_state.layer.homescreen.state,
- stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state]);
- HMI_DEBUG("wm:pm", "apps state (is_changed:%d state:%d:%s)",
- crr_state.layer.apps.is_changed,
- crr_state.layer.apps.state,
- stm::gStmLayoutNo2Name[crr_state.layer.apps.state]);
- HMI_DEBUG("wm:pm", "restriction state (is_changed:%d state:%d:%s)",
- crr_state.layer.restriction.is_changed,
- crr_state.layer.restriction.state,
- stm::gStmLayoutNo2Name[crr_state.layer.restriction.state]);
- HMI_DEBUG("wm:pm", "on_screen state (is_changed:%d state:%d:%s)",
- crr_state.layer.on_screen.is_changed,
- crr_state.layer.on_screen.state,
- stm::gStmLayoutNo2Name[crr_state.layer.on_screen.state]);
-
- json_object* json_out = json_object_new_object();
-
- // Create result
- // {
- // "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*>
- // },
- addStateToJson("restriction_mode",
- crr_state.restriction_mode.is_changed,
- stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
- &json_out);
-
- // "layers": [
- json_object* json_layer = json_object_new_array();
- json_object* json_tmp;
-
- // {
- // "homescreen": {
- // "is_changed": <bool>,
- // "state": <const char*>
- // }
- // },
- // ]
- // }
- json_tmp = json_object_new_object();
- addStateToJson("homescreen",
- crr_state.layer.homescreen.is_changed,
- stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state],
- &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.apps.is_changed,
- stm::gStmLayoutNo2Name[crr_state.layer.apps.state],
- &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.restriction.is_changed,
- stm::gStmLayoutNo2Name[crr_state.layer.restriction.state],
- &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.on_screen.is_changed,
- stm::gStmLayoutNo2Name[crr_state.layer.on_screen.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);
-
- // Call event handler
- event_data.handler(json_out);
-
- if (crr_state.car.is_changed) {
- // Set delay event(restriction mode on) when car state is chaged stop -> run
- if (stm::gStmCarStateNoRun == crr_state.car.state) {
- checkPolicyEntry(event_data.ctx, STM_EVT_NO_RESTRICTION_MODE_ON,
- 3000, event_data.handler);
+ 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 0 // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ // Store previous layers
+ pm::g_prv_layers = pm::g_crr_layers;
+
+ std::string layer_name = "homescreen";
+
+ // changed?
+ if (crr_state.layer[stm::gStmLayerNoHomescreen].is_changed) {
+ // Get previous layout name of this layer
+ pm::LayoutState prv_layout_state = pm::g_prv_layers[layer_name];
+ std::string prv_layout_name = prv_homescreen_layout_state.first();
+
+ // Get current layout name of this layer
+ std::string crr_layout_name = std::string(stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state]);
+
+ // Compare layout name
+ pm::LayoutState crr_layout_state;
+ if ("none" == crr_layout_name) {
+ // If current layout is "none",
+ // current areas is set with "none"
+ HMI_DEBUG("wm:pm", "Current layout is \"none\"");
+ HMI_DEBUG("wm:lm", "Current layout is \"none\"");
+ pm::AppAttribute crr_app_attribute;
+ pm::AreasState crr_areas_state;
+ crr_app_attribute["role"] = "none";
+ crr_areas_state["none"] = "none";
+ crr_layout_state["none"] = crr_areas_state;
+ }
+ else {
+ if (prv_layout_name == crr_layout_name) {
+ // If previous layout is same with current,
+ // previous areas are copied to current
+ crr_layout_state[crr_layout_name] = pm::g_prv_layers[layer_name][crr_layout_name];
+ }
+ else {
+ // If previous layout is same with current,
+ // previous areas are copied to current
+ crr_layout_state[crr_layout_name] = this->default_layout_state[crr_layout_name];
}
- else if (stm::gStmCarStateNoStop == crr_state.car.state) {
- checkPolicyEntry(event_data.ctx, STM_EVT_NO_RESTRICTION_MODE_OFF,
- 0, event_data.handler);
+
+ // Update role in new area
+#if 1
+ if (crr_state.restriction_mode.is_changed) {
+ // Updating role is not necessary
+ // because new_role is not specified
+ // when restriction mode is changed
+ HMI_DEBUG("wm:lm", "Updating role is not necessary because new_role is not specified when restriction mode is changed");
+#else
+ if (crr_state.car.is_changed) {
+ // Updating role is not necessary
+ // because new_role is not specified
+ // when car state is changed
+ HMI_DEBUG("wm:lm", "Updating role is not necessary because new_role is not specified when car state is changed");
+#endif
+ }
+ else {
+ HMI_DEBUG("wm:lm", "Get new_area for new role");
+ // Get new_area for new role
+ std::string new_area = this->getAreaName(this->layout_define_[crr_layout_name],
+ new_role, category);
+
+ if ("none" == new_area) {
+ HMI_DEBUG("wm:lm", "It is not necessary to update role of areas in this layer, because new_role is not specified for this layer");
+ }
+ else {
+ // Is there new_area?
+ // if there is new_area, set new role there
+
+ // if NOT, find same category of new_role
+ // pop old role and shift area
+ // push new role and set area
+
+
+ // Update role in new area
+ // because new_role is specified for this layer
+ TypeRolCtg crr_role;
+ crr_role["role"] = std::string(new_role);
+ crr_layout[crr_layout_name][new_area] = crr_role;
+ }
+ }
}
}
- // Release json_object
- json_object_put(json_out);
+ // Update current layout of this layer
+ pm::g_crr_layers[layer_name] = crr_layout_state;
+
+ }
+#endif // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ json_object* json_out = json_object_new_object();
+
+ // Create result
+ // {
+ // "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*>
+ // },
+ addStateToJson("restriction_mode",
+ crr_state.restriction_mode.is_changed,
+ stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
+ &json_out);
+
+ // "layers": [
+ json_object* json_layer = json_object_new_array();
+ json_object* json_tmp;
+ // {
+ // "homescreen": {
+ // "is_changed": <bool>,
+ // "state": <const char*>
+ // }
+ // },
+ // ]
+ // }
+ json_tmp = json_object_new_object();
+ addStateToJson("homescreen",
+ crr_state.layer[stm::gStmLayerNoHomescreen].is_changed,
+ stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoHomescreen].state],
+ &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,
+ stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoApps].state],
+ &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,
+ stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoRestriction].state],
+ &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,
+ stm::gStmLayoutNo2Name[crr_state.layer[stm::gStmLayerNoOnScreen].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);
+
+ // Notify state is changed
+ if (nullptr != pm::callback.onStateTransitioned) {
+ pm::callback.onStateTransitioned(json_out);
+ }
+
+ 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");
+ }
+ }
+ }
}
- else {
- HMI_DEBUG("wm:pm", "Request for event:%d is removed", event);
- }
+
+ // Release json_object
+ json_object_put(json_out);
// Release data
delete (int*)data;
- // Destroy sd_event_soutce object
+ // Destroy sd_event_source object
sd_event_source_unref(source);
+ // Remove event source from list
+ if (pm::event_source_list.find(event) != pm::event_source_list.end()) {
+ pm::event_source_list.erase(event);
+ }
+
HMI_DEBUG("wm:pm", ">>>>>>>>>> FINISH CHECK POLICY");
return 0;
}
checkPolicy(source, data);
};
-static int checkPolicyEntry(PolicyManager* ctx, int event, uint64_t delay_ms,
- PolicyManager::Handler handler)
+static int checkPolicyEntry(int event, uint64_t delay_ms)
{
HMI_DEBUG("wm:pm", "Call");
HMI_DEBUG("wm:pm", "event:0x%x", event);
- // If event is restriction off and there is restriction on event,
- // remove restriction on event
- if ((STM_EVT_NO_RESTRICTION_MODE_OFF == event)
- && (pm::event_data_list.find(event) != pm::event_data_list.end())) {
- HMI_DEBUG("wm:pm", "Remove event: restriction on");
- pm::event_data_list.erase(STM_EVT_NO_RESTRICTION_MODE_ON);
- }
-
- // Create event data
- pm::EventData event_data;
- event_data.ctx = ctx;
- event_data.event = event;
- event_data.handler = handler;
- pm::event_data_list[event] = event_data;
-
if (0 == delay_ms) {
int ret = sd_event_add_defer(pm::event_loop, NULL,
&checkPolicy, new int(event));
+ (delay_ms * 1000);
// Set timer
- int ret = sd_event_add_time(pm::event_loop, NULL, CLOCK_MONOTONIC, usec, 1,
+ struct sd_event_source* event_source;
+ int ret = sd_event_add_time(pm::event_loop, &event_source, CLOCK_MONOTONIC, usec, 1,
&timerEvent, new int(event));
if (0 > ret) {
HMI_ERROR("wm:pm", "Faild to sd_event_add_time: errno:%d", ret);
return -1;
}
+
+ // Store event source
+ pm::event_source_list[event] = event_source;
}
return 0;
}
-int PolicyManager::inputEvent(json_object* json_in, PolicyManager::Handler notify_state) {
+void PolicyManager::registerCallback(CallbackTable callback) {
+ pm::callback.onStateTransitioned = callback.onStateTransitioned;
+ pm::callback.onError = callback.onError;
+}
+
+int PolicyManager::inputEvent(json_object* json_in) {
HMI_DEBUG("wm:pm", "Call");
// Check arguments
}
// Check policy
- checkPolicyEntry(this, (event_no | category_no | area_no), 0, notify_state);
+ checkPolicyEntry((event_no | category_no | area_no), 0);
return 0;
}