2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 <runtime_info.h>
24 #include <runtime_info_private.h>
31 #define LOG_TAG "CAPI_RUNTIME_INFO_USAGE"
33 #define _E(fmt, arg...) LOGE("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg)
34 #define _D(fmt, arg...) LOGD("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg)
35 #define _I(fmt, arg...) LOGI("[%s,%d] "fmt, __FUNCTION__, __LINE__, ##arg)
37 #define RESOURCED_BUS_NAME "org.tizen.resourced"
38 #define RESOURCED_USAGE_OBJECT_NAME "/Org/Tizen/ResourceD/Process"
39 #define RESOURCED_USAGE_INTERFACE_NAME "org.tizen.resourced.process"
40 #define RESOURCED_MEMORY_USAGE_METHOD "ProcMemoryUsage"
41 #define RESOURCED_CPU_USAGE_METHOD "ProcCpuUsage"
42 #define DBUS_REPLY_TIMEOUT (120 * 1000)
43 #define MEMORY_USAGE 1
46 #define kBtoKiB(val) (int)(((long long)val * 1024)/1000)
48 static int runtime_info_get_dbus_error(const char *err_name)
53 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
55 size = strlen(err_name);
56 if (!strncmp(err_name, DBUS_ERROR_IO_ERROR, size))
57 return RUNTIME_INFO_ERROR_IO_ERROR;
58 else if (!strncmp(err_name, DBUS_ERROR_NO_MEMORY, size))
59 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
60 else if (!strncmp(err_name, DBUS_ERROR_ACCESS_DENIED, size))
61 return RUNTIME_INFO_ERROR_PERMISSION_DENIED;
63 return RUNTIME_INFO_ERROR_REMOTE_IO;
66 /* Handler function which handles dbus related instructions
67 * for both per process memory and cpu requests.
68 * Creates the method call to resourced and receives the reply (if successful)
69 * Return the received reply (if received) else NULL to signify failed call to resourced
71 static DBusMessage *runtime_info_dbus_process_usage_info(int *pid, int size, int info, int *error)
80 _E("INVALID_PARAMETER(0x%08x): pid list and error params cannot be null");
83 *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
87 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
89 _E("DBUS_CONNECTION_ERROR");
90 *error = RUNTIME_INFO_ERROR_REMOTE_IO;
94 if (info == MEMORY_USAGE) {
95 _D("Process %d: received query to get process memory info of %d processes",
97 msg = dbus_message_new_method_call(RESOURCED_BUS_NAME,
98 RESOURCED_USAGE_OBJECT_NAME,
99 RESOURCED_USAGE_INTERFACE_NAME,
100 RESOURCED_MEMORY_USAGE_METHOD);
101 } else if (info == CPU_USAGE) {
102 _D("Process %d: received query to get process cpu usage of %d processes",
104 msg = dbus_message_new_method_call(RESOURCED_BUS_NAME,
105 RESOURCED_USAGE_OBJECT_NAME,
106 RESOURCED_USAGE_INTERFACE_NAME,
107 RESOURCED_CPU_USAGE_METHOD);
109 _E("INVALID_PARAMETER(0x%08x): info parameter should be %d or %d",
110 MEMORY_USAGE, CPU_USAGE, RUNTIME_INFO_ERROR_INVALID_PARAMETER);
111 *error = RUNTIME_INFO_ERROR_INVALID_PARAMETER;
116 _E("DBUS_METHOD_CALL: not able to create method call (%s:%s-%s)",
117 RESOURCED_USAGE_OBJECT_NAME, RESOURCED_USAGE_INTERFACE_NAME,
118 RESOURCED_MEMORY_USAGE_METHOD);
119 *error = RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
123 ret = dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &pid,
124 size, DBUS_TYPE_INVALID);
126 _E("DBUS_METHOD_CALL: not able to append pid array to message");
127 *error = RUNTIME_INFO_ERROR_IO_ERROR;
128 dbus_message_unref(msg);
132 dbus_error_init(&err);
135 if (info == MEMORY_USAGE)
136 _D("Process %d: Sending dbus message to resourced for process memory usage info",
139 _D("Process %d: Sending dbus message to resourced for process cpu usage info",
141 reply = dbus_connection_send_with_reply_and_block(conn, msg,
142 DBUS_REPLY_TIMEOUT, &err);
144 _E("DBUS_METHOD_CALL: not able to send message");
146 if (dbus_error_is_set(&err)) {
147 _E("DBUS_METHOD_CALL: dbus_connection_send error(%s:%s)", err.name, err.message);
148 *error = runtime_info_get_dbus_error(err.name);
149 dbus_error_free(&err);
153 dbus_message_unref(msg);
157 API int runtime_info_get_system_memory_info(runtime_memory_info_s *info)
161 unsigned long swap_total, swap_free, value;
164 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
165 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
166 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
169 swap_total = swap_free = 0;
171 meminfo_fp = fopen("/proc/meminfo", "r");
172 if (meminfo_fp == NULL) {
173 _E("IO_ERROR(0x%08x) : failed to open file to read memory usage",
174 RUNTIME_INFO_ERROR_IO_ERROR);
175 return RUNTIME_INFO_ERROR_IO_ERROR;
178 while (fgets(buf, sizeof(buf), meminfo_fp) != NULL) {
179 if (sscanf(buf, "MemTotal: %lu", &value) == 1)
180 info->total = kBtoKiB(value);
181 else if (sscanf(buf, "MemFree: %lu", &value) == 1)
182 info->free = kBtoKiB(value);
183 else if (sscanf(buf, "Cached: %lu", &value) == 1)
184 info->cache = kBtoKiB(value);
185 else if (sscanf(buf, "SwapTotal: %lu", &value) == 1)
187 else if (sscanf(buf, "SwapFree: %lu", &value) == 1)
192 info->used = (info->total > info->free) ? (info->total - info->free) : 0;
193 info->swap = kBtoKiB(((swap_total > swap_free) ? (int)(swap_total - swap_free) : 0));
195 return RUNTIME_INFO_ERROR_NONE;
198 API int runtime_info_get_process_memory_info(int *pid, int size, process_memory_info_s **info)
200 DBusMessageIter iter, iter_array, iter_struct;
203 process_memory_info_s *proc_info;
204 DBusMessage *replymsg;
206 if (!pid || size <= 0) {
207 _E("INVALID_PARAMETER(0x%08x) : invalid input param",
208 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
209 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
213 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
214 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
215 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
220 /* Get the needed information from resourced daemon using dbus */
221 replymsg = runtime_info_dbus_process_usage_info(pid, size, MEMORY_USAGE, &error);
223 _E("DBUS_METHOD_CALL: call to resourced not successful");
227 /* Check if the message is an error message or not in expected
228 * format and return error value */
229 dbus_message_iter_init(replymsg, &iter);
230 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_INT32) {
231 dbus_message_iter_get_basic(&iter, &error);
232 _E("DBUS_METHOD_CALL: call to resourced returned error message");
233 dbus_message_unref(replymsg);
235 } else if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
236 _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
237 dbus_message_unref(replymsg);
238 return RUNTIME_INFO_ERROR_REMOTE_IO;
241 /* Populate the entries of info array using the data received from resourced */
242 *info = (process_memory_info_s *)malloc(size * sizeof(process_memory_info_s));
244 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
245 dbus_message_unref(replymsg);
246 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
249 dbus_message_iter_recurse(&iter, &iter_array);
250 for (index = 0; index < size; ++index) {
251 proc_info = &(*info)[index];
253 dbus_message_iter_recurse(&iter_array, &iter_struct);
255 dbus_message_iter_get_basic(&iter_struct, &value);
256 proc_info->vsz = value;
257 dbus_message_iter_next(&iter_struct);
258 dbus_message_iter_get_basic(&iter_struct, &value);
259 proc_info->rss = value;
260 dbus_message_iter_next(&iter_struct);
261 dbus_message_iter_get_basic(&iter_struct, &value);
262 proc_info->pss = value;
263 dbus_message_iter_next(&iter_struct);
264 dbus_message_iter_get_basic(&iter_struct, &value);
265 proc_info->shared_clean = value;
266 dbus_message_iter_next(&iter_struct);
267 dbus_message_iter_get_basic(&iter_struct, &value);
268 proc_info->shared_dirty = value;
269 dbus_message_iter_next(&iter_struct);
270 dbus_message_iter_get_basic(&iter_struct, &value);
271 proc_info->private_clean = value;
272 dbus_message_iter_next(&iter_struct);
273 dbus_message_iter_get_basic(&iter_struct, &value);
274 proc_info->private_dirty = value;
276 dbus_message_iter_next(&iter_array);
279 dbus_message_unref(replymsg);
280 return RUNTIME_INFO_ERROR_NONE;
283 API int runtime_info_get_cpu_usage(runtime_cpu_usage_s *usage)
287 unsigned long long user, nice, system, idle, iowait, irq, softirq, total_uptime;
290 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
291 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
292 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
295 cpuinfo_fp = fopen("/proc/stat", "r");
296 if (cpuinfo_fp == NULL) {
297 _E("IO_ERROR(0x%08x) : failed to open file to read cpu usage",
298 RUNTIME_INFO_ERROR_IO_ERROR);
299 return RUNTIME_INFO_ERROR_IO_ERROR;
302 while (fgets(buf, sizeof(buf), cpuinfo_fp) != NULL) {
303 if (!strncmp(buf, "cpu ", 4) &&
304 sscanf(buf+4, "%llu %llu %llu %llu %llu %llu %llu",
305 &user, &nice, &system, &idle,
306 &iowait, &irq, &softirq) == 7)
311 total_uptime = user+nice+system+idle+iowait+irq+softirq;
313 usage->user = (double)user*100/total_uptime;
314 usage->nice = (double)nice*100/total_uptime;
315 usage->system = (double)system*100/total_uptime;
316 usage->iowait = (double)iowait*100/total_uptime;
318 return RUNTIME_INFO_ERROR_NONE;
321 API int runtime_info_get_process_cpu_usage(int *pid, int size, process_cpu_usage_s **usage)
323 DBusMessageIter iter, iter_array, iter_struct;
326 process_cpu_usage_s *proc_usage;
327 DBusMessage *replymsg;
329 if (!pid || size <= 0) {
330 _E("INVALID_PARAMETER(0x%08x) : invalid input param",
331 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
332 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
336 _E("INVALID_PARAMETER(0x%08x) : invalid output param",
337 RUNTIME_INFO_ERROR_INVALID_PARAMETER);
338 return RUNTIME_INFO_ERROR_INVALID_PARAMETER;
343 /* Get the needed information from resourced daemon using dbus */
344 replymsg = runtime_info_dbus_process_usage_info(pid, size, CPU_USAGE, &error);
346 _E("DBUS_METHOD_CALL: call to resourced not successful");
350 /* Check if the message is an error message or not in expected format
351 * and return error value */
352 dbus_message_iter_init(replymsg, &iter);
353 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_INT32) {
354 dbus_message_iter_get_basic(&iter, &error);
355 _E("DBUS_METHOD_CALL: call to resourced returned error message");
356 dbus_message_unref(replymsg);
358 } else if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
359 _E("DBUS_METHOD_CALL: received dbus message is not in expected format");
360 dbus_message_unref(replymsg);
361 return RUNTIME_INFO_ERROR_REMOTE_IO;
364 /* Populate the entries of info array using the data received from resourced */
365 *usage = (process_cpu_usage_s *)malloc(size * sizeof(process_cpu_usage_s));
367 _E("OUT_OF_MEMORY(0x%08x)", RUNTIME_INFO_ERROR_OUT_OF_MEMORY);
368 dbus_message_unref(replymsg);
369 return RUNTIME_INFO_ERROR_OUT_OF_MEMORY;
372 dbus_message_iter_recurse(&iter, &iter_array);
373 for (index = 0; index < size; ++index) {
374 proc_usage = &(*usage)[index];
376 dbus_message_iter_recurse(&iter_array, &iter_struct);
378 dbus_message_iter_get_basic(&iter_struct, &value);
379 proc_usage->utime = value;
380 dbus_message_iter_next(&iter_struct);
381 dbus_message_iter_get_basic(&iter_struct, &value);
382 proc_usage->stime = value;
384 dbus_message_iter_next(&iter_array);
387 dbus_message_unref(replymsg);
388 return RUNTIME_INFO_ERROR_NONE;