Add new APIs getting all apps' memory/CPU usage 98/129798/22
authorKichan Kwon <k_c.kwon@samsung.com>
Thu, 18 May 2017 06:22:39 +0000 (15:22 +0900)
committerKichan Kwon <k_c.kwon@samsung.com>
Thu, 8 Jun 2017 08:01:34 +0000 (17:01 +0900)
1) runtime_info_app_usage_destroy
  - Free app usage handle

2) runtime_info_app_usage_get_count
  - Get the count of handle

3) runtime_info_app_usage_get_appid
  - Get app's ID from handle

4) runtime_info_app_usage_get_usage
  - Get app's resource usage from handle

5) runtime_info_get_all_apps_memory_usage
  - Get handle storing each app's memory usage(KB)

6) runtime_info_get_all_apps_cpu_rate
  - Get handle storing each app's CPU rate(%)

- To get information, it requests to resourced via D-Bus

Change-Id: Ib3fc4b91475600c071a6a6e18b6998bfbcee4e4d
Signed-off-by: Kichan Kwon <k_c.kwon@samsung.com>
include/runtime_info.h
include/runtime_info_private.h
src/runtime_info_usage.c

index 446ccea..cd5a0ae 100644 (file)
@@ -391,6 +391,172 @@ int runtime_info_get_processor_max_frequency(int core_idx, int *cpu_freq);
  */
 int runtime_info_get_physical_memory_size(int *size);
 
