pmqos: Convert pass-pmqos.conf format to json to improve readability 55/261955/5
authorChanwoo Choi <cw00.choi@samsung.com>
Thu, 29 Jul 2021 12:38:13 +0000 (21:38 +0900)
committerChanwoo Choi <cw00.choi@samsung.com>
Fri, 30 Jul 2021 04:27:29 +0000 (13:27 +0900)
The legacy pass-pmqos.conf file format is not better on side of readability.
So that change the configuration file format to json style to improve
readability.

Change-Id: I4898d431b1d0f8bc3b50b1d1ea764c87992cdf6c
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
CMakeLists.txt
include/pass/common.h
packaging/pass.spec
scripts/pass-pmqos.conf [deleted file]
scripts/pass-pmqos.json [new file with mode: 0644]
src/core/common.c
src/pmqos/pmqos-parser.c
src/pmqos/pmqos.c
unittest/CMakeLists.txt

index 9f5c08a..6bd9240 100644 (file)
@@ -50,6 +50,7 @@ SET(PKG_MODULES
        gio-unix-2.0
        libudev
        libsystemd
+       json-c
        hal-api-power
 )
 
@@ -97,7 +98,7 @@ ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -ldl -lm)
 INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/${PROJECT_NAME}.conf DESTINATION /etc/dbus-1/system.d)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.conf DESTINATION /etc/pass)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-pmqos.json DESTINATION /etc/pass)
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/pass-thermal.conf DESTINATION /etc/pass)
 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service.in ${CMAKE_SOURCE_DIR}/systemd/${PROJECT_NAME}.service @ONLY)
 INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.pass.service DESTINATION /usr/share/dbus-1/system-services)
index 3bef731..851212c 100644 (file)
@@ -26,6 +26,9 @@
 #include <stdbool.h>
 #include <unistd.h>
 
+#include <json-c/json.h>
+#include <json-c/arraylist.h>
+
 typedef unsigned int uint32;
 typedef unsigned long long uint64;
 
@@ -90,6 +93,11 @@ typedef unsigned long long uint64;
 #define USEC_TO_MSEC(x)                ((double)x/1000)
 #endif
 
-int sys_get_str(char *fname, char *str);
-int sys_strtol(char *str);
+int sys_get_str(const char *fname, char *str);
+int sys_strtol(const char *str);
+
+const char *get_string_from_object(json_object *obj, const char *key);
+const int get_int_from_object(json_object *obj, const char *key);
+const double get_double_from_object(json_object *obj, const char *key);
+const int get_boolean_from_object(json_object *obj, const char *key);
 #endif /* __CORE_COMMON_H__ */
index 6f2f77d..b1fd8a0 100644 (file)
@@ -22,6 +22,7 @@ BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(gmock)
 BuildRequires:  pkgconfig(libudev)
 BuildRequires:  pkgconfig(libsystemd)
+BuildRequires:  pkgconfig(json-c)
 BuildRequires:  pkgconfig(hal-api-power)
 
 %description
@@ -89,7 +90,7 @@ systemctl daemon-reload
 %manifest %{name}.manifest
 %license LICENSE
 %config %{_sysconfdir}/dbus-1/system.d/%{daemon_name}.conf
-%config %{_sysconfdir}/pass/pass-pmqos.conf
+%config %{_sysconfdir}/pass/pass-pmqos.json
 %config %{_sysconfdir}/pass/pass-thermal.conf
 %{_bindir}/%{daemon_name}
 %{_unitdir}/delayed.target.wants/%{daemon_name}.service
