#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <stdarg.h>
#include <dlog.h>
#include <runtime_info.h>
#include <runtime_info_private.h>
+#include <runtime_info-internal.h>
#include <gio/gio.h>
#include <glib.h>
+#include <hal/device/hal-memory.h>
+
#define RESOURCED_BUS_NAME "org.tizen.resourced"
#define RESOURCED_USAGE_OBJECT_NAME "/Org/Tizen/ResourceD/Process"
#define RESOURCED_USAGE_INTERFACE_NAME "org.tizen.resourced.process"
USAGE_TYPE_PROCESS_CPU,
USAGE_TYPE_APP_MEMORY,
USAGE_TYPE_APP_CPU,
+ USAGE_TYPE_PROCESS_SWAP,
} runtime_info_usage_type_e;
typedef struct {
{ "ProcCpuUsage", "process cpu" },
{ "GetMemoryList", "all apps memory" },
{ "GetCpuList", "all apps cpu" },
+ { "ProcSwapUsage", "process swap" },
};
#define ULONGtoINT(ulong) (int)(MIN((ulong), INT_MAX))
switch (type) {
case USAGE_TYPE_PROCESS_MEMORY:
case USAGE_TYPE_PROCESS_CPU:
+ case USAGE_TYPE_PROCESS_SWAP:
if (!pid || size <= 0) {
//LCOV_EXCL_START : system error
_E("INVALID_PARAMETER(0x%08x): pid list cannot be null",
switch (type) {
case USAGE_TYPE_PROCESS_MEMORY:
case USAGE_TYPE_PROCESS_CPU:
+ case USAGE_TYPE_PROCESS_SWAP:
_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);
return RUNTIME_INFO_ERROR_NONE;
}
+static runtime_info_error_e hal_error_to_runtime_info_error(int err)
+{
+ switch (err) {
+ case 0:
+ return RUNTIME_INFO_ERROR_NONE;
+ case -EINVAL:
+ return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ case -ENOMEM:
+ return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+ case -EIO:
+ case -ENOENT:
+ return RUNTIME_INFO_ERROR_IO_ERROR;
+ case -EPERM:
+ case -EACCES:
+ return RUNTIME_INFO_ERROR_PERMISSION_DENIED;
+ case -ENOTSUP:
+ return RUNTIME_INFO_ERROR_NOT_SUPPORTED;
+ default:
+ // TODO: what is the runtime-info error for this default case?
+ return RUNTIME_INFO_ERROR_NO_DATA;
+ }
+}
+
+static int get_process_memory_info_direct(int *pid, int size, process_memory_info_key_e key, int **info)
+{
+ int ret, i;
+ struct gpu_info gpu_info;
+ struct gem_info gem_info;
+ int *result;
+ int err = RUNTIME_INFO_ERROR_NONE;
+
+ result = (int *)calloc(size, sizeof(int));
+ if (!result) {
+ err = RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ switch (key) {
+ case RUNTIME_INFO_PROC_MEMORY_GPU:
+ for (i = 0; i < size; ++i) {
+ ret = hal_device_memory_get_gpu_info(pid[i], &gpu_info);
+ if (ret != 0) {
+ err = hal_error_to_runtime_info_error(ret);
+ goto out;
+ }
+ result[i] = gpu_info.used_pages;
+ }
+ *info = result;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_GEM_RSS:
+ for (i = 0; i < size; ++i) {
+ ret = hal_device_memory_get_gem_info(pid[i], &gem_info);
+ if (ret != 0) {
+ err = hal_error_to_runtime_info_error(ret);
+ goto out;
+ }
+ result[i] = gem_info.rss;
+ }
+ *info = result;
+ break;
+ default:
+ err = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ break;
+ }
+
+out:
+ if (err != RUNTIME_INFO_ERROR_NONE)
+ free(result);
+
+ return err;
+}
+
+static int get_process_memory_swap_info(int *pid, int size, int **info)
+{
+ int i, temp;
+ int error;
+ GVariant *usages;
+ GVariantIter iter;
+
+ if (!pid || size <= 0) {
+ _E("INVALID_PARAMETER(0x%08x) : invalid input param",
+ RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+ return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!info) {
+ _E("INVALID_PARAMETER(0x%08x) : invalid output param",
+ RUNTIME_INFO_ERROR_INVALID_PARAMETER);
+ return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ }
+
+ *info = NULL;
+
+ /* Get the needed information from resourced daemon using dbus */
+ usages = runtime_info_dbus_request_usage_info(USAGE_TYPE_PROCESS_SWAP, pid, size, &error);
+ if (!usages) {
+ //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(usages), "a(i)") ||
+ g_variant_n_children(usages) != size) {
+ //LCOV_EXCL_START : system error
+ _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
+ g_variant_unref(usages);
+ return RUNTIME_INFO_ERROR_REMOTE_IO;
+ //LCOV_EXCL_STOP
+ }
+
+ /* Populate the entries of info array using the data received from resourced */
+ *info = (int *)malloc(size * sizeof(int));
+ if (!(*info)) {
+ _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
+ g_variant_unref(usages);
+ return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+ }
+
+ g_variant_iter_init(&iter, usages);
+ for (i = 0; i < size; i++) {
+ g_variant_iter_next(&iter, "(i)", &temp);
+ (*info)[i] = temp;
+ }
+
+ g_variant_unref(usages);
+
+ return RUNTIME_INFO_ERROR_NONE;
+}
+
+static int get_process_memory_info(int *pid, int size, process_memory_info_key_e key, int **info)
+{
+ int i;
+ int ret;
+ int *result;
+ process_memory_info_s *base = NULL;
+
+ ret = RUNTIME_INFO_ERROR_NONE;
+
+ result = (int *)calloc(size, sizeof(int));
+ if (!result) {
+ ret = RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = runtime_info_get_process_memory_info(pid, size, &base);
+ if (ret != RUNTIME_INFO_ERROR_NONE)
+ goto out;
+
+ switch (key) {
+ case RUNTIME_INFO_PROC_MEMORY_VSZ:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].vsz;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_RSS:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].rss;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_PSS:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].pss;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_SHARED_CLEAN:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].shared_clean;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_SHARED_DIRTY:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].shared_dirty;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_PRIVATE_CLEAN:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].private_clean;
+ break;
+ case RUNTIME_INFO_PROC_MEMORY_PRIVATE_DIRTY:
+ for (i = 0; i < size; ++i)
+ result[i] = base[i].private_dirty;
+ break;
+ default:
+ ret = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ goto out;
+ }
+
+ *info = result;
+
+out:
+ if (ret != RUNTIME_INFO_ERROR_NONE)
+ free(result);
+ free(base);
+
+ return ret;
+}
+
+API int runtime_info_get_process_memory_value_int(int *pid, int size, process_memory_info_key_e key, int **info)
+{
+ switch (key) {
+ case RUNTIME_INFO_PROC_MEMORY_GPU:
+ case RUNTIME_INFO_PROC_MEMORY_GEM_RSS:
+ return get_process_memory_info_direct(pid, size, key, info);
+ case RUNTIME_INFO_PROC_MEMORY_SWAP:
+ return get_process_memory_swap_info(pid, size, info);
+ case RUNTIME_INFO_PROC_MEMORY_VSZ:
+ case RUNTIME_INFO_PROC_MEMORY_RSS:
+ case RUNTIME_INFO_PROC_MEMORY_PSS:
+ case RUNTIME_INFO_PROC_MEMORY_SHARED_CLEAN:
+ case RUNTIME_INFO_PROC_MEMORY_SHARED_DIRTY:
+ case RUNTIME_INFO_PROC_MEMORY_PRIVATE_CLEAN:
+ case RUNTIME_INFO_PROC_MEMORY_PRIVATE_DIRTY:
+ return get_process_memory_info(pid, size, key, info);
+ default:
+ return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
+ }
+}
+
API int runtime_info_get_cpu_usage(runtime_cpu_usage_s *usage)
{
FILE *cpuinfo_fp;