19f632069cdeeb4336b9cc065386d0462b3422ac
[platform/core/api/runtime-info.git] / src / runtime_info_usage.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <limits.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <dlog.h>
24
25 #include <runtime_info.h>
26 #include <runtime_info_private.h>
27
28 #include <gio/gio.h>
29 #include <glib.h>
30
31 #define RESOURCED_BUS_NAME "org.tizen.resourced"
32 #define RESOURCED_USAGE_OBJECT_NAME "/Org/Tizen/ResourceD/Process"
33 #define RESOURCED_USAGE_INTERFACE_NAME "org.tizen.resourced.process"
34 #define DBUS_REPLY_TIMEOUT (120 * 1000)
35
36 typedef enum {
37         USAGE_TYPE_PROCESS_MEMORY,
38         USAGE_TYPE_PROCESS_CPU,
39         USAGE_TYPE_APP_MEMORY,
40         USAGE_TYPE_APP_CPU,
41 } runtime_info_usage_type_e;
42
43 typedef struct {
44         const char *method_name;
45         const char *caption;
46 } runtime_info_dbus_info_s;
47
48 /* The index of this array must be matched with runtime_info_usage_type_e */
49 static const runtime_info_dbus_info_s dbus_info[] = {
50         { "ProcMemoryUsage", "process memory" },
51         { "ProcCpuUsage", "process cpu" },
52         { "GetMemoryList", "all apps memory" },
53         { "GetCpuList", "all apps cpu" },
54 };
55
56 #define ULONGtoINT(ulong)       (int)(MIN((ulong), INT_MAX))
57
58 /* ((val << 12) >> 10) = (val << 2) */
59 #define pagetoKiB(val) ((val) <= 0) ? 0 : (int)MIN(((long long)(val) << 2), INT_MAX)
60
61 /* Convert int array to GVariant("ai") */
62 static GVariant *runtime_info_append_args(int *args, int size)
63 {
64         GVariantBuilder builder, *sub_builder;
65         int i;
66
67         g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
68         sub_builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
69
70         for (i = 0; i < size; i++)
71                 g_variant_builder_add(sub_builder, "i", args[i]);
72
73         g_variant_builder_add_value(&builder, g_variant_new("ai", sub_builder));
74         g_variant_builder_unref(sub_builder);
75
76         return g_variant_builder_end(&builder);
77 }
78
79 /* Handler function which handles dbus related instructions
80  * Creates the method call to resourced and receives the reply (if successful)
81  * Return the received usage information (if received) else NULL to signify failed call to resourced
82  */
83 static GVariant *runtime_info_dbus_request_usage_info(runtime_info_usage_type_e type,
84                 int *pid, int size, int *error)
85 {
86         static GDBusConnection *conn;
87         GError *err = NULL;
88         GVariant *args_in = NULL;
89         GVariant *args_out = NULL;
90         GVariant *usage;
91
92         /* Check parameter */
93         switch (type) {
94         case USAGE_TYPE_PROCESS_MEMORY:
95         case USAGE_TYPE_PROCESS_CPU:
96                 if (!pid || size <= 0) {
97                         //LCOV_EXCL_START : system error
98                         _E("INVALID_PARAMETER(0x%08x): pid list cannot be null",
99                                         RUNTIME_INFO_ERROR_INVALID_PARAMETER);
100                         if (error)
101                                 *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
102                         return NULL;
103                         //LCOV_EXCL_STOP
104                 }
105                 /* Fall through */
106         case USAGE_TYPE_APP_MEMORY:
107         case USAGE_TYPE_APP_CPU:
108                 if (!error) {
109                         //LCOV_EXCL_START : system error
110                         _E("INVALID_PARAMETER(0x%08x): error parameter cannot be null",
111                                         RUNTIME_INFO_ERROR_INVALID_PARAMETER);
112                         return NULL;
113                         //LCOV_EXCL_STOP
114                 }
115                 break;
116         default:
117                 //LCOV_EXCL_START : system error
118                 _E("INVALID_PARAMETER(0x%08x): invalid type parameter",
119                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
120                 *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
121                 return NULL;
122                 //LCOV_EXCL_STOP
123         }
124
125         /* Make argument for requesting */
126         switch (type) {
127         case USAGE_TYPE_PROCESS_MEMORY:
128         case USAGE_TYPE_PROCESS_CPU:
129                 _D("Process %d: received query to get %s usage of %d processes",
130                                 getpid(), dbus_info[type].caption, size);
131                 args_in = runtime_info_append_args(pid, size);
132                 if (!args_in) {
133                         //LCOV_EXCL_START : system error
134                         _E("DBUS_METHOD_CALL: not able to append pid array to message");
135                         *error = RUNTIME_INFO_ERROR_IO_ERROR;
136                         return NULL;
137                         //LCOV_EXCL_STOP
138                 }
139                 break;
140         case USAGE_TYPE_APP_MEMORY:
141         case USAGE_TYPE_APP_CPU:
142                 _D("Process %d: received query to get %s usage of all apps",
143                                 getpid(), dbus_info[type].caption);
144                 args_in = NULL;
145                 break;
146         }
147
148         /* Send message to resourced and receive reply */
149         if (!conn) {
150                 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
151                 if (!conn) {
152                         //LCOV_EXCL_START : system error
153                         _E("Failed to get dbus connection : %s",
154                                         err && err->message ? err->message : NULL);
155                         if (args_in)
156                                 g_variant_unref(args_in);
157                         return NULL;
158                         //LCOV_EXCL_STOP
159                 }
160         }
161
162         _D("Process %d: Sending dbus message to resourced for %s info",
163                         getpid(), dbus_info[type].caption);
164
165         args_out = g_dbus_connection_call_sync(conn,
166                                 RESOURCED_BUS_NAME,
167                                 RESOURCED_USAGE_OBJECT_NAME,
168                                 RESOURCED_USAGE_INTERFACE_NAME,
169                                 dbus_info[type].method_name,
170                                 args_in, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_REPLY_TIMEOUT, NULL, &err);
171         if (!args_out) {
172                 //LCOV_EXCL_START : system error
173                 _E("DBUS_METHOD_CALL: not able to send message : %s",
174                                 err && err->message ? err->message : NULL);
175                 if (err && (err->code == G_FILE_ERROR_TXTBSY))
176                         *error = RUNTIME_INFO_ERROR_PERMISSION_DENIED;
177                 else
178                         *error = RUNTIME_INFO_ERROR_REMOTE_IO;
179                 if (args_in && !err)
180                         g_variant_unref(args_in);
181                 return NULL;
182                 //LCOV_EXCL_STOP
183         }
184
185         usage = g_variant_get_child_value(args_out, 0);
186         g_variant_unref(args_out);
187
188         return usage;
189 }
190
191 static int runtime_info_get_all_apps_usage(runtime_info_usage_type_e type,
192                                                                                 app_usage_h *handle)
193 {
194         int i;
195         int error;
196         unsigned int len;
197         struct app_usages_s *usages;
198         GVariant *reply;
199         GVariantIter iter;
200
201         if (!handle) {
202                 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
203                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
204                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
205         }
206
207         reply = runtime_info_dbus_request_usage_info(type, NULL, 0, &error);
208         if (!reply) {
209                 //LCOV_EXCL_START : system error
210                 _E("DBUS_METHOD_CALL: call to resourced not successful");
211                 return error;
212                 //LCOV_EXCL_STOP
213         }
214
215         /* Check whether the received usage has expected format or not */
216         if (g_strcmp0(g_variant_get_type_string(reply), "a(su)")) {
217                 //LCOV_EXCL_START : system error
218                 _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
219                 g_variant_unref(reply);
220                 return RUNTIME_INFO_ERROR_REMOTE_IO;
221                 //LCOV_EXCL_STOP
222         }
223
224         /* Populate the entries of info array using the data received from resourced */
225         len = g_variant_n_children(reply);
226         if (len <= 0) {
227                 _E("NO_DATA(0x%08x) : there is no registered app", RUNTIME_INFO_ERROR_NO_DATA);
228                 g_variant_unref(reply);
229                 return RUNTIME_INFO_ERROR_NO_DATA;
230         }
231
232         usages = calloc(1, sizeof(struct app_usages_s));
233         if (!usages) {
234                 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
235                 g_variant_unref(reply);
236                 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
237         }
238
239         usages->len = (int)len;
240
241         usages->list = calloc(len, sizeof(struct app_usage_s));
242         if (!usages->list) {
243                 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
244                 free(usages);
245                 g_variant_unref(reply);
246                 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
247         }
248
249         g_variant_iter_init(&iter, reply);
250         for (i = 0; i < len; i++)
251                 g_variant_iter_next(&iter, "(su)",
252                                 &(usages->list[i].appid), &(usages->list[i].usage));
253         g_variant_unref(reply);
254
255         *handle = usages;
256
257         return RUNTIME_INFO_ERROR_NONE;
258 }
259
260 API int runtime_info_get_system_memory_info(runtime_memory_info_s *info)
261 {
262         FILE *fp;
263         char buf[256];
264         unsigned long value;
265         unsigned long mem_total = 0;
266         unsigned long mem_free = 0;
267         unsigned long cached = 0;
268         unsigned long mem_available = 0;
269         unsigned long swap_total = 0;
270         unsigned long swap_free = 0;
271
272         if (info == NULL) {
273                 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
274                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
275                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
276         }
277
278         swap_total = swap_free = mem_available = 0;
279
280         fp = fopen("/proc/meminfo", "r");
281         if (fp == NULL) {
282                 _E("IO_ERROR(0x%08x) : failed to open file to read memory usage",
283                                 RUNTIME_INFO_ERROR_IO_ERROR);
284                 return RUNTIME_INFO_ERROR_IO_ERROR;
285         }
286
287         info->total = info->free = info->cache = 0;
288         while (fgets(buf, sizeof(buf), fp) != NULL) {
289                 if (sscanf(buf, "MemTotal: %lu", &mem_total) == 1)
290                         info->total = ULONGtoINT(mem_total);
291                 else if (sscanf(buf, "MemFree: %lu", &mem_free) == 1)
292                         info->free = ULONGtoINT(mem_free);
293                 else if (sscanf(buf, "Cached: %lu", &cached) == 1)
294                         info->cache = ULONGtoINT(cached);
295                 else if (sscanf(buf, "MemAvailable: %lu", &value) == 1)
296                         mem_available = value;
297                 else if (sscanf(buf, "SwapTotal: %lu", &value) == 1)
298                         swap_total = value;
299                 else if (sscanf(buf, "SwapFree: %lu", &value) == 1)
300                         swap_free = value;
301         }
302         fclose(fp);
303
304         if (mem_available > 0) {
305                 if (mem_total > mem_available)
306                         info->used = ULONGtoINT(mem_total - mem_available);
307                 else
308                         info->used = 0;
309         } else {
310                 if (mem_total > mem_free && mem_total - mem_free > cached)
311                         info->used = ULONGtoINT(mem_total - mem_free - cached);
312                 else
313                         info->used = 0;
314         }
315
316         info->swap = (swap_total > swap_free) ? ULONGtoINT(swap_total - swap_free) : 0;
317
318         return RUNTIME_INFO_ERROR_NONE;
319 }
320
321 API int runtime_info_get_process_memory_info(int *pid, int size, process_memory_info_s **info)
322 {
323         int i;
324         int error;
325         GVariant *usages;
326         GVariantIter iter;
327
328         if (!pid || size <= 0) {
329                 _E("INVALID_PARAMETER(0x%08x) : invalid input param",
330                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
331                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
332         }
333
334         if (!info) {
335                 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
336                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
337                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
338         }
339
340         *info = NULL;
341
342         /* Get the needed information from resourced daemon using dbus */
343         usages = runtime_info_dbus_request_usage_info(USAGE_TYPE_PROCESS_MEMORY, pid, size, &error);
344         if (!usages) {
345                 //LCOV_EXCL_START : system error
346                 _E("DBUS_METHOD_CALL: call to resourced not successful");
347                 return error;
348                 //LCOV_EXCL_STOP
349         }
350
351         /* Check whether the received usage has expected format or not */
352         if (g_strcmp0(g_variant_get_type_string(usages), "a(iiiiiii)") ||
353                         g_variant_n_children(usages) != size) {
354                 //LCOV_EXCL_START : system error
355                 _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
356                 g_variant_unref(usages);
357                 return RUNTIME_INFO_ERROR_REMOTE_IO;
358                 //LCOV_EXCL_STOP
359         }
360
361         /* Populate the entries of info array using the data received from resourced */
362         *info = (process_memory_info_s *)malloc(size * sizeof(process_memory_info_s));
363         if (!(*info)) {
364                 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
365                 g_variant_unref(usages);
366                 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
367         }
368
369         g_variant_iter_init(&iter, usages);
370         for (i = 0; i < size; i++)
371                 g_variant_iter_next(&iter, "(iiiiiii)",
372                                 &((*info)[i].vsz),
373                                 &((*info)[i].rss),
374                                 &((*info)[i].pss),
375                                 &((*info)[i].shared_clean),
376                                 &((*info)[i].shared_dirty),
377                                 &((*info)[i].private_clean),
378                                 &((*info)[i].private_dirty));
379
380         g_variant_unref(usages);
381
382         return RUNTIME_INFO_ERROR_NONE;
383 }
384
385 API int runtime_info_get_cpu_usage(runtime_cpu_usage_s *usage)
386 {
387         FILE *cpuinfo_fp;
388         char buf[256];
389         unsigned long long user = 0;
390         unsigned long long nice = 0;
391         unsigned long long system = 0;
392         unsigned long long idle = 0;
393         unsigned long long iowait = 0;
394         unsigned long long irq = 0;
395         unsigned long long softirq = 0;
396         unsigned long long total_uptime = 0;
397
398         if (usage == NULL) {
399                 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
400                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
401                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
402         }
403
404         cpuinfo_fp = fopen("/proc/stat", "r");
405         if (cpuinfo_fp == NULL) {
406                 _E("IO_ERROR(0x%08x) : failed to open file to read cpu usage",
407                                 RUNTIME_INFO_ERROR_IO_ERROR);
408                 return RUNTIME_INFO_ERROR_IO_ERROR;
409         }
410
411         while (fgets(buf, sizeof(buf), cpuinfo_fp) != NULL) {
412                 if (!strncmp(buf, "cpu ", 4) &&
413                     sscanf(buf + 4, "%llu %llu %llu %llu %llu %llu %llu",
414                                 &user, &nice, &system, &idle,
415                                 &iowait, &irq, &softirq) == 7)
416                         break;
417         }
418         fclose(cpuinfo_fp);
419
420         total_uptime = user + nice + system + idle + iowait + irq + softirq;
421
422         if (total_uptime > 0) {
423                 usage->user = (double)user * 100 / total_uptime;
424                 usage->nice = (double)nice * 100 / total_uptime;
425                 usage->system = (double)system * 100 / total_uptime;
426                 usage->iowait = (double)iowait * 100 / total_uptime;
427         } else {
428                 usage->user = 0;
429                 usage->nice = 0;
430                 usage->system = 0;
431                 usage->iowait = 0;
432         }
433
434         return RUNTIME_INFO_ERROR_NONE;
435 }
436
437 API int runtime_info_get_process_cpu_usage(int *pid, int size, process_cpu_usage_s **usage)
438 {
439         int i;
440         int error;
441         GVariant *usages;
442         GVariantIter iter;
443
444         if (!pid || size <= 0) {
445                 _E("INVALID_PARAMETER(0x%08x) : invalid input param",
446                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
447                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
448         }
449
450         if (!usage) {
451                 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
452                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
453                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
454         }
455
456         *usage = NULL;
457
458         /* Get the needed information from resourced daemon using dbus */
459         usages = runtime_info_dbus_request_usage_info(USAGE_TYPE_PROCESS_CPU, pid, size, &error);
460         if (!usages) {
461                 //LCOV_EXCL_START : system error
462                 _E("DBUS_METHOD_CALL: call to resourced not successful");
463                 return error;
464                 //LCOV_EXCL_STOP
465         }
466
467         /* Check whether the received usage has expected format or not */
468         if (g_strcmp0(g_variant_get_type_string(usages), "a(ii)") ||
469                         g_variant_n_children(usages) != size) {
470                 //LCOV_EXCL_START : system error
471                 _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
472                 g_variant_unref(usages);
473                 return RUNTIME_INFO_ERROR_REMOTE_IO;
474                 //LCOV_EXCL_STOP
475         }
476
477         /* Populate the entries of info array using the data received from resourced */
478         *usage = (process_cpu_usage_s *)malloc(size * sizeof(process_cpu_usage_s));
479         if (!(*usage)) {
480                 //LCOV_EXCL_START : system error
481                 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
482                 g_variant_unref(usages);
483                 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
484                 //LCOV_EXCL_STOP
485         }
486
487         g_variant_iter_init(&iter, usages);
488         for (i = 0; i < size; i++)
489                 g_variant_iter_next(&iter, "(ii)", &((*usage)[i].utime), &((*usage)[i].stime));
490
491         g_variant_unref(usages);
492
493         return RUNTIME_INFO_ERROR_NONE;
494 }
495
496 API int runtime_info_get_processor_count(int *num_core)
497 {
498         FILE *cpuinfo_fp;
499         int buf;
500         int result;
501
502         if (!num_core) {
503                 _E("INVALID_PARAMETER(0x%08x) : invalid output parameter",
504                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
505                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
506         }
507
508         cpuinfo_fp = fopen("/sys/devices/system/cpu/possible", "r");
509         if (cpuinfo_fp == NULL) {
510                 //LCOV_EXCL_START : system error
511                 _E("IO_ERROR(0x%08x) : failed to open file to read cpu information",
512                                 RUNTIME_INFO_ERROR_IO_ERROR);
513                 return RUNTIME_INFO_ERROR_IO_ERROR;
514                 //LCOV_EXCL_STOP
515         }
516
517         if (!fscanf(cpuinfo_fp, "%d-%d", &buf, &result)) {
518                 //LCOV_EXCL_START : system error
519                 _E("IO_ERROR(0x%08x) : there is no information in the system file",
520                                 RUNTIME_INFO_ERROR_IO_ERROR);
521                 fclose(cpuinfo_fp);
522                 return RUNTIME_INFO_ERROR_IO_ERROR;
523                 //LCOV_EXCL_STOP
524         }
525
526         *num_core = result + 1;
527
528         fclose(cpuinfo_fp);
529         return RUNTIME_INFO_ERROR_NONE;
530 }
531
532 API int runtime_info_get_processor_current_frequency(int core_idx, int *cpu_freq)
533 {
534         int num_core;
535
536         if (runtime_info_get_processor_count(&num_core)
537                         != RUNTIME_INFO_ERROR_NONE) {
538                 _E("runtime_info_get_processor_count is failed");
539                 return RUNTIME_INFO_ERROR_IO_ERROR;
540         }
541
542         if (core_idx < 0 || core_idx >= num_core) {
543                 _E("INVALID_PARAMETER(0x%08x) : invalid input parameter",
544                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
545                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
546         }
547
548         if (!cpu_freq) {
549                 _E("INVALID_PARAMETER(0x%08x) : invalid output parameter",
550                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
551                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
552         }
553
554         if (runtime_info_get_frequency_cpufreq(core_idx, "cur", cpu_freq)
555                         != RUNTIME_INFO_ERROR_NONE) {
556                 //LCOV_EXCL_START : system error
557                 _I("This system doesn't support cpufreq. Use cpuinfo instead.");
558
559                 switch (runtime_info_get_frequency_cpuinfo(core_idx, cpu_freq)) {
560                 case RUNTIME_INFO_ERROR_NONE:
561                         _I("Notice : it is max CPU frequency");
562                         break;
563                 case RUNTIME_INFO_ERROR_NO_DATA:
564                         _E("This system doesn't support MHz information in the cpuinfo");
565                         return RUNTIME_INFO_ERROR_NO_DATA;
566                 default:
567                         _E("Fail to get current CPU frequency");
568                         return RUNTIME_INFO_ERROR_IO_ERROR;
569                 };
570                 //LCOV_EXCL_STOP
571         }
572
573         return RUNTIME_INFO_ERROR_NONE;
574 }
575
576 API int runtime_info_get_processor_max_frequency(int core_idx, int *cpu_freq)
577 {
578         int num_core;
579
580         if (runtime_info_get_processor_count(&num_core)
581                         != RUNTIME_INFO_ERROR_NONE) {
582                 _E("runtime_info_get_processor_count is failed");
583                 return RUNTIME_INFO_ERROR_IO_ERROR;
584         }
585
586         if (core_idx < 0 || core_idx >= num_core) {
587                 _E("INVALID_PARAMETER(0x%08x) : invalid input parameter",
588                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
589                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
590         }
591
592         if (!cpu_freq) {
593                 _E("INVALID_PARAMETER(0x%08x) : invalid output parameter",
594                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
595                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
596         }
597
598         if (runtime_info_get_frequency_cpufreq(core_idx, "max", cpu_freq)
599                         != RUNTIME_INFO_ERROR_NONE) {
600                 //LCOV_EXCL_START : system error
601                 _I("This system doesn't support cpufreq. Use cpuinfo instead.");
602
603                 switch (runtime_info_get_frequency_cpuinfo(core_idx, cpu_freq)) {
604                 case RUNTIME_INFO_ERROR_NONE:
605                         break;
606                 case RUNTIME_INFO_ERROR_NO_DATA:
607                         _E("This system doesn't support MHz information in the cpuinfo");
608                         return RUNTIME_INFO_ERROR_NO_DATA;
609                 default:
610                         _E("Fail to get current CPU frequency");
611                         return RUNTIME_INFO_ERROR_IO_ERROR;
612                 };
613                 //LCOV_EXCL_STOP
614         }
615
616         return RUNTIME_INFO_ERROR_NONE;
617 }
618
619 API int runtime_info_get_physical_memory_size(int *size)
620 {
621         char buf[256];
622         unsigned long value;
623         int sum;
624         FILE *fp = fopen("/proc/zoneinfo", "r");
625         if (!fp) {
626                 _E("IO_ERROR(0x%08x) : failed to open file to read memory size",
627                                 RUNTIME_INFO_ERROR_IO_ERROR);
628                 return RUNTIME_INFO_ERROR_IO_ERROR;
629         }
630
631         if (!size) {
632                 _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
633                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
634                 fclose(fp);
635                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
636         }
637
638         sum = 0;
639         while (fgets(buf, sizeof(buf), fp) != NULL)
640                 if (sscanf(buf, " spanned %lu", &value) == 1)
641                         sum += value;
642         *size = pagetoKiB(sum);
643
644         fclose(fp);
645
646         return RUNTIME_INFO_ERROR_NONE;
647 }
648
649 API int runtime_info_app_usage_destroy(app_usage_h handle)
650 {
651         int i;
652         struct app_usage_s *list;
653         struct app_usages_s *usages = handle;
654
655         if (!usages) {
656                 _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
657                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
658                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
659         }
660
661         list = usages->list;
662         if (list) {
663                 for (i = 0; i < usages->len; i++)
664                         if (list[i].appid)
665                                 free(list[i].appid);
666         }
667
668         free(list);
669         free(usages);
670
671         return RUNTIME_INFO_ERROR_NONE;
672 }
673
674 API int runtime_info_app_usage_get_count(app_usage_h handle, int *count)
675 {
676         struct app_usages_s *usages = handle;
677
678         if (!usages) {
679                 _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
680                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
681                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
682         }
683
684         if (!count) {
685                 _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
686                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
687                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
688         }
689
690         *count = usages->len;
691
692         return RUNTIME_INFO_ERROR_NONE;
693 }
694
695 API int runtime_info_app_usage_get_appid(app_usage_h handle, int index, char **appid)
696 {
697         struct app_usages_s *usages = handle;
698
699         if (!usages || index < 0 || index >= usages->len) {
700                 _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
701                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
702                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
703         }
704
705         if (!appid) {
706                 _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
707                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
708                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
709         }
710
711         *appid = strndup(usages->list[index].appid, strlen(usages->list[index].appid));
712
713         return RUNTIME_INFO_ERROR_NONE;
714 }
715
716 API int runtime_info_app_usage_get_usage(app_usage_h handle, int index, unsigned int *usage)
717 {
718         struct app_usages_s *usages = handle;
719
720         if (!usages || index < 0 || index >= usages->len) {
721                 _E("INVALID PARAMETER(0x%08x) : invalid input parameter",
722                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
723                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
724         }
725
726         if (!usage) {
727                 _E("INVALID PARAMETER(0x%08x) : invalid output parameter",
728                                 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
729                 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
730         }
731
732         *usage = usages->list[index].usage;
733
734         return RUNTIME_INFO_ERROR_NONE;
735 }
736
737 API int runtime_info_get_all_apps_memory_usage(app_usage_h *usage)
738 {
739         return runtime_info_get_all_apps_usage(USAGE_TYPE_APP_MEMORY, usage);
740 }
741
742 API int runtime_info_get_all_apps_cpu_rate(app_usage_h *rate)
743 {
744         return runtime_info_get_all_apps_usage(USAGE_TYPE_APP_CPU, rate);
745 }