diff --git a/scripts/pass-pmqos.conf b/scripts/pass-pmqos.conf
deleted file mode 100644 (file)
index 4a4259a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-[PassScenario]
-# set to "yes" scenario_support (Default value is no)
-# set scenario_num to be tested
-scenario_support=yes
-scenario_num=6
-
-# describe the scenario section as follows
-#[Scenario0]
-#[Mandatory properties]
-#      name=AppLaunch # (dbus method name)
-#      support=yes
-#[Optional properties]
-#      max_duration_ms=3000 # (unit:millisecond, max dururation is 3000ms)
-[Scenario0]
-name=AppLaunch
-max_duration_ms=3000
-support=yes
-
-[Scenario1]
-name=UltraPowerSaving
-support=yes
-
-[Scenario2]
-name=Doze
-support=yes
-
-[Scenario3]
-name=AppLaunchHome
-max_duration_ms=3000
-support=yes
-
-[Scenario4]
-name=HomeScreen
-max_duration_ms=3000
-support=yes
-
-[Scenario5]
-name=Performance
-support=yes
diff --git a/scripts/pass-pmqos.json b/scripts/pass-pmqos.json
new file mode 100644 (file)
index 0000000..34f1032
--- /dev/null
@@ -0,0 +1,24 @@
+{
+       "pmqos_support"         : true,
+       "pmqos_scenario_list"   :
+       [
+               {
+                       "name"                  : "AppLaunch",
+                       "max_duration_ms"       : 3000,
+                       "support"               : true
+               }, {
+                       "name"                  : "AppLaunchHome",
+                       "max_duration_ms"       : 3000,
+                       "support"               : true
+               }, {
+                       "name"                  : "UltraPowerSaving",
+                       "support"               : true
+               }, {
+                       "name"                  : "Doze",
+                       "support"               : true
+               }, {
+                       "name"                  : "Performance",
+                       "support"               : true
+               }
+       ]
+}
index bf1a81b..66fe952 100644 (file)
@@ -40,7 +40,7 @@
 
 #define BUFF_MAX       255
 
-static int sys_read_buf(char *file, char *buf)
+static int sys_read_buf(const char *file, char *buf)
 {
        int fd;
        int r;
@@ -61,7 +61,7 @@ static int sys_read_buf(char *file, char *buf)
        return ret;
 }
 
-int sys_get_str(char *fname, char *str)
+int sys_get_str(const char *fname, char *str)
 {
        char buf[BUFF_MAX] = {0};
 
@@ -73,7 +73,7 @@ int sys_get_str(char *fname, char *str)
        return -1;
 }
 
-int sys_strtol(char *str)
+int sys_strtol(const char *str)
 {
        long value;
 
@@ -83,3 +83,43 @@ int sys_strtol(char *str)
 
        return (int)value;
 }
+
+const char *get_string_from_object(json_object *obj, const char *key)
+{
+       json_object *tmp = NULL;
+
+       if (!json_object_object_get_ex(obj, key, &tmp))
+               return NULL;
+
+       return json_object_get_string(tmp);
+}
+
+const int get_int_from_object(json_object *obj, const char *key)
+{
+       json_object *tmp = NULL;
+
+       if (!json_object_object_get_ex(obj, key, &tmp))
+               return -EINVAL;
+
+       return json_object_get_int(tmp);
+}
+
+const double get_double_from_object(json_object *obj, const char *key)
+{
+       json_object *tmp = NULL;
+
+       if (!json_object_object_get_ex(obj, key, &tmp))
+               return -EINVAL;
+
+       return json_object_get_double(tmp);
+}
+
+const int get_boolean_from_object(json_object *obj, const char *key)
+{
+       json_object *tmp = NULL;
+
+       if (!json_object_object_get_ex(obj, key, &tmp))
+               return -EINVAL;
+
+       return (int)json_object_get_boolean(tmp);
+}
index 3e8ee97..d0fec49 100644 (file)
 #include <errno.h>
 #include <string.h>
 
+#include <gio/gio.h>
+#include <glib-object.h>
+
 #include <pass/log.h>
 #include <pass/common.h>
-#include <pass/config-parser.h>
 
 #include "pmqos.h"
 
-#define MAX_NUM_OF_SCENARIOS           255
-
-static bool is_supported(const char *value)
-{
-       assert(value);
-
-       if (MATCH(value, "yes"))
-               return true;
-       return false;
-}
-
 /**
  * @brief      Parse scenario section to get a scenario information
  *             for PMQoS(Power Management Quality of Service).
- * @param      [in] result Parsed raw data from configuration
- * @param      [in] user_data Instance for each scenario
- * @param      [in] index Index of each scenario
+ * @param      [in] obj Instance of json_object for each scenario
+ * @param      [in] scenario Instance for each scenario
  * @return     @c 0 on success, otherwise error value
  */
-static int pmqos_parse_scenario(struct parse_result *result, void *user_data, unsigned int index)
+static int pmqos_parse_scenario(json_object *obj, struct scenario *scenario)
 {
-       struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data;
-
-       assert(result);
-       assert(result->section && result->name && result->value);
-
-       /* Parse 'PassScenario' section */
-       if (MATCH(result->section, "PassScenario")) {
-               if (MATCH(result->name, "scenario_support"))
-                       scenarios->support = is_supported(result->value);
-               else if (MATCH(result->name, "scenario_num")) {
-                       int num;
-
-                       num = sys_strtol(result->value);
-                       if (num < 0)
-                               return num;
-
-                       if (num > MAX_NUM_OF_SCENARIOS)
-                               return -EINVAL;
-
-                       if (num > 0) {
-                               scenarios->list = calloc(num,
-                                               sizeof(struct scenario));
-                               if (!scenarios->list) {
-                                       _E("failed to allocate memory for scenario");
-                                       return -errno;
-                               }
-
-                               scenarios->num = num;
-                       }
-               }
+       const char *name;
+       int max_duration_ms;
+       int support;
+
+       /* Get property values */
+       name = get_string_from_object(obj, "name");
+       max_duration_ms = get_int_from_object(obj, "max_duration_ms");
+       support = get_boolean_from_object(obj, "support");
+
+       /* Check the mandatory property values are valid or not */
+       if (!name) {
+               _E("Failed to get 'name' property of scenario section\n");
+               return -EINVAL;
        }
 
-       /* Do not support pmqos scenario */
-       if (!scenarios->support)
-               return 0;
-
-       /* Do not have pmqos scenario */
-       if (!scenarios->num)
-               return 0;
-
-       /* No item to parse */
-       if (index >= scenarios->num)
-               return 0;
-
-       /* Parse 'Scenario' section */
-       if (MATCH(result->name, "name"))
-               snprintf(scenarios->list[index].name, strlen(result->value) + 1,
-                               "%s", result->value);
-       else if (MATCH(result->name, "support"))
-               scenarios->list[index].support = is_supported(result->value);
-       else if (MATCH(result->name, "max_duration_ms")) {
-               int max_duration_ms = sys_strtol(result->value);
-
-               if (max_duration_ms < 0) {
-                       _E("failed to parse max_duration_ms property (%d)\n",
-                                       max_duration_ms);
-                       return -EINVAL;
-               }
-
-               /*
-                * If maximum duration is zero, it measn that this scenario is
-                * mode without any maximum duration.
-                */
-               scenarios->list[index].max_duration_ms = max_duration_ms;
-       }
+       /* Initialize config_data from property values of confiugartion file */
+       snprintf(scenario->name, strlen(name) + 1, "%s", name);
+       scenario->max_duration_ms = (max_duration_ms < 0) ? 0 : max_duration_ms;
+       scenario->support = (support < 0) ? 1 : support;
 
        return 0;
 }
@@ -134,49 +78,56 @@ static int pmqos_parse_scenario(struct parse_result *result, void *user_data, un
  * @brief      Parse configuration to get information of supported scenarios
  *             for PMQoS(Power Management Quality of Service) such as
  *             AppLaunch, UltraPowerSaving.
- * @param      [in] result Parsed raw data from configuration
- * @param      [in] user_data Instance for each scenario
+ * @param      [in] obj Instance of json_object of thermal configuration file
+ * @param      [in] scenarios Instance for all scenarios
  * @return     @c 0 on success, otherwise error value
  */
-static int pmqos_load_config(struct parse_result *result, void *user_data)
+static int pmqos_load_config(json_object *obj, struct pmqos_scenario *scenarios)
 {
-       struct pmqos_scenario *scenarios = (struct pmqos_scenario *)user_data;
-       char name[NAME_MAX];
-       int ret;
-       static int index;
-
-       if (!result)
-               return 0;
-
-       if (!result->section || !result->name || !result->value)
+       int pmqos_support;
+       json_object *pmqos_scenario_list = NULL;
+       int num_scenarios = 0, ret, i;
+
+       /* Get property values */
+       pmqos_support = get_boolean_from_object(obj, "pmqos_support");
+       if (json_object_object_get_ex(obj, "pmqos_scenario_list",
+                               &pmqos_scenario_list))
+               num_scenarios = json_object_array_length(pmqos_scenario_list);
+
+       /* Check the mandatory property values are valid or not */
+       if (pmqos_support <= 0 || num_scenarios <= 0) {
+               _I("Disable PMQOS module\n");
                return 0;
+       }
 
-       /* Parsing 'PassScenario' section */
-       if (MATCH(result->section, "PassScenario")) {
-               ret = pmqos_parse_scenario(result, user_data, -1);
-               if (ret < 0) {
-                       _E("failed to parse [PassScenario] section : %d", ret);
-                       return ret;
-               }
-               goto out;
+       /* Initialize config_data from property values of confiugartion file */
+       scenarios->support = pmqos_support;
+       scenarios->list = calloc(num_scenarios, sizeof(struct scenario));
+       if (!scenarios->list) {
+               _E("failed to allocate memory for scenario");
+               return -ENOMEM;
        }
+       scenarios->num = num_scenarios;
 
-       /* Parsing 'Scenario' section */
-       for (index = 0; index < scenarios->num; ++index) {
-               snprintf(name, sizeof(name), "Scenario%d", index);
-
-               if (MATCH(result->section, name)) {
-                       ret = pmqos_parse_scenario(result, user_data, index);
-                       if (ret < 0) {
-                               _E("failed to parse [Scenario%d] section : %d", index, ret);
-                               return ret;
-                       }
-                       goto out;
+       for (i = 0; i < scenarios->num ; i++) {
+               json_object *scenario_obj
+                       = json_object_array_get_idx(pmqos_scenario_list, i);
+               struct scenario *scenario = &(scenarios->list[i]);
+
+               ret = pmqos_parse_scenario(scenario_obj, scenario);
+               if (ret < 0) {
+                       _E("cannot parse 'pmqos.scenario%d' section\n", i);
+                       goto err;
                }
        }
 
-out:
        return 0;
+err:
+       free(scenarios->list);
+       scenarios->list = NULL;
+       scenarios->num = 0;
+
+       return ret;
 }
 
 /**
@@ -209,16 +160,24 @@ int pmqos_put_scenario(struct pmqos_scenario *scenarios)
 int pmqos_get_scenario(const char *path, struct pmqos_scenario *scenarios)
 {
        int ret;
+       json_object *obj = NULL;
 
        /* Initialize the variables before parsing the pass-pmqos.conf */
        scenarios->num = 0;
 
-       /* get configuration file */
-       ret = config_parse(path, pmqos_load_config, scenarios);
-       if (ret < 0) {
-               pmqos_put_scenario(scenarios);
-               return ret;
+       /* Parse configuration file */
+       obj = json_object_from_file(path);
+       if (!obj) {
+               _E("Failed to get json_object from %s (%s)\n",
+                               path, json_util_get_last_err());
+               return -EINVAL;
        }
 
-       return 0;
+       ret = pmqos_load_config(obj, scenarios);
+       if (ret < 0)
+               pmqos_put_scenario(scenarios);
+
+       json_object_put(obj);
+
+       return ret;
 }
index eb40199..ec64276 100644 (file)
@@ -39,7 +39,7 @@
 
 #include "pmqos.h"
 
-#define PMQOS_CONF_PATH                "/etc/pass/pass-pmqos.conf"
+#define PMQOS_JSON_PATH                "/etc/pass/pass-pmqos.json"
 #define MILLISECONDS(tv)       ((tv.tv_sec)*1000 + (tv.tv_nsec)/1000000)
 #define DELTA(a, b)            (MILLISECONDS(a) - MILLISECONDS(b))
 
@@ -520,7 +520,7 @@ static int pmqos_init_done(void *data, void *user_data)
        if (!g_pmqos)
                return -ENOMEM;
 
-       ret = pmqos_get_scenario(PMQOS_CONF_PATH, g_pmqos);
+       ret = pmqos_get_scenario(PMQOS_JSON_PATH, g_pmqos);
        if (ret < 0) {
                _E("failed to get PMQoS scenario\n");
                return ret;
index bf34e78..12a56db 100644 (file)
@@ -17,6 +17,7 @@ pkg_check_modules(gtest_pkgs REQUIRED
        gio-2.0
        gmock
        dlog
+       json-c
        hal-api-power
 )