5 * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd. All rights reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * @file proc-monitor.c
24 * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
29 #include <sys/types.h>
31 #include <sys/mount.h>
33 #include <sys/resource.h>
35 #include "proc-main.h"
36 #include "proc-monitor.h"
37 #include "resourced.h"
40 #include "safe-kill.h"
41 #include "dbus-handler.h"
42 #include "proc-process.h"
43 #include "proc-usage-stats.h"
44 #include "proc-usage-stats-helper.h"
49 #include "file-helper.h"
50 #include "watchdog-cgroup.h"
52 #include <libsyscommon/libsystemd.h>
54 #define WATCHDOG_LAUNCHING_PARAM "PopupLaunch"
55 #define WATCHDOG_KEY1 "_SYSPOPUP_CONTENT_"
56 #define WATCHDOG_KEY2 "_APP_NAME_"
57 #define WATCHDOG_VALUE_1 "watchdog"
59 #define TIZEN_DEBUG_MODE_FILE RD_SYS_ETC"/.debugmode"
60 #define DEFAULT_APPID "NULL"
61 #define DEFAULT_RAMSIZE 512
64 #define POWER_OFF_DIRECT 2
66 static int current_lcd_state;
68 static GSource *app_watchdog_check_timer;
69 #define APP_WATCHDOG_TIMER_INTERVAL 10
71 static struct app_watchdog_info {
74 } app_watchdog = { -1, -1 };
76 #define INIT_PROCESS_PID 1
78 static bool is_valid_window(const char *window_name, const char *app_state,
79 const struct proc_app_window_info *window)
82 _E("Window name cannot be NULL");
86 if (window->pid < INIT_PROCESS_PID) {
87 _E("window = %s, pid = %d", window_name, window->pid);
91 /* Focused app should be visible */
92 if (window->is_focused) {
93 if (window->visibility != 0 && window->visibility != 1) {
94 _I("Focused app should be visible."
95 "window = %s, is_focused = %d, visibility = %d",
96 window_name, window->is_focused,
102 if (app_state == NULL)
105 if (!strncmp(app_state, "fg", 3)) {
107 * Foreground app should be visible,
108 * but sometimes it does not guaranteed because of timing issue
110 if (window->visibility != 0 && window->visibility != 1) {
111 _I("Fg app (window = %s) must be visible.",
115 } else if (!strncmp(app_state, "bg", 3)) {
117 * Background app should not be focused,
118 * but sometimes it does not guaranteed because of timing issue
120 if (window->is_focused) {
121 _I("Bg app (window = %s) must not be focused.",
127 * Background app should not be visible,
128 * but sometimes it does not guaranteed because of timing issue
130 if (window->visibility == 0 || window->visibility == 1) {
131 _I("Bg app (window = %s) must not be visible.",
136 _I("Unknown app state = %s, window = %s",
137 app_state, window_name);
144 static int insert_window_in_window_table(GHashTable *window_table,
145 const struct proc_app_window_info *window)
147 struct proc_app_window_info *new_window;
148 struct proc_app_window_info *existing_window;
150 if (!window_table || !window) {
151 _E("window table and window cannot be NULL");
152 return RESOURCED_ERROR_INVALID_PARAMETER;
156 * A process (app) can have more than 1 window.
157 * In this case, resourced stores the most important window information
158 * into proc_app_info structure.
160 * Criterion for judging which window is the most important:
162 * If one of window has is_focused = 1, then it is the most important.
163 * Otherwise, the higher in the window stack, the more important window.
165 existing_window = g_hash_table_lookup(window_table, (gconstpointer) &window->pid);
166 if (existing_window && !window->is_focused)
167 return RESOURCED_ERROR_NONE;
169 new_window = calloc(1, sizeof(struct proc_app_window_info));
170 if (new_window == NULL) {
171 _E("Failed to alloc memory for new window");
172 return RESOURCED_ERROR_OUT_OF_MEMORY;
175 memcpy(new_window, window, sizeof(struct proc_app_window_info));
176 g_hash_table_insert(window_table, (gpointer) &new_window->pid,
177 (gpointer)new_window);
179 return RESOURCED_ERROR_NONE;
182 static int insert_window_info_in_proc_app_info(GHashTable *window_table)
184 struct proc_app_window_info *window;
185 struct proc_app_info *pai;
191 _E("window table can not be NULL");
192 return RESOURCED_ERROR_INVALID_PARAMETER;
195 g_hash_table_iter_init(&iter, window_table);
196 while (g_hash_table_iter_next(&iter, &pid, &value)) {
197 window = (struct proc_app_window_info *)value;
199 _E("Window strucutre can not be null (SIGABRT)");
203 pai = find_app_info(window->pid);
207 memcpy(&pai->window, window, sizeof(struct proc_app_window_info));
208 _D("app = %s, pid = %d, is_focused = %d, "
209 "visibility = %d, x = %d, y = %d, z = %d",
210 pai->appid, pai->window.pid,
211 pai->window.is_focused, pai->window.visibility,
212 pai->window.x, pai->window.y, pai->window.z);
215 return RESOURCED_ERROR_NONE;
218 static void free_window_stack(GVariantIter *iter, GVariant *reply,
219 GHashTable *window_table)
222 g_variant_iter_free(iter);
225 g_variant_unref(reply);
228 g_hash_table_remove_all(window_table);
231 static int dbus_update_window_stack(pid_t *pid, const char *app_state)
233 static GHashTable *window_table = NULL;
234 struct proc_app_window_info window;
235 GVariantIter *iter = NULL;
236 GVariant *reply = NULL;
241 if (!pid || !app_state) {
242 _E("It is impossible to parse pid or app status");
243 return RESOURCED_ERROR_INVALID_PARAMETER;
246 ret = d_bus_call_method_sync_gvariant_with_reply(WINDOW_SYSTEM_BUS_NAME,
247 WINDOW_SYSTEM_OBJECT_PATH, WINDOW_SYSTEM_INTERFACE_NAME,
248 GET_VISIBLE_WINDOW_INFO_V2, NULL, &reply);
250 _E("d_bus call fail");
251 return RESOURCED_ERROR_FAIL;
254 if (!g_variant_get_safe (reply, "(a("VISIBLE_WINDOW_INFO_V2_ARRAY_VALUE_TYPE"))",
256 _E("reply type is wrong");
257 goto error_to_parse_window_stack;
260 if (window_table == NULL) {
261 window_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, free);
262 g_assert(window_table);
265 while (g_variant_iter_loop(iter, "("VISIBLE_WINDOW_INFO_V2_VALUE_TYPE")",
266 &window.pid, &window.x, &window.y, &window.w, &window.h,
267 &window.is_transformed, &window.alpha, &window.opaque,
268 &window.visibility, &window.is_focused,
269 &window.is_mapped, &window.layer, &name)) {
275 is_same_pid = (*pid == window.pid);
276 if (!is_valid_window(name, is_same_pid ? app_state : NULL, &window))
277 goto error_to_parse_window_stack;
279 ret = insert_window_in_window_table(window_table, &window);
281 goto error_to_parse_window_stack;
285 * Validity of all windows in window stack is checked,
286 * so update proc_app_info structure of corresponding windows
288 ret = insert_window_info_in_proc_app_info(window_table);
290 goto error_to_parse_window_stack;
291 free_window_stack(iter, reply, window_table);
293 return RESOURCED_ERROR_NONE;
295 error_to_parse_window_stack:
296 free_window_stack(iter, reply, window_table);
298 return RESOURCED_ERROR_FAIL;
301 static void dbus_get_meminfo(GDBusMethodInvocation *invocation, GVariant *params)
303 unsigned int mem_total, mem_free, mem_available, cached, used;
304 unsigned int swap_total, swap_free, swap;
308 r = proc_get_meminfo(&mi,
309 MEMINFO_MASK_MEM_TOTAL |
310 MEMINFO_MASK_MEM_FREE |
311 MEMINFO_MASK_MEM_AVAILABLE |
312 MEMINFO_MASK_CACHED |
313 MEMINFO_MASK_SWAP_TOTAL |
314 MEMINFO_MASK_SWAP_FREE);
316 _E("Failed to get meminfo: %m");
317 D_BUS_REPLY_ERR(invocation);
321 mem_total = mi.value[MEMINFO_ID_MEM_TOTAL];
322 mem_free = mi.value[MEMINFO_ID_MEM_FREE];
323 mem_available = mi.value[MEMINFO_ID_MEM_AVAILABLE];
324 cached = mi.value[MEMINFO_ID_CACHED];
325 swap_total = mi.value[MEMINFO_ID_SWAP_TOTAL];
326 swap_free = mi.value[MEMINFO_ID_SWAP_FREE];
328 used = mem_total - mem_available;
329 swap = swap_total - swap_free;
331 _D("memory info total = %u, free = %u, cache = %u, used = %u, swap = %u",
332 mem_total, mem_free, cached, used, swap);
334 g_dbus_method_invocation_return_value(invocation, g_variant_new("(uuuuu)",
335 mem_total, mem_free, cached, used, swap));
338 static void dbus_reclaim_memory(GDBusMethodInvocation *invocation, GVariant *params)
340 _D("reclaiming memory!");
343 ok &= (RESOURCED_ERROR_NONE == proc_sys_node_trigger(SYS_VM_SHRINK_MEMORY));
344 ok &= (RESOURCED_ERROR_NONE == proc_sys_node_trigger(SYS_VM_COMPACT_MEMORY));
346 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL));
349 static void turn_off_proc_watchdog_handler()
351 /* Set the agent to something harmless. This destroys the previous
352 * state by losing information about the previous agent, though it's
353 * fine because the system is shutting down anyway and the "proper"
354 * way of doing this (iterate over all subdirectories and set their
355 * `notify_on_release` to 0) is bound to be slower than this. */
356 static const char AGENT_REPLACEMENT_PATH[] = "/bin/true";
357 if (fwrite_str(PROC_WATCHDOGCG_PATH "/" RELEASE_AGENT, AGENT_REPLACEMENT_PATH) == RESOURCED_ERROR_NONE) {
358 _I("disabled release agent by setting to %s", AGENT_REPLACEMENT_PATH);
362 /* Fallback: subvert the agent itself. This is somewhat dangerous
363 * as now the program does something else than expected but the
364 * system is shutting down and nobody else should use the agent
365 * anyway so there isn't much opportunity to cause any surprises. */
366 if (!mount(AGENT_REPLACEMENT_PATH, PROC_WATCHDOG_HANDLER_PATH, NULL, MS_BIND | MS_RDONLY, NULL)) {
367 _I("disabled release agent by bind mounting %s to %s", AGENT_REPLACEMENT_PATH, PROC_WATCHDOG_HANDLER_PATH);
371 _E("disabling release agent by bind mounting %s to %s failed; release agent is potentially still alive", AGENT_REPLACEMENT_PATH, PROC_WATCHDOG_HANDLER_PATH);
374 static void turn_off_proc_watchdog()
376 /* Turn off the "reboot on death" behaviour.
377 * It is normal for processes to die throughout a poweroff, while it
378 * is undesirable for the poweroff to be replaced by a reboot. */
379 turn_off_proc_watchdog_handler();
381 /* Unmounting the release cgroup does not make the above redundant because
382 * the unmounting can be done lazily and is not guaranteed to take place
384 umount2(PROC_WATCHDOGCG_PATH, MNT_FORCE | MNT_DETACH);
385 _I("disabled process by unmounting release cgroup");
388 static void proc_poweroff()
390 _D("pre power off: unmounting cgroup fs");
392 proc_sweep_memory(PROC_SWEEP_EXCLUDE_ACTIVE, INIT_PID);
393 resourced_notify(RESOURCED_NOTIFIER_POWER_OFF, NULL);
394 turn_off_proc_watchdog();
397 static void dbus_pre_poweroff(GDBusMethodInvocation *invocation, GVariant *params)
400 g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", -1));
403 static void dbus_get_checkappstatus(GDBusMethodInvocation *invocation, GVariant *params)
407 struct proc_app_info *pai;
408 char *appid = DEFAULT_APPID;
412 do_expr_unless_g_variant_get_typechecked(goto null_reply, params, "(i&s)", &pid, &type);
413 if (pid < 0 || type == NULL) {
414 _D("there is no message");
418 pai = find_app_info(pid);
420 _D("There is no appid %d", pid);
425 * allowed strings: normal, lcddim, lcdoff
426 * normal & lcddim : allow only UI application
427 * lcdoff : allow if it sends the excluding dbus signal
432 _D("wrong lock type : %s", type);
437 if (pai->app_watchdog_exclude || pai->runtime_exclude) {
438 _E("application (%d, %s) used %s lock longly but it is excluded", pid, appid, type);
442 if (!strncmp(type, "norm", 4) || !strncmp(type, "lcdd", 4)) {
443 if (pai->type == PROC_TYPE_SERVICE || pai->type == PROC_TYPE_READY ||
444 pai->type == PROC_TYPE_NONE)
446 } else if (!strncmp(type, "lcdo", 4)) {
451 _E("detect application locking %s lock longly : %d, %s", type, pid, appid);
453 _D("application locking %s lock longly but it seems normal : %d, %s", type, pid, appid);
456 g_dbus_method_invocation_return_value(invocation, g_variant_new("(iis)",
457 pid, detect, appid));
461 D_BUS_REPLY_ERR(invocation);
464 EXPORT_TEST void proc_dbus_active_signal_handler(GVariant *params)
470 do_expr_unless_g_variant_get_typechecked(return, params, "(&si)", &str, &pid);
471 if (!str || pid == 0) {
472 _D("there is no message");
476 if (!strncmp(str, "active", strlen("active")+1))
477 type = PROC_CGROUP_SET_ACTIVE;
478 else if (!strncmp(str, "inactive", strlen("inactive")+1))
479 type = PROC_CGROUP_SET_INACTIVE;
483 _D("received %s signal for pid %d", str, pid);
484 resourced_proc_status_change(type, pid, NULL, NULL, PROC_TYPE_NONE);
487 EXPORT_TEST void dbus_get_app_cpu(GDBusMethodInvocation *invocation, GVariant *params)
490 unsigned long total, utime, stime, starttime;
491 struct proc_app_info *pai = NULL;
493 do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&s)", &appid);
495 _E("Wrong message arguments!");
499 pai = find_app_info_by_appid(appid);
501 _E("There is no appid %s", appid);
505 if (proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime) != RESOURCED_ERROR_NONE) {
506 _E("proc_get_cpu_time = %s (%d)", appid, pai->main_pid);
510 _D("cpu usage of %s (%d), utime = %lu, stime = %lu", appid, pai->main_pid, utime, stime);
511 total = utime + stime;
513 g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", total));
517 D_BUS_REPLY_ERR(invocation);
520 EXPORT_TEST void dbus_get_app_memory(GDBusMethodInvocation *invocation, GVariant *params)
523 unsigned int usage = 0;
524 struct proc_app_info *pai = NULL;
526 do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&s)", &appid);
528 _E("Wrong message arguments!");
532 pai = find_app_info_by_appid(appid);
533 if (!pai || !pai->main_pid) {
534 _E("There is no appid %s", appid);
538 if (proc_get_mem_usage(pai->main_pid, &usage) < 0) {
539 _E("lowmem_get_proc_mem_usage failed for appid = %s (%d)",
540 appid, pai->main_pid);
544 _D("memory usage of %s (%d), rss = %u", appid, pai->main_pid, usage);
546 g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", usage));
550 D_BUS_REPLY_ERR(invocation);
553 EXPORT_TEST void dbus_get_memory_list(GDBusMethodInvocation *invocation, GVariant *params)
555 _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE;
558 struct proc_app_info *pai;
559 unsigned int usage = 0;
560 GVariantBuilder builder, *sub_builder;
562 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
563 sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
565 proc_app_list = proc_app_list_open();
566 gslist_for_each_item(giter, proc_app_list) {
567 pai = (struct proc_app_info *)giter->data;
568 if (!pai || !pai->main_pid)
570 if (proc_get_mem_usage(pai->main_pid, &usage) < 0)
575 g_variant_builder_add(sub_builder, "(su)", appid, usage);
577 g_variant_builder_add_value(&builder, g_variant_new("a(su)", sub_builder));
578 g_variant_builder_unref(sub_builder);
580 g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
583 EXPORT_TEST void dbus_get_cpu_list(GDBusMethodInvocation *invocation, GVariant *params)
585 _cleanup_app_list_close_ GSList *proc_app_list = PAL_INIT_VALUE;
588 struct proc_app_info *pai;
589 unsigned long uptime, utime, stime, deltatime, starttime;
591 GVariantBuilder builder, *sub_builder;
593 proc_app_list = proc_app_list_open();
595 ret = proc_get_uptime(&uptime);
597 _E("Failed to get uptime");
598 D_BUS_REPLY_ERR(invocation);
602 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
603 sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
605 gslist_for_each_item(giter, proc_app_list) {
606 unsigned long percent;
607 pai = (struct proc_app_info *)giter->data;
610 if (proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime) != RESOURCED_ERROR_NONE)
614 deltatime = uptime - pai->starttime;
618 percent = (utime + stime) / deltatime;
620 g_variant_builder_add(sub_builder, "(su)", appid, percent);
622 g_variant_builder_add_value(&builder, g_variant_new("a(su)", sub_builder));
623 g_variant_builder_unref(sub_builder);
625 g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
628 EXPORT_TEST void dbus_get_memory_lists(GDBusMethodInvocation *invocation, GVariant *params)
630 GSList *proc_app_list = PAL_INIT_VALUE;
634 struct proc_app_info *pai;
635 unsigned int usage = 0;
636 GVariantBuilder builder, *sub_builder;
638 do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &type);
639 if (type < 0 || type >= PROC_TYPE_MAX) {
640 _E("Wrong message arguments!");
644 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
645 sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
647 proc_app_list = proc_app_list_open();
648 gslist_for_each_item(giter, proc_app_list) {
649 pai = (struct proc_app_info *)giter->data;
650 if (!pai || !pai->main_pid)
652 if (type != PROC_TYPE_MAX && pai->type != type)
654 if (proc_get_mem_usage(pai->main_pid, &usage) < 0)
659 g_variant_builder_add(sub_builder, "(su)", appid, usage);
661 g_variant_builder_add_value(&builder, g_variant_new("a(su)", sub_builder));
662 g_variant_builder_unref(sub_builder);
664 g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
665 proc_app_list_close();
669 D_BUS_REPLY_ERR(invocation);
672 EXPORT_TEST void dbus_get_cpu_lists(GDBusMethodInvocation *invocation, GVariant *params)
674 GSList *proc_app_list = PAL_INIT_VALUE;
678 struct proc_app_info *pai;
679 unsigned long uptime, utime, stime, deltatime, starttime;
680 GVariantBuilder builder, *sub_builder;
682 do_expr_unless_g_variant_get_typechecked(goto failure, params, "(i)", &type);
683 if (type < 0 || type >= PROC_TYPE_MAX) {
684 _E("Wrong message arguments!");
688 ret = proc_get_uptime(&uptime);
690 _E("Failed to get uptime");
694 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
695 sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a(su)"));
697 proc_app_list = proc_app_list_open();
698 gslist_for_each_item(giter, proc_app_list) {
699 unsigned long percent;
700 pai = (struct proc_app_info *)giter->data;
703 if (type != PROC_TYPE_MAX && pai->type != type)
705 if (proc_get_cpu_time(pai->main_pid, &utime, &stime, &starttime) != RESOURCED_ERROR_NONE)
710 * cpu usage can be calculated using total usage of stime and utime out of delta time.
711 * cpu usage = (utime + stime ticks) / (current uptime - process start time) * 100 percentage
712 * = (utime + stime seconds) / (current uptime - process start time)
714 * Meanwhile, delta time between uptime and starttime should be checked
715 * whether it is zero or not.
716 * If delta time is zero, it can cause "divided by zero" fatal error.
718 deltatime = uptime - pai->starttime;
722 percent = (utime + stime) / deltatime;
724 g_variant_builder_add(sub_builder, "(su)", appid, percent);
726 g_variant_builder_add_value(&builder, g_variant_new("a(su)", sub_builder));
727 g_variant_builder_unref(sub_builder);
729 g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
730 proc_app_list_close();
734 D_BUS_REPLY_ERR(invocation);
737 static void dbus_get_get_ram_size(GDBusMethodInvocation *invocation, GVariant *params)
739 unsigned int total = MBYTE_TO_KBYTE(DEFAULT_RAMSIZE);
742 ret = proc_get_ram_total(&total);
744 _E("can't get ram total size. use default size");
746 g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", total));
749 EXPORT_TEST void proc_dbus_exclude_signal_handler(GVariant *params)
751 const char *str = NULL;
753 struct proc_exclude pe;
756 do_expr_unless_g_variant_get_typechecked(return, params, "(&si)", &str, &pid);
757 if (!str || pid == 0) {
758 _D("there is no message");
763 * allowed strings: wakeup, exclude, include
767 _D("%s signal on pid = %d", str, pid);
768 if (len == 6 && !strncmp(str, "wa", 2)) {
769 struct proc_status ps = {0};
771 ps.pai = find_app_info(pid);
773 resourced_notify(RESOURCED_NOTIFIER_APP_WAKEUP, &ps);
774 } else if (len == 7) {
775 if (!strncmp(str, "ex", 2)) {
777 pe.type = PROC_EXCLUDE;
778 resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
779 proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid));
780 } else if (!strncmp(str, "in", 2)) {
782 pe.type = PROC_INCLUDE;
783 resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
784 proc_set_runtime_exclude_list(pe.pid, pe.type, find_app_info(pe.pid));
790 EXPORT_TEST void proc_dbus_exclude_method_handler(GDBusMethodInvocation *invocation, GVariant *params)
792 const char *str = NULL;
795 do_expr_unless_g_variant_get_typechecked(goto failure, params, "(&si)", &str, &pid);
796 if (!str || pid == 0) {
797 _E("invalid parameters");
800 proc_dbus_exclude_signal_handler(params);
801 g_dbus_method_invocation_return_value(invocation, NULL);
805 g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
806 G_DBUS_ERROR_INVALID_ARGS, "invalid arguments");
809 EXPORT_TEST void proc_dbus_exclude_appid_signal_handler(GVariant *params)
813 struct proc_exclude pe;
815 struct proc_status ps = {0};
817 do_expr_unless_g_variant_get_typechecked(return, params, "(&s&s)", &str, &appid);
818 if (!str || !appid) {
819 _D("there is no message");
823 ps.pai = find_app_info_by_appid(appid);
825 _E("no entry of %s in app list", appid);
828 ps.pid = ps.pai->main_pid;
831 * allowed strings: wakeup, exclude, include
835 _D("%s signal on app = %s", str, appid);
836 if (len == 6 && !strncmp(str, "wa", 2)) {
837 resourced_notify(RESOURCED_NOTIFIER_APP_WAKEUP, &ps);
838 } else if (len == 7) {
839 if (!strncmp(str, "ex", 2)) {
841 pe.type = PROC_EXCLUDE;
842 resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
843 proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai);
844 } else if (!strncmp(str, "in", 2)) {
846 pe.type = PROC_INCLUDE;
847 resourced_notify(RESOURCED_NOTIFIER_CONTROL_EXCLUDE, &pe);
848 proc_set_runtime_exclude_list(pe.pid, pe.type, ps.pai);
854 static void proc_dbus_set_priority_signal_handler(GVariant *params)
858 struct proc_app_info *pai;
860 do_expr_unless_g_variant_get_typechecked(return, params, "(&si)", &str, &pid);
861 if (!str || pid < 0) {
862 _D("there is no message");
866 pai = find_app_info(pid);
867 if (pai && pai->app_cpu_nice_update_exclude)
870 _D("pid (%d) requested to change priority (%s)", pid, str);
871 if (!strncmp(str, "high", sizeof "high"))
872 setpriority(PRIO_PGRP, pid, -5);
873 else if (!strncmp(str, "default", sizeof "default"))
874 setpriority(PRIO_PGRP, pid, 0);
875 else if (!strncmp(str, "low", sizeof "low"))
876 setpriority(PRIO_PGRP, pid, 1);
878 _W("Warning: invalid set priority request (%s)!", str);
881 EXPORT_TEST void proc_dbus_prelaunch_signal_handler(GVariant *params)
887 struct proc_status ps;
888 struct proc_app_info *pai;
890 do_expr_unless_g_variant_get_typechecked(return, params, "(&s&sii)", &appid, &pkgid, &flags, &categories);
891 if (!appid || !pkgid || flags < 0 || categories < 0) {
892 _D("there is no message");
896 _D("call proc_dbus_prelaunch_handler: appid = %s, pkgid = %s, flags = %d,"
897 " categories = %X\n", appid, pkgid, flags, categories);
899 pai = proc_add_app_info(appid, pkgid, 0, flags, categories, PROC_TYPE_READY, PROC_STATE_DEFAULT);
901 resourced_notify(RESOURCED_NOTIFIER_APP_PRELAUNCH, &ps);
904 static void proc_dbus_sweep_signal_handler(GVariant *params)
906 proc_sweep_memory(PROC_SWEEP_INCLUDE_ACTIVE, INIT_PID);
909 static gboolean check_app_watchdog_cb(gpointer data)
911 int oom_score_adj = 0, ret;
912 pid_t pid = app_watchdog.pid;
914 ret = proc_get_oom_score_adj(pid, &oom_score_adj);
916 _E("app watchdog pid %d not terminated, kill again\n", pid);
917 safe_kill(pid, SIGKILL);
919 app_watchdog_check_timer = NULL;
920 app_watchdog.pid = -1;
921 app_watchdog.signum = -1;
926 static int proc_dbus_show_popup(const char *value)
928 char str_val[32]; // The original max size of represented string is 32
929 memcpy(str_val, value, sizeof str_val - 1);
930 str_val[sizeof str_val - 1] = '\0';
932 GVariantBuilder *const gv_builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}"));
933 g_variant_builder_add(gv_builder, "{ss}", WATCHDOG_KEY1, WATCHDOG_VALUE_1);
934 g_variant_builder_add(gv_builder, "{ss}", WATCHDOG_KEY2, str_val);
936 GVariant *const params = g_variant_new("(a{ss})", gv_builder);
937 g_variant_builder_unref(gv_builder);
939 int ret_val = d_bus_call_method_sync_gvariant(SYSTEM_POPUP_BUS_NAME, SYSTEM_POPUP_PATH_SYSTEM,
940 SYSTEM_POPUP_IFACE_SYSTEM, WATCHDOG_LAUNCHING_PARAM, params);
942 g_variant_unref(params);
947 static void proc_dbus_app_watchdog_handler(GVariant *params)
952 char appname[PROC_NAME_MAX];
953 struct proc_status ps;
955 do_expr_unless_g_variant_get_typechecked(return, params, "(ii)", &pid, &command);
956 if (pid < 0 || command < 0) {
957 _D("[WATCHDOG] there is no message");
961 result = proc_get_cmdline(pid, appname, sizeof appname);
962 if (result != RESOURCED_ERROR_NONE) {
963 _E("[WATCHDOG] ERROR : invalid pid(%d)", pid);
967 result = fixed_app_and_service_watchdog_action(appname, APP_TYPE);
968 if (result == PROC_ACTION_IGNORE) {
969 _I("[WATCHDOG] appname (%s), pid (%d) is watchdog excluded app", appname, pid);
973 if (current_lcd_state == LCD_STATE_OFF) {
974 _E("[WATCHDOG] Receive watchdog signal to pid: %d(%s) but don't show ANR popup in LCD off state\n", pid, appname);
978 _E("[WATCHDOG] Receive watchdog signal to app %s, pid %d\n", appname, pid);
979 ps.pai = find_app_info(pid);
981 resourced_notify(RESOURCED_NOTIFIER_APP_ANR, &ps);
983 if (proc_dbus_show_popup(appname) < 0)
984 _E("[WATCHDOG] Failed to show ANR popup");
986 if (app_watchdog_check_timer) {
987 if (app_watchdog.pid == pid) {
988 _E("[WATCHDOG] app %s, pid %d has already received watchdog siganl but not terminated", appname, pid);
989 safe_kill(pid, SIGKILL);
990 app_watchdog.pid = -1;
991 app_watchdog.signum = -1;
996 resourced_proc_status_change(PROC_CGROUP_SET_TERMINATE_REQUEST,
997 pid, NULL, NULL, PROC_TYPE_NONE);
998 safe_kill(pid, SIGABRT);
999 if (!app_watchdog_check_timer) {
1000 app_watchdog_check_timer = g_timeout_source_new_seconds(APP_WATCHDOG_TIMER_INTERVAL);
1001 g_source_set_callback(app_watchdog_check_timer, check_app_watchdog_cb, NULL, NULL);
1002 g_source_attach(app_watchdog_check_timer, NULL);
1004 app_watchdog.pid = pid;
1005 app_watchdog.signum = command;
1009 static void send_dump_signal(char *signal)
1011 pid_t pid = getpid();
1013 d_bus_broadcast_signal_gvariant(DUMP_SERVICE_OBJECT_PATH,
1014 DUMP_SERVICE_INTERFACE_NAME, signal,
1015 g_variant_new("(i)", pid));
1018 static void proc_dbus_dump_handler(GVariant *params)
1023 do_expr_unless_g_variant_get_typechecked(return, params, "(i&s)", &mode, &path);
1024 if (mode < 0 || !path) {
1025 _D("there is no message");
1029 _D("received dump request: path %s", path);
1030 send_dump_signal(SIGNAL_DUMP_START);
1031 resourced_proc_dump(mode, path);
1032 send_dump_signal(SIGNAL_DUMP_FINISH);
1035 static void proc_dbus_systemservice_handler(GVariant *params)
1039 do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &pid);
1041 _D("there is no message");
1045 resourced_proc_status_change(PROC_CGROUP_SET_SYSTEM_SERVICE, pid,
1046 NULL, NULL, PROC_TYPE_NONE);
1049 EXPORT_TEST void proc_dbus_lcd_on(GVariant *params)
1051 current_lcd_state = LCD_STATE_ON;
1055 EXPORT_TEST void proc_dbus_lcd_off(GVariant *params)
1057 current_lcd_state = LCD_STATE_OFF;
1060 EXPORT_TEST void booting_done_signal_handler(GVariant *params)
1063 modules_init_late(NULL);
1064 resourced_notify(RESOURCED_NOTIFIER_BOOTING_DONE, NULL);
1067 EXPORT_TEST void low_battery_signal_handler(GVariant *params)
1069 resourced_notify(RESOURCED_NOTIFIER_LOW_BATTERY, NULL);
1072 static void poweroff_signal_handler(GVariant *params)
1076 do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &response);
1078 /* This code does not check for values which could be too high.
1079 * This is for legacy reasons (we inherited the code without such
1080 * checks so potentially somebody might be using it that way). */
1081 if (response < POWER_OFF_DIRECT) {
1082 _D("Invalid power off status: %d", response);
1089 static void systemtime_changed_signal_handler(GVariant *params)
1091 resourced_notify(RESOURCED_NOTIFIER_SYSTEMTIME_CHANGED, NULL);
1094 EXPORT_TEST void proc_dbus_aul_launch(GVariant *params)
1097 int status, apptype;
1100 char *pkgtype = NULL;
1102 do_expr_unless_g_variant_get_typechecked(return, params, "(i&s&s&s)", &pid, &appid, &pkgid, &pkgtype);
1103 if (pid == 0 || !appid || !pkgid || !pkgtype) {
1104 _D("there is no message");
1109 _D("aul_launch: app %s, pkgd %s, pid %d, pkgtype %s",
1110 appid, pkgid, pid, pkgtype);
1113 if (!strncmp(pkgtype, "svc", 3)) {
1114 apptype = PROC_TYPE_SERVICE;
1115 status = PROC_CGROUP_SET_SERVICE_REQUEST;
1116 } else if (!strncmp(pkgtype, "ui", 2)) {
1117 apptype = PROC_TYPE_GUI;
1118 status = PROC_CGROUP_SET_LAUNCH_REQUEST;
1119 } else if (!strncmp(pkgtype, "widget", 6)) {
1120 apptype = PROC_TYPE_WIDGET;
1121 status = PROC_CGROUP_SET_LAUNCH_REQUEST;
1122 } else if (!strncmp(pkgtype, "watch", 5)) {
1123 apptype = PROC_TYPE_WATCH;
1124 status = PROC_CGROUP_SET_LAUNCH_REQUEST;
1128 resourced_proc_status_change(status, pid, appid, pkgid, apptype);
1131 EXPORT_TEST void proc_dbus_aul_resume(GVariant *params)
1134 int status = PROC_CGROUP_SET_RESUME_REQUEST, apptype;
1137 char *pkgtype = NULL;
1139 do_expr_unless_g_variant_get_typechecked(return, params, "(i&s&s&s)", &pid, &appid, &pkgid, &pkgtype);
1140 if (pid == 0 || !appid || !pkgid || !pkgtype) {
1141 _D("there is no message");
1145 if (!strncmp(pkgtype, "svc", 3))
1146 apptype = PROC_TYPE_SERVICE;
1147 else if (!strncmp(pkgtype, "widget", 6))
1148 apptype = PROC_TYPE_WIDGET;
1149 else if (!strncmp(pkgtype, "watch", 5))
1150 apptype = PROC_TYPE_WATCH;
1152 apptype = PROC_TYPE_GUI;
1154 resourced_proc_status_change(status, pid, appid, pkgid, apptype);
1157 EXPORT_TEST void proc_dbus_aul_terminate(GVariant *params)
1160 int status = PROC_CGROUP_SET_TERMINATE_REQUEST;
1163 char *pkgtype = NULL;
1165 do_expr_unless_g_variant_get_typechecked(return, params, "(i&s&s&s)", &pid, &appid, &pkgid, &pkgtype);
1166 if (pid == 0 || !appid || !pkgid || !pkgtype) {
1167 _D("there is no message");
1171 resourced_proc_status_change(status, pid, appid, pkgid, PROC_TYPE_NONE);
1174 EXPORT_TEST void proc_dbus_aul_changestate(GVariant *params)
1177 int status, apptype;
1180 char *statstr = NULL;
1181 char *pkgtype = NULL;
1183 do_expr_unless_g_variant_get_typechecked(return, params, "(i&s&s&s&s)", &pid, &appid, &pkgid, &statstr, &pkgtype);
1184 if (pid == 0 || !appid || !pkgid || !statstr || !pkgtype) {
1185 _D("there is no message");
1189 if (!strncmp(statstr, "fg", 2))
1190 status = PROC_CGROUP_SET_FOREGRD;
1191 else if (!strncmp(statstr, "bg", 2))
1192 status = PROC_CGROUP_SET_BACKGRD;
1196 if (!strncmp(pkgtype, "svc", 3))
1197 apptype = PROC_TYPE_SERVICE;
1198 else if (!strncmp(pkgtype, "widget", 6))
1199 apptype = PROC_TYPE_WIDGET;
1200 else if (!strncmp(pkgtype, "watch", 5))
1201 apptype = PROC_TYPE_WATCH;
1203 apptype = PROC_TYPE_GUI;
1205 resourced_proc_status_change(status, pid, appid, pkgid, apptype);
1206 dbus_update_window_stack(&pid, statstr);
1209 EXPORT_TEST void proc_dbus_aul_group(GVariant *params)
1215 do_expr_unless_g_variant_get_typechecked(return, params, "(ii&s)", &ownerpid, &childpid, &appid);
1216 if (ownerpid == 0 || childpid == 0 || !appid) {
1217 _D("there is no message");
1221 if (ownerpid == childpid) {
1222 _I("specific case, one application %d makes multiple window. skip to merge", ownerpid);
1226 _D("received process grouping : owner %d, child %d, previous appid %s",
1227 ownerpid, childpid, appid);
1228 proc_set_group(ownerpid, childpid, appid);
1231 EXPORT_TEST void proc_dbus_aul_terminated(GVariant *params)
1234 int status = PROC_CGROUP_SET_TERMINATED;
1236 do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &pid);
1238 _D("there is no message");
1242 resourced_proc_status_change(status, pid, NULL, NULL, PROC_TYPE_NONE);
1245 EXPORT_TEST void proc_dbus_suspend_hint(GVariant *params)
1248 struct proc_app_info *pai = NULL;
1249 struct proc_status ps = {0};
1250 enum proc_state state;
1252 do_expr_unless_g_variant_get_typechecked(return, params, "(i)", &pid);
1254 _D("there is no message");
1258 pai = find_app_info(pid);
1263 _D("received suspend hint : app %s, pid %d",
1266 _D("received suspend hint : pid %d", pid);
1268 state = proc_check_suspend_state(pai);
1269 if (state == PROC_STATE_SUSPEND) {
1272 resourced_notify(RESOURCED_NOTIFIER_APP_SUSPEND,
1277 static const char dbus_methods_xml[] =
1279 " <interface name='"RESOURCED_INTERFACE_PROCESS"'>"
1280 " <method name='GetAppCpu'>"
1281 " <arg type='s' name='Appid' direction='in'/>"
1282 " <arg type='u' name='CpuUsage' direction='out'/>"
1284 " <method name='GetCpuList'>"
1285 " <arg type='a(su)' name='PidWithCpuUsagePercent' direction='out'/>"
1287 " <method name='GetCpuLists'>"
1288 " <arg type='i' name='AppType' direction='in'/>"
1289 " <arg type='a(su)' name='UsagePercent' direction='out'/>"
1291 " <method name='GetAppMemory'>"
1292 " <arg type='s' name='Appid' direction='in'/>"
1293 " <arg type='u' name='MemoryUsage' direction='out'/>"
1295 " <method name='GetMemoryList'>"
1296 " <arg type='a(su)' name='PidWithMemoryUsage' direction='out'/>"
1298 " <method name='GetMemoryLists'>"
1299 " <arg type='i' name='AppType' direction='in'/>"
1300 " <arg type='a(su)' name='PidWithMemoryUsage' direction='out'/>"
1302 " <method name='GetMemInfo'>"
1303 " <arg type='u' name='MemTotal' direction='out'/>"
1304 " <arg type='u' name='MemFree' direction='out'/>"
1305 " <arg type='u' name='MemCached' direction='out'/>"
1306 " <arg type='u' name='MemUsed' direction='out'/>"
1307 " <arg type='u' name='MemSwap' direction='out'/>"
1309 " <method name='ReclaimMemory'>"
1310 " <arg type='i' name='ZeroOnSuccess' direction='out'/>"
1312 " <method name='PrePoweroff'>"
1313 " <arg type='i' name='MinusOne' direction='out'/>"
1315 " <method name='ProcExclude'>"
1316 " <arg type='s' name='Action' direction='in'/>"
1317 " <arg type='i' name='PID' direction='in'/>"
1319 /* Following functions are defined in proc-usage-stats.c */
1320 " <method name='ProcMemoryUsage'>"
1321 " <arg type='ai' name='ProcList' direction='in'/>"
1322 " <arg type='a(iiiiiii)' name='MemoryUsage' direction='out'/>"
1324 " <method name='ProcCpuUsage'>"
1325 " <arg type='ai' name='ProcList' direction='in'/>"
1326 " <arg type='a(ii)' name='CpuUsage' direction='out'/>"
1328 " <method name='ProcSwapUsage'>"
1329 " <arg type='ai' name='ProcList' direction='in'/>"
1330 " <arg type='a(i)' name='SwapUsage' direction='out'/>"
1332 " <method name='CheckAppStatus'>"
1333 " <arg type='i' name='Pid' direction='in'/>"
1334 " <arg type='s' name='Type' direction='in'/>"
1335 " <arg type='i' name='Pid' direction='out'/>"
1336 " <arg type='i' name='Detect' direction='out'/>"
1337 " <arg type='s' name='Appid' direction='out'/>"
1339 " <method name='GetRamSize'>"
1340 " <arg type='u' name='TotalSizeKB' direction='out'/>"
1345 static struct d_bus_method dbus_methods[] = {
1346 { "GetAppCpu", dbus_get_app_cpu },
1347 { "GetCpuList", dbus_get_cpu_list },
1348 { "GetCpuLists", dbus_get_cpu_lists },
1349 { "GetAppMemory", dbus_get_app_memory },
1350 { "GetMemoryList", dbus_get_memory_list },
1351 { "GetMemoryLists", dbus_get_memory_lists },
1352 { "GetMemInfo", dbus_get_meminfo },
1353 { "ReclaimMemory", dbus_reclaim_memory },
1354 { "PrePoweroff", dbus_pre_poweroff },
1355 { "ProcExclude", proc_dbus_exclude_method_handler},
1356 /* Following functions are defined in proc-usage-stats.c */
1357 { "ProcMemoryUsage", dbus_proc_memory_usage },
1358 { "ProcCpuUsage", dbus_proc_cpu_usage },
1359 { "CheckAppStatus", dbus_get_checkappstatus },
1360 { "GetRamSize", dbus_get_get_ram_size },
1361 { "ProcSwapUsage", dbus_proc_swap_usage },
1362 /* Add methods here */
1365 static const struct d_bus_signal dbus_signals[] = {
1366 /* RESOURCED DBUS */
1367 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1368 SIGNAL_PROC_ACTIVE, proc_dbus_active_signal_handler, NULL},
1369 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1370 SIGNAL_PROC_EXCLUDE, proc_dbus_exclude_signal_handler, NULL},
1371 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1372 SIGNAL_PROC_PRELAUNCH, proc_dbus_prelaunch_signal_handler, NULL},
1373 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1374 SIGNAL_PROC_SWEEP, proc_dbus_sweep_signal_handler, NULL},
1375 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1376 SIGNAL_PROC_WATCHDOG, proc_dbus_app_watchdog_handler, NULL},
1377 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1378 SIGNAL_PROC_SYSTEMSERVICE, proc_dbus_systemservice_handler, NULL},
1379 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1380 SIGNAL_PROC_EXCLUDEAPPID, proc_dbus_exclude_appid_signal_handler, NULL},
1381 {RESOURCED_PATH_PROCESS, RESOURCED_INTERFACE_PROCESS,
1382 SIGNAL_PROC_SET_PRIORITY, proc_dbus_set_priority_signal_handler, NULL},
1385 {DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
1386 SIGNAL_DEVICED_LCDON, proc_dbus_lcd_on, NULL},
1387 {DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
1388 SIGNAL_DEVICED_LCDOFF, proc_dbus_lcd_off, NULL},
1389 /* DEVICED_INTERFACE_POWEROFF / SIGNAL_DEVICED_CHANGESTATE left unhandled
1390 on purpose - DeviceD sends the signal earlier than supposed to. Nothing
1391 is lost though because at some point DeviceD also sends a SIGTERM,
1392 which is handled the same way (i.e. quits the main loop). */
1393 {DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF,
1394 SIGNAL_DEVICED_POWEROFF_STATE, poweroff_signal_handler, NULL},
1395 {DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY,
1396 SIGNAL_DEVICED_LOW_BATTERY, low_battery_signal_handler, NULL},
1397 {DUMP_SERVICE_OBJECT_PATH, DUMP_SERVICE_INTERFACE_NAME,
1398 SIGNAL_DUMP, proc_dbus_dump_handler, NULL},
1399 {DEVICED_PATH_TIME, DEVICED_INTERFACE_TIME,
1400 SIGNAL_DEVICED_SYSTEMTIME_CHANGED,
1401 systemtime_changed_signal_handler, NULL},
1404 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1405 SIGNAL_AMD_LAUNCH, proc_dbus_aul_launch, NULL},
1406 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1407 SIGNAL_AMD_RESUME, proc_dbus_aul_resume, NULL},
1408 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1409 SIGNAL_AMD_TERMINATE, proc_dbus_aul_terminate, NULL},
1410 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1411 SIGNAL_AMD_STATE, proc_dbus_aul_changestate, NULL},
1412 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1413 SIGNAL_AMD_GROUP, proc_dbus_aul_group, NULL},
1414 {AUL_APPSTATUS_OBJECT_PATH, AUL_APPSTATUS_INTERFACE_NAME,
1415 SIGNAL_AMD_TERMINATED, proc_dbus_aul_terminated, NULL},
1416 {AUL_SUSPEND_OBJECT_PATH, AUL_SUSPEND_INTERFACE_NAME,
1417 SIGNAL_AMD_SUSPNED, proc_dbus_suspend_hint, NULL},
1420 {BOOTING_DONE_PATH, BOOTING_DONE_INTERFACE,
1421 SIGNAL_BOOTING_DONE, booting_done_signal_handler, NULL},
1424 static int proc_dbus_init(void *data)
1426 resourced_ret_c ret;
1428 /* start watchdog check timer for preveting ANR during booting */
1429 app_watchdog_check_timer = g_timeout_source_new_seconds(APP_WATCHDOG_TIMER_INTERVAL);
1430 g_source_set_callback(app_watchdog_check_timer, check_app_watchdog_cb, NULL, NULL);
1431 g_source_attach(app_watchdog_check_timer, NULL);
1433 ret = d_bus_register_signals(dbus_signals, ARRAY_SIZE(dbus_signals));
1434 if (ret != RESOURCED_ERROR_NONE)
1437 ret = d_bus_register_methods(RESOURCED_PATH_PROCESS, dbus_methods_xml,
1438 dbus_methods, ARRAY_SIZE(dbus_methods));
1443 static int proc_dbus_exit(void *data)
1445 if (app_watchdog_check_timer)
1446 g_source_destroy(app_watchdog_check_timer);
1447 return RESOURCED_ERROR_NONE;
1450 static const struct proc_module_ops proc_dbus_ops = {
1451 .name = "PROC_DBUS",
1452 .init = proc_dbus_init,
1453 .exit = proc_dbus_exit,
1455 PROC_MODULE_REGISTER(&proc_dbus_ops)