+
+/**
+ * @brief  Handle for app usage information.
+ * @since_tizen  4.0
+ */
+typedef struct app_usages_s *app_usage_h;
+
+
+/**
+ * @brief  Frees an app usage handle.
+ * @since_tizen  4.0
+ *
+ * @param[in]  handle  App usage handle to free
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ */
+int runtime_info_app_usage_destroy(app_usage_h handle);
+
+
+/**
+ * @brief  Gets the app count from an app usage handle.
+ * @since_tizen  4.0
+ *
+ * @param[in]  handle  The app usage handle
+ * @param[out]  count  The number of apps on the app list
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ *
+ * @see  runtime_info_get_all_apps_memory_usage()
+ * @see  runtime_info_get_all_apps_cpu_rate()
+ */
+int runtime_info_app_usage_get_count(app_usage_h handle, unsigned int *count);
+
+
+/**
+ * @brief  Gets the app ID from an app usage handle.
+ * @since_tizen  4.0
+ *
+ * @remarks  You must release @a appid using free().
+ *
+ * @param[in]  handle  The app usage handle
+ * @param[in]  index  The index in the app list; should be between 0 and @a count - 1 (inclusive), \n
+ *                    where @a count is provided by runtime_info_app_usage_get_count()
+ * @param[out]  appid  The app ID
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ *
+ * @see  runtime_info_get_all_apps_memory_usage()
+ * @see  runtime_info_get_all_apps_cpu_rate()
+ */
+int runtime_info_app_usage_get_appid(app_usage_h handle, int index, char **appid);
+
+
+/**
+ * @brief  Gets resource usage from an app usage handle.
+ * @since_tizen  4.0
+ *
+ * @remarks  The meaning of @a usage depends on which function was used to create @a handle.
+ *
+ * @param[in]  handle  The app usage handle
+ * @param[in]  index  The index in the app list; should be between 0 and @a count - 1 (inclusive), \n
+ *                    where @a count is provided by runtime_info_app_usage_get_count()
+ * @param[out]  usage  Resource usage
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ *
+ * @see  runtime_info_get_all_apps_memory_usage()
+ * @see  runtime_info_get_all_apps_cpu_rate()
+ */
+int runtime_info_app_usage_get_usage(app_usage_h handle, int index, unsigned int *usage);
+
+
+/**
+ * @brief  Gets memory usage of all apps.
+ * @since_tizen  4.0
+ *
+ * @privilege  %http://tizen.org/privilege/systemmonitor
+ * @remarks  You must release @a usage using runtime_info_app_usage_destroy().
+ *
+ * @param[out]  usage  An array of each app's memory usage (KB)
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #RUNTIME_INFO_ERROR_OUT_OF_MEMORY  Not able to allocate memory (for output param/other operations)
+ * @retval  #RUNTIME_INFO_ERROR_REMOTE_IO  Call to resource daemon failed (dbus errors/resource daemon errors)
+ * @retval  #RUNTIME_INFO_ERROR_IO_ERROR  An I/O error during dbus message operations
+ * @retval  #RUNTIME_INFO_ERROR_PERMISSION_DENIED  Process not authorized to request app usage info
+ *
+ * @code
+ * #include <runtime_info.h>
+ *
+ * void print_memory_usage(void)
+ * {
+ *     int i;
+ *     unsigned int count;
+ *     app_usage_h mem_usage_handle;
+ *     char *appid;
+ *     unsigned int usage;
+ *
+ *     runtime_info_get_all_apps_memory_usage(&mem_usage_handle);
+ *     runtime_info_app_usage_get_count(mem_usage_handle, &count);
+ *
+ *     for (i = 0; i < count; i++) {
+ *         runtime_info_app_usage_get_appid(mem_usage_handle, i, &appid);
+ *         runtime_info_app_usage_get_usage(mem_usage_handle, i, &usage);
+ *         printf("appid = %s, usage = %u KB\n", appid, usage);
+ *         free(appid);
+ *     }
+ *
+ *     runtime_info_app_usage_destroy(mem_usage_handle);
+ *
+ * }
+ * @endcode
+ */
+int runtime_info_get_all_apps_memory_usage(app_usage_h *usage);
+
+
+/**
+ * @brief  Gets CPU rate of all apps.
+ * @since_tizen  4.0
+ *
+ * @privilege  %http://tizen.org/privilege/systemmonitor
+ * @remarks  You must release @a rate using runtime_info_app_usage_destroy().
+ *
+ * @param[out]  rate  An array of each app's CPU usage rate (%), the values are rounded down.
+ *
+ * @retval  #RUNTIME_INFO_ERROR_NONE  Successful
+ * @retval  #RUNTIME_INFO_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #RUNTIME_INFO_ERROR_OUT_OF_MEMORY  Not able to allocate memory (for output param/other operations)
+ * @retval  #RUNTIME_INFO_ERROR_REMOTE_IO  Call to resource daemon failed (dbus errors/resource daemon errors)
+ * @retval  #RUNTIME_INFO_ERROR_IO_ERROR  An I/O error during dbus message operations
+ * @retval  #RUNTIME_INFO_ERROR_PERMISSION_DENIED  Process not authorized to request app usage info
+ *
+ * @code
+ * #include <runtime_info.h>
+ *
+ * void print_cpu_usage(void)
+ * {
+ *     int i;
+ *     unsigned int count;
+ *     app_usage_h cpu_rate_handle;
+ *     char *appid;
+ *     unsigned int rate;
+ *
+ *     runtime_info_get_all_apps_cpu_rate(&cpu_rate_handle);
+ *     runtime_info_app_usage_get_count(cpu_rate_handle, &count);
+ *
+ *     for (i = 0; i < count; i++) {
+ *         runtime_info_app_usage_get_appid(cpu_rate_handle, i, &appid);
+ *         runtime_info_app_usage_get_usage(cpu_rate_handle, i, &rate);
+ *         printf("appid = %s, rate = %u %%\n", appid, rate);
+ *         free(appid);
+ *     }
+ *
+ *     runtime_info_app_usage_destroy(cpu_rate_handle);
+ *
+ * }
+ * @endcode
+ */
+int runtime_info_get_all_apps_cpu_rate(app_usage_h *rate);
+
+
 /**
  * @}
  */
index be5eab7..6486d94 100644 (file)
@@ -54,6 +54,16 @@ typedef union {
 
 typedef runtime_info_value_u * runtime_info_value_h;
 
+struct app_usage_s {
+       char *appid;
+       unsigned int usage;
+};
+
+struct app_usages_s {
+       unsigned int len;
+       struct app_usage_s *list;
+};
+
 typedef int (*runtime_info_func_get_value) (runtime_info_value_h value);
 typedef int (*runtime_info_func_set_event_cb) (void);
 typedef void (*runtime_info_func_unset_event_cb) (void);
index b8e1c5e..bb63755 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -35,6 +36,8 @@
 typedef enum {
        USAGE_TYPE_PROCESS_MEMORY,
        USAGE_TYPE_PROCESS_CPU,
+       USAGE_TYPE_APP_MEMORY,
+       USAGE_TYPE_APP_CPU,
 } runtime_info_usage_type_e;
 
 typedef struct {
@@ -46,6 +49,8 @@ typedef struct {
 static const runtime_info_dbus_info_s dbus_info[] = {
        { "ProcMemoryUsage", "process memory" },
        { "ProcCpuUsage", "process cpu" },
+       { "GetMemoryList", "all apps memory" },
+       { "GetCpuList", "all apps cpu" },
 };
 
 #define kBtoKiB(val) ((val) <= 0) ? 0 : (int)MIN((((long long)(val) << 10) / 1000), INT_MAX)
@@ -83,18 +88,30 @@ static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e
        GVariant *usage;
 
        /* Check parameter */
-       if (!pid || !error) {
-               //LCOV_EXCL_START : system error
-               _E("INVALID_PARAMETER(0x%08x): pid list and error params cannot be null");
-               if (error)
-                       *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
-               return NULL;
-               //LCOV_EXCL_STOP
-       }
-
-       if (type != USAGE_TYPE_PROCESS_MEMORY && type != USAGE_TYPE_PROCESS_CPU) {
+       switch (type) {
+       case USAGE_TYPE_PROCESS_MEMORY:
+       case USAGE_TYPE_PROCESS_CPU:
+               if (!pid || size <= 0) {
+                       //LCOV_EXCL_START : system error
+                       _E("INVALID_PARAMETER(0x%08x): pid list cannot be null");
+                       if (error)
+                               *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+                       return NULL;
+                       //LCOV_EXCL_STOP
+               }
+               /* Fall through */
+       case USAGE_TYPE_APP_MEMORY:
+       case USAGE_TYPE_APP_CPU:
+               if (!error) {
+                       //LCOV_EXCL_START : system error
+                       _E("INVALID_PARAMETER(0x%08x): error parameter cannot be null");
+                       return NULL;
+                       //LCOV_EXCL_STOP
+               }
+               break;
+       default:
                //LCOV_EXCL_START : system error
-               _E("INVALID_PARAMETER(0x%08x): invalid info parameter",
+               _E("INVALID_PARAMETER(0x%08x): invalid type parameter",
                                RUNTIME_INFO_ERROR_INVALID_PARAMETER);
                *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
                return NULL;
@@ -102,16 +119,26 @@ static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e
        }
 
        /* Make argument for requesting */
-       _D("Process %d: received query to get %s usage of %d processes",
-                       getpid(), dbus_info[type].caption, size);
-
-       args_in = runtime_info_append_args(pid, size);
-       if (!args_in) {
-               //LCOV_EXCL_START : system error
-               _E("DBUS_METHOD_CALL: not able to append pid array to message");
-               *error = RUNTIME_INFO_ERROR_IO_ERROR;
-               return NULL;
-               //LCOV_EXCL_STOP
+       switch (type) {
+       case USAGE_TYPE_PROCESS_MEMORY:
+       case USAGE_TYPE_PROCESS_CPU:
+               _D("Process %d: received query to get %s usage of %d processes",
+                               getpid(), dbus_info[type].caption, size);
+               args_in = runtime_info_append_args(pid, size);
+               if (!args_in) {
+                       //LCOV_EXCL_START : system error
+                       _E("DBUS_METHOD_CALL: not able to append pid array to message");
+                       *error = RUNTIME_INFO_ERROR_IO_ERROR;
+                       return NULL;
+                       //LCOV_EXCL_STOP
+               }
+               break;
+       case USAGE_TYPE_APP_MEMORY:
+       case USAGE_TYPE_APP_CPU:
+               _D("Process %d: received query to get %s usage of all apps",
+                               getpid(), dbus_info[type].caption);
+               args_in = NULL;
+               break;
        }
 
        /* Send message to resourced and receive reply */
@@ -120,7 +147,8 @@ static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e
                if (!conn) {
                        //LCOV_EXCL_START : system error
                        _E("Failed to get dbus connection : %s", err->message);
-                       g_variant_unref(args_in);
+                       if (args_in)
+                               g_variant_unref(args_in);
                        return NULL;
                        //LCOV_EXCL_STOP
                }
@@ -142,12 +170,14 @@ static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e
                        *error = RUNTIME_INFO_ERROR_PERMISSION_DENIED;
                else
                        *error = RUNTIME_INFO_ERROR_REMOTE_IO;
-               g_variant_unref(args_in);
+               if (args_in)
+                       g_variant_unref(args_in);
                return NULL;
                //LCOV_EXCL_STOP
        }
 
-       g_variant_unref(args_in);
+       if (args_in)
+               g_variant_unref(args_in);
 
        usage = g_variant_get_child_value(args_out, 0);
        g_variant_unref(args_out);
@@ -155,6 +185,70 @@ static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e
        return usage;
 }
 
+static int runtime_info_get_all_apps_usage(runtime_info_usage_type_e type,
+                                                                               app_usage_h *handle)
+{
+       int i;
+       int error;
+       unsigned int len;
+       struct app_usages_s *usages;
+       GVariant *reply;
+       GVariantIter iter;
+
+       if (!handle) {
+               _E("INVALID_PARAMETER(0x%08x) : invalid output param",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       reply = runtime_info_dbus_request_usage_info(type, NULL, 0, &error);
+       if (!reply) {
+               //LCOV_EXCL_START : system error
+               _E("DBUS_METHOD_CALL: call to resourced not successful");
+               return error;
+               //LCOV_EXCL_STOP
+       }
+
+       /* Check whether the received usage has expected format or not */
+       if (g_strcmp0(g_variant_get_type_string(reply), "a(su)")) {
+               //LCOV_EXCL_START : system error
+               _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
+               g_variant_unref(reply);
+               return RUNTIME_INFO_ERROR_REMOTE_IO;
+               //LCOV_EXCL_STOP
+       }
+
+       /* Populate the entries of info array using the data received from resourced */
+       len = g_variant_n_children(reply);
+
+       usages = calloc(1, sizeof(struct app_usages_s));
+       if (!usages) {
+               _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
+               g_variant_unref(reply);
+               return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+       }
+
+       usages->len = len;
+
+       usages->list = calloc(len, sizeof(struct app_usage_s));
+       if (!usages->list) {
+               _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
+               free(usages);
+               g_variant_unref(reply);
+               return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+       }
+
+       g_variant_iter_init(&iter, reply);
+       for (i = 0; i < len; i++)
+               g_variant_iter_next(&iter, "(su)",
+                               &(usages->list[i].appid), &(usages->list[i].usage));
+       g_variant_unref(reply);
+
+       *handle = usages;
+
+       return RUNTIME_INFO_ERROR_NONE;
+}
+
 API int runtime_info_get_system_memory_info(runtime_memory_info_s *info)
 {
        FILE *fp;
@@ -516,3 +610,101 @@ API int runtime_info_get_physical_memory_size(int *size)
 
        return RUNTIME_INFO_ERROR_NONE;
 }
+
+API int runtime_info_app_usage_destroy(app_usage_h handle)
+{
+       int i;
+       struct app_usage_s *list;
+       struct app_usages_s *usages = handle;
+
+       if (!usages) {
+               _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       list = usages->list;
+       if (list) {
+               for (i = 0; i < usages->len; i++)
+                       if (list[i].appid)
+                               free(list[i].appid);
+       }
+
+       free(list);
+       free(usages);
+
+       return RUNTIME_INFO_ERROR_NONE;
+}
+
+API int runtime_info_app_usage_get_count(app_usage_h handle, unsigned int *count)
+{
+       struct app_usages_s *usages = handle;
+
+       if (!usages) {
+               _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!count) {
+               _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       *count = usages->len;
+
+       return RUNTIME_INFO_ERROR_NONE;
+}
+
+API int runtime_info_app_usage_get_appid(app_usage_h handle, int index, char **appid)
+{
+       struct app_usages_s *usages = handle;
+
+       if (!usages || index < 0 || index >= usages->len) {
+               _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!appid) {
+               _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       *appid = strndup(usages->list[index].appid, strlen(usages->list[index].appid));
+
+       return RUNTIME_INFO_ERROR_NONE;
+}
+
+API int runtime_info_app_usage_get_usage(app_usage_h handle, int index, unsigned int *usage)
+{
+       struct app_usages_s *usages = handle;
+
+       if (!usages || index < 0 || index >= usages->len) {
+               _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!usage) {
+               _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
+                               RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+               return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+       }
+
+       *usage = usages->list[index].usage;
+
+       return RUNTIME_INFO_ERROR_NONE;
+}
+
+API int runtime_info_get_all_apps_memory_usage(app_usage_h *usage)
+{
+       return runtime_info_get_all_apps_usage(USAGE_TYPE_APP_MEMORY, usage);
+}
+
+API int runtime_info_get_all_apps_cpu_rate(app_usage_h *rate)
+{
+       return runtime_info_get_all_apps_usage(USAGE_TYPE_APP_CPU, rate);
+}