2 * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <systemd/sd-event.h>
24 #include <json-c/json.h>
25 #include "policy_manager.hpp"
26 #include "hmi-debug.h"
30 #include "dummy_stm.h"
37 struct sd_event* event_loop;
38 struct sd_event_source* event_source;
43 PolicyManager::Handler handler;
46 std::map<int, EventData> event_data_list;
50 PolicyManager::PolicyManager() :
58 HMI_DEBUG("wm:pm", "Call");
61 int PolicyManager::initialize() {
62 HMI_DEBUG("wm:pm", "Call");
67 for (unsigned int i=0; i<STM_NUM_EVT; i++) {
68 HMI_DEBUG("wm:pm", "event name:%s no:%d", stm::gStmEventName[i], stm::gStmEventNo[i]);
69 this->eventname2no_[stm::gStmEventName[i]] = stm::gStmEventNo[i];
72 for (unsigned int i=0; i<STM_NUM_CTG; i++) {
73 HMI_DEBUG("wm:pm", "category name:%s no:%d", stm::gStmCategoryName[i], stm::gStmCategoryNo[i]);
74 this->categoryname2no_[stm::gStmCategoryName[i]] = stm::gStmCategoryNo[i];
77 for (unsigned int i=0; i<STM_NUM_ARA; i++) {
78 HMI_DEBUG("wm:pm", "area name:%s no:%d", stm::gStmAreaName[i], stm::gStmAreaNo[i]);
79 this->areaname2no_[stm::gStmAreaName[i]] = stm::gStmAreaNo[i];
83 ret = this->loadRoleDb();
85 HMI_ERROR("wm:pm", "Load role.db Error!!");
89 // Initialize StateTransitioner
92 // Initialize sd_event loop
93 ret = this->initializeSdEventLoop();
95 HMI_ERROR("wm:pm", "Failed to initializeSdEventLoop!!");
102 int PolicyManager::initializeSdEventLoop() {
103 // Get default event loop object
104 int ret = sd_event_new(&(pm::event_loop));
106 HMI_ERROR("wm:pm", "Faild to sd_event_default: errno:%d", ret);
110 // Create thread for sd_event and detach
111 std::thread sd_event_loop([this]() {
113 sd_event_run(pm::event_loop, 1000);
116 sd_event_loop.detach();
121 static void addStateToJson(
122 const char* key, int is_changed, const char* state, json_object** json_out) {
123 if ((nullptr == key) || (nullptr == state) || (nullptr == json_out)) {
124 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
128 json_object* json_obj = json_object_new_object();
129 json_object_object_add(json_obj, "is_changed", json_object_new_boolean(is_changed));
131 HMI_DEBUG("wm:pm", "%s: state changed (%s)", key, state);
132 json_object_object_add(json_obj, "state", json_object_new_string(state));
134 json_object_object_add(*json_out, key, json_obj);
137 static int checkPolicyEntry(PolicyManager* ctx, int event, uint64_t delay_ms,
138 PolicyManager::Handler handler);
139 static int checkPolicy(sd_event_source *source, void *data) {
140 HMI_DEBUG("wm:pm", "Call");
141 HMI_DEBUG("wm:pm", ">>>>>>>>>> START CHECK POLICY");
143 int event = *((int*)data);
145 pm::EventData event_data;
146 if (pm::event_data_list.find(event) != pm::event_data_list.end()) {
147 event_data = pm::event_data_list[event];
149 int event_no, category_no, area_no;
150 event_no = event & STM_MSK_EVT_NO;
151 category_no = event & STM_MSK_CTG_NO;
152 area_no = event & STM_MSK_ARA_NO;
153 HMI_DEBUG("wm:pm", ">>>>>>>>>> event:%s category:%s area:%s",
154 stm::gStmEventName[event_no - 1],
155 stm::gStmCategoryName[(category_no >> 8) - 1],
156 stm::gStmAreaName[(area_no >> 16) - 1]);
159 stm::stm_state_t crr_state;
160 int ret = stm::stmTransitionState(event_data.event, &crr_state);
162 HMI_ERROR("wm:pm", "Error!!");
166 HMI_DEBUG("wm:pm", "parking brake state (is_changed:%d state:%d:%s)",
167 crr_state.parking_brake.is_changed,
168 crr_state.parking_brake.state,
169 stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state]);
170 HMI_DEBUG("wm:pm", "accelerator pedal state (is_changed:%d state:%d:%s)",
171 crr_state.accel_pedal.is_changed,
172 crr_state.accel_pedal.state,
173 stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state]);
174 HMI_DEBUG("wm:pm", "lightstatus brake state (is_changed:%d state:%d:%s)",
175 crr_state.lightstatus_brake.is_changed,
176 crr_state.lightstatus_brake.state,
177 stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state]);
178 HMI_DEBUG("wm:pm", "car state (is_changed:%d state:%d:%s)",
179 crr_state.car.is_changed,
181 stm::gStmCarStateNo2Name[crr_state.car.state]);
182 HMI_DEBUG("wm:pm", "lamp state (is_changed:%d state:%d:%s)",
183 crr_state.lamp.is_changed,
184 crr_state.lamp.state,
185 stm::gStmLampStateNo2Name[crr_state.lamp.state]);
186 HMI_DEBUG("wm:pm", "restriction mode state (is_changed:%d state:%d:%s)",
187 crr_state.restriction_mode.is_changed,
188 crr_state.restriction_mode.state,
189 stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state]);
190 HMI_DEBUG("wm:pm", "homescreen state (is_changed:%d state:%d:%s)",
191 crr_state.layer.homescreen.is_changed,
192 crr_state.layer.homescreen.state,
193 stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state]);
194 HMI_DEBUG("wm:pm", "apps state (is_changed:%d state:%d:%s)",
195 crr_state.layer.apps.is_changed,
196 crr_state.layer.apps.state,
197 stm::gStmLayoutNo2Name[crr_state.layer.apps.state]);
198 HMI_DEBUG("wm:pm", "restriction state (is_changed:%d state:%d:%s)",
199 crr_state.layer.restriction.is_changed,
200 crr_state.layer.restriction.state,
201 stm::gStmLayoutNo2Name[crr_state.layer.restriction.state]);
202 HMI_DEBUG("wm:pm", "on_screen state (is_changed:%d state:%d:%s)",
203 crr_state.layer.on_screen.is_changed,
204 crr_state.layer.on_screen.state,
205 stm::gStmLayoutNo2Name[crr_state.layer.on_screen.state]);
207 json_object* json_out = json_object_new_object();
211 // "parking_brake": {
212 // "is_changed": <bool>,
213 // "state": <const char*>
215 addStateToJson("parking_brake",
216 crr_state.parking_brake.is_changed,
217 stm::gStmParkingBrakeStateNo2Name[crr_state.parking_brake.state],
221 // "is_changed": <bool>,
222 // "state": <const char*>
224 addStateToJson("accel_pedal",
225 crr_state.accel_pedal.is_changed,
226 stm::gStmAccelPedalStateNo2Name[crr_state.accel_pedal.state],
229 // "lightstatus_brake": {
230 // "is_changed": <bool>,
231 // "state": <const char*>
233 addStateToJson("lightstatus_brake",
234 crr_state.lightstatus_brake.is_changed,
235 stm::gStmLightstatusBrakeStateNo2Name[crr_state.lightstatus_brake.state],
239 // "is_changed": <bool>,
240 // "state": <const char*>
242 addStateToJson("car",
243 crr_state.car.is_changed,
244 stm::gStmCarStateNo2Name[crr_state.car.state],
248 // "is_changed": <bool>,
249 // "state": <const char*>
251 addStateToJson("lamp",
252 crr_state.lamp.is_changed,
253 stm::gStmLampStateNo2Name[crr_state.lamp.state],
256 // "restriction_mode": {
257 // "is_changed": <bool>,
258 // "state": <const char*>
260 addStateToJson("restriction_mode",
261 crr_state.restriction_mode.is_changed,
262 stm::gStmRestrictionModeStateNo2Name[crr_state.restriction_mode.state],
266 json_object* json_layer = json_object_new_array();
267 json_object* json_tmp;
271 // "is_changed": <bool>,
272 // "state": <const char*>
277 json_tmp = json_object_new_object();
278 addStateToJson("homescreen",
279 crr_state.layer.homescreen.is_changed,
280 stm::gStmLayoutNo2Name[crr_state.layer.homescreen.state],
282 json_object_array_add(json_layer, json_tmp);
286 // "is_changed": <bool>,
287 // "state": <const char*>
290 json_tmp = json_object_new_object();
291 addStateToJson("apps",
292 crr_state.layer.apps.is_changed,
293 stm::gStmLayoutNo2Name[crr_state.layer.apps.state],
295 json_object_array_add(json_layer, json_tmp);
299 // "is_changed": <bool>,
300 // "state": <const char*>
303 json_tmp = json_object_new_object();
304 addStateToJson("restriction",
305 crr_state.layer.restriction.is_changed,
306 stm::gStmLayoutNo2Name[crr_state.layer.restriction.state],
308 json_object_array_add(json_layer, json_tmp);
312 // "is_changed": <bool>,
313 // "state": <const char*>
316 json_tmp = json_object_new_object();
317 addStateToJson("on_screen",
318 crr_state.layer.on_screen.is_changed,
319 stm::gStmLayoutNo2Name[crr_state.layer.on_screen.state],
321 json_object_array_add(json_layer, json_tmp);
323 // Add json array of layer
324 json_object_object_add(json_out, "layers", json_layer);
326 // Call event handler
327 event_data.handler(json_out);
329 if (crr_state.car.is_changed) {
330 // Set delay event(restriction mode on) when car state is chaged stop -> run
331 if (stm::gStmCarStateNoRun == crr_state.car.state) {
332 checkPolicyEntry(event_data.ctx, STM_EVT_NO_RESTRICTION_MODE_ON,
333 3000, event_data.handler);
335 else if (stm::gStmCarStateNoStop == crr_state.car.state) {
336 checkPolicyEntry(event_data.ctx, STM_EVT_NO_RESTRICTION_MODE_OFF,
337 0, event_data.handler);
341 // Release json_object
342 json_object_put(json_out);
346 HMI_DEBUG("wm:pm", "Request for event:%d is removed", event);
352 // Destroy sd_event_soutce object
353 sd_event_source_unref(source);
355 HMI_DEBUG("wm:pm", ">>>>>>>>>> FINISH CHECK POLICY");
359 static int timerEvent(sd_event_source *source, uint64_t usec, void *data) {
360 checkPolicy(source, data);
363 static int checkPolicyEntry(PolicyManager* ctx, int event, uint64_t delay_ms,
364 PolicyManager::Handler handler)
366 HMI_DEBUG("wm:pm", "Call");
367 HMI_DEBUG("wm:pm", "event:0x%x", event);
369 // If event is restriction off and there is restriction on event,
370 // remove restriction on event
371 if ((STM_EVT_NO_RESTRICTION_MODE_OFF == event)
372 && (pm::event_data_list.find(event) != pm::event_data_list.end())) {
373 HMI_DEBUG("wm:pm", "Remove event: restriction on");
374 pm::event_data_list.erase(STM_EVT_NO_RESTRICTION_MODE_ON);
378 pm::EventData event_data;
379 event_data.ctx = ctx;
380 event_data.event = event;
381 event_data.handler = handler;
382 pm::event_data_list[event] = event_data;
385 int ret = sd_event_add_defer(pm::event_loop, NULL,
386 &checkPolicy, new int(event));
388 HMI_ERROR("wm:pm", "Faild to sd_event_add_defer: errno:%d", ret);
394 struct timespec time_spec;
395 clock_gettime(CLOCK_MONOTONIC, &time_spec);
397 // Calculate timer fired time
398 uint64_t usec = (time_spec.tv_sec * 1000000)
399 + (time_spec.tv_nsec / 1000)
403 int ret = sd_event_add_time(pm::event_loop, NULL, CLOCK_MONOTONIC, usec, 1,
404 &timerEvent, new int(event));
406 HMI_ERROR("wm:pm", "Faild to sd_event_add_time: errno:%d", ret);
414 int PolicyManager::inputEvent(json_object* json_in, PolicyManager::Handler notify_state) {
415 HMI_DEBUG("wm:pm", "Call");
418 if (nullptr == json_in) {
419 HMI_ERROR("wm:pm", "Argument is NULL!!");
423 // Get event from json_object
424 const char* event = this->getStringFromJson(json_in, "event");
426 if (nullptr != event) {
427 // Convert name to number
428 event_no = this->eventname2no_[event];
429 HMI_DEBUG("wm:pm", "event(%s:%d)", event, event_no);
432 // Get role from json_object
433 const char* role = this->getStringFromJson(json_in, "role");
435 if (nullptr != role) {
436 HMI_DEBUG("wm:pm", "role(%s)", role);
438 // Convert role to category
439 const char* category = this->role2category_[role].c_str();
440 if (0 == strcmp("", category)) {
441 HMI_ERROR("wm:pm", "Error!!");
444 HMI_DEBUG("wm:pm", "category(%s)", category);
446 // Convert name to number
447 category_no = categoryname2no_[category];
448 HMI_DEBUG("wm:pm", "role(%s), category(%s:%d)", role, category, category_no);
451 // Get areat from json_object
452 const char* area = this->getStringFromJson(json_in, "area");
454 if (nullptr != area) {
455 // Convert name to number
456 area_no = areaname2no_[area];
457 HMI_DEBUG("wm:pm", "area(%s:%d)", area, area_no);
461 checkPolicyEntry(this, (event_no | category_no | area_no), 0, notify_state);
466 std::string PolicyManager::roleToCategory(const char* role) {
467 return this->role2category_[role];
470 extern const char* kDefaultRoleDb;
471 int PolicyManager::loadRoleDb() {
472 HMI_DEBUG("wm:pm", "Call");
474 std::string file_name;
476 // Get afm application installed dir
477 char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
478 HMI_DEBUG("wm:pm", "afm_app_install_dir:%s", afm_app_install_dir);
480 if (!afm_app_install_dir) {
481 HMI_ERROR("wm:pm", "AFM_APP_INSTALL_DIR is not defined");
484 file_name = std::string(afm_app_install_dir) + std::string("/etc/role.db");
488 json_object* json_obj;
489 int ret = this->inputJsonFilie(file_name.c_str(), &json_obj);
491 HMI_ERROR("wm:pm", "Could not open role.db, so use default role information");
492 json_obj = json_tokener_parse(kDefaultRoleDb);
494 HMI_DEBUG("wm:pm", "json_obj dump:%s", json_object_get_string(json_obj));
496 json_object* json_roles;
497 if (!json_object_object_get_ex(json_obj, "roles", &json_roles)) {
498 HMI_ERROR("wm:pm", "Parse Error!!");
502 int len = json_object_array_length(json_roles);
503 HMI_DEBUG("wm:pm", "json_cfg len:%d", len);
504 HMI_DEBUG("wm:pm", "json_cfg dump:%s", json_object_get_string(json_roles));
506 json_object* json_tmp;
507 const char* category;
510 for (int i=0; i<len; i++) {
511 json_tmp = json_object_array_get_idx(json_roles, i);
513 category = this->getStringFromJson(json_tmp, "category");
514 roles = this->getStringFromJson(json_tmp, "role");
515 areas = this->getStringFromJson(json_tmp, "area");
517 if ((nullptr == category) || (nullptr == roles) || (nullptr == areas)) {
518 HMI_ERROR("wm:pm", "Parse Error!!");
522 // Parse roles by '|'
523 std::vector<std::string> vct_roles;
524 vct_roles = this->parseString(std::string(roles), '|');
526 // Parse areas by '|'
527 std::vector<std::string> vct_areas;
528 vct_areas = this->parseString(std::string(areas), '|');
530 // Set role, category, default area
531 for (auto itr = vct_roles.begin(); itr != vct_roles.end(); ++itr) {
532 // Delete space from role and area name
533 std::string role = this->deleteSpace(*itr);
534 std::string area = this->deleteSpace(vct_areas[0]);
536 this->role2category_[role] = std::string(category);
537 this->role2defaultarea_[role] = area;
540 this->category2role_[std::string(category)] = std::string(roles);
544 HMI_DEBUG("wm:pm", "Check role2category_");
545 for (auto& x:this->role2category_){
546 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
549 HMI_DEBUG("wm:pm", "Check role2defaultarea_");
550 for (auto& x:this->role2defaultarea_){
551 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
554 HMI_DEBUG("wm:pm", "Check category2role_");
555 for (auto& x:this->category2role_){
556 HMI_DEBUG("wm:pm", "key:%s, val:%s", x.first.c_str(), x.second.c_str());
563 // This function will be removed because json_helper has same function.
564 // json_helper should be library.
565 const char* PolicyManager::getStringFromJson(json_object* obj, const char* key) {
566 if ((nullptr == obj) || (nullptr == key)) {
567 HMI_ERROR("wm:pm", "Argument is nullptr!!!");
572 if (!json_object_object_get_ex(obj, key, &tmp)) {
573 HMI_DEBUG("wm:pm", "Not found key \"%s\"", key);
577 return json_object_get_string(tmp);
581 // This function will be removed because json_helper has same function.
582 // json_helper should be library.
583 int PolicyManager::inputJsonFilie(const char* file, json_object** obj) {
584 const int input_size = 128;
587 if ((nullptr == file) || (nullptr == obj)) {
588 HMI_ERROR("wm:jh", "Argument is nullptr!!!");
592 HMI_DEBUG("wm:jh", "Input file: %s", file);
595 FILE *fp = fopen(file, "rb");
597 HMI_ERROR("wm:jh", "Could not open file");
602 struct json_tokener *tokener = json_tokener_new();
603 enum json_tokener_error json_error;
604 char buffer[input_size];
607 size_t len = fread(buffer, sizeof(char), input_size, fp);
608 *obj = json_tokener_parse_ex(tokener, buffer, len);
609 if (nullptr != *obj) {
610 HMI_DEBUG("wm:jh", "File input is success");
615 json_error = json_tokener_get_error(tokener);
616 if ((json_tokener_continue != json_error)
617 || (input_size > len)) {
618 HMI_ERROR("wm:jh", "Failed to parse file (byte:%d err:%s)",
619 (input_size * block_cnt), json_tokener_error_desc(json_error));
620 HMI_ERROR("wm:jh", "\n%s", buffer);
631 json_tokener_free(tokener);
636 std::vector<std::string> PolicyManager::parseString(std::string str, char delimiter) {
637 // Parse string by delimiter
638 std::vector<std::string> vct;
639 std::stringstream ss{str};
641 while (std::getline(ss, buf, delimiter)) {
649 std::string PolicyManager::deleteSpace(std::string str) {
650 std::string ret = str;
652 while ((pos = ret.find_first_of(" ")) != std::string::npos) {
658 const char* kDefaultRoleDb = "{ \
661 \"category\": \"homescreen\", \
662 \"role\": \"homescreen\", \
663 \"area\": \"full\", \
666 \"category\": \"map\", \
668 \"area\": \"full | normal | split.main\", \
671 \"category\": \"general\", \
672 \"role\": \"poi | music | video | browser | sdl | settings | mixer | radio | hvac | dashboard | debug\", \
673 \"area\": \"normal\", \
676 \"category\": \"phone\", \
677 \"role\": \"phone\", \
678 \"area\": \"normal\", \
681 \"category\": \"splitable\", \
682 \"role\": \"splitable1 | splitable2\", \
683 \"area\": \"normal | split.main | split.sub\", \
686 \"category\": \"popup\", \
687 \"role\": \"popup\", \
688 \"area\": \"on_screen\", \
691 \"category\": \"system_alert\", \
692 \"role\": \"system_alert\", \
693 \"area\": \"on_screen\", \
696 \"category\": \"tbt\", \