From d447d111f225aec6526ee94b1fab5afa9f0242de Mon Sep 17 00:00:00 2001 From: Nishant Chaprana Date: Thu, 17 Aug 2017 19:38:03 +0530 Subject: [PATCH] Added netlink connector for monitoring processes Change-Id: I43335ff9d4daf2ca0d01decb29d7837a8f76af9c Signed-off-by: Nishant Chaprana --- packaging/stc-manager.spec | 2 +- src/helper/helper-procfs.c | 165 +++++++ src/helper/helper-procfs.h | 63 +++ ...ication-lifecycle.h => stc-app-ground-status.h} | 10 +- src/monitor/include/stc-app-lifecycle.h | 44 ++ src/monitor/stc-app-ground-status.c | 147 ++++++ src/monitor/stc-app-lifecycle.c | 508 +++++++++++++++++++++ src/monitor/stc-application-lifecycle.c | 458 ------------------- src/stc-manager-gdbus.c | 6 +- src/stc-manager.c | 3 + 10 files changed, 939 insertions(+), 467 deletions(-) create mode 100644 src/helper/helper-procfs.c create mode 100644 src/helper/helper-procfs.h rename src/monitor/include/{stc-application-lifecycle.h => stc-app-ground-status.h} (74%) create mode 100755 src/monitor/include/stc-app-lifecycle.h create mode 100755 src/monitor/stc-app-ground-status.c create mode 100755 src/monitor/stc-app-lifecycle.c delete mode 100755 src/monitor/stc-application-lifecycle.c diff --git a/packaging/stc-manager.spec b/packaging/stc-manager.spec index a15bc75..66b9d54 100644 --- a/packaging/stc-manager.spec +++ b/packaging/stc-manager.spec @@ -1,6 +1,6 @@ Name: stc-manager Summary: STC(Smart Traffic Control) manager -Version: 0.0.28 +Version: 0.0.29 Release: 0 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/src/helper/helper-procfs.c b/src/helper/helper-procfs.c new file mode 100644 index 0000000..0974f2a --- /dev/null +++ b/src/helper/helper-procfs.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * @file procfs.c + * @desc wrapper for reading profs information. + * + * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stc-error.h" +#include "stc-manager-util.h" +#include "helper-procfs.h" + +int proc_get_cmdline(pid_t pid, char *cmdline) +{ + char buf[PROC_BUF_MAX]; + char cmdline_buf[PROC_NAME_MAX]; + char *filename; + FILE *fp; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + fp = fopen(buf, "r"); + if (fp == NULL) + return STC_ERROR_FAIL; + + if (fgets(cmdline_buf, PROC_NAME_MAX-1, fp) == NULL) { + fclose(fp); + return STC_ERROR_FAIL; + } + fclose(fp); + + filename = strrchr(cmdline_buf, '/'); + if (filename == NULL) + filename = cmdline_buf; + else + filename = filename + 1; + + strncpy(cmdline, filename, PROC_NAME_MAX-1); + + return STC_ERROR_NONE; +} + +pid_t find_pid_from_cmdline(char *cmdline) +{ + pid_t pid = -1, foundpid = -1; + int ret = 0; + DIR *dp; + struct dirent *dentry; + char appname[PROC_NAME_MAX]; + + dp = opendir("/proc"); + if (!dp) { + STC_LOGE("BACKGRD MANAGE : fail to open /proc"); + return STC_ERROR_FAIL; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + pid = atoi(dentry->d_name); + if (!pid) + continue; + ret = proc_get_cmdline(pid, appname); + if (ret == STC_ERROR_NONE) { + if (!strncmp(cmdline, appname, strlen(appname)+1)) { + foundpid = pid; + break; + } + } + } + closedir(dp); + return foundpid; +} + +int proc_get_label(pid_t pid, char *label) +{ + char buf[PROC_BUF_MAX]; + FILE *fp; + + snprintf(buf, sizeof(buf), "/proc/%d/attr/current", pid); + fp = fopen(buf, "r"); + if (fp == NULL) + return STC_ERROR_FAIL; + + if (fgets(label, PROC_NAME_MAX-1, fp) == NULL) { + fclose(fp); + return STC_ERROR_FAIL; + } + fclose(fp); + return STC_ERROR_NONE; +} + +int proc_get_exepath(pid_t pid, char *buf, int len) +{ + char path[PROC_BUF_MAX]; + int ret = 0; + + snprintf(path, sizeof(path), "/proc/%d/exe", pid); + ret = readlink(path, buf, len-1); + if (ret > 0) + buf[ret] = '\0'; + else + buf[0] = '\0'; + return STC_ERROR_NONE; +} + +static int proc_get_data(char *path, char *buf, int len) +{ + _cleanup_close_ int fd = -1; + int ret; + + fd = open(path, O_RDONLY); + if (fd < 0) + return STC_ERROR_FAIL; + + ret = read(fd, buf, len-1); + if (ret < 0) { + buf[0] = '\0'; + return STC_ERROR_FAIL; + } + buf[ret] = '\0'; + return STC_ERROR_NONE; +} + +int proc_get_raw_cmdline(pid_t pid, char *buf, int len) +{ + char path[PROC_BUF_MAX]; + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + return proc_get_data(path, buf, len); +} + +int proc_get_status(pid_t pid, char *buf, int len) +{ + char path[PROC_BUF_MAX]; + snprintf(path, sizeof(path), "/proc/%d/status", pid); + return proc_get_data(path, buf, len); +} diff --git a/src/helper/helper-procfs.h b/src/helper/helper-procfs.h new file mode 100644 index 0000000..4f0fd02 --- /dev/null +++ b/src/helper/helper-procfs.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __HELPER_PROCFS_H__ +#define __HELPER_PROCFS_H__ + +#include + +#define PROC_BUF_MAX 64 + +/** + * @desc get command line from /proc/{pid}/cmdline + * @return negative value if error + */ +int proc_get_cmdline(pid_t pid, char *cmdline); + +/** + * @desc find pid with /proc/{pid}/cmdline + * it returns first entry when many pids have same cmdline + * @return negative value if error + */ +pid_t find_pid_from_cmdline(char *cmdline); + +/** + * @desc get smack subject label from /proc/{pid}/attr/current + * this label can indicate package name about child processes + * @return negative value if error or pid doesn't exist + */ +int proc_get_label(pid_t pid, char *label); + +/** + * @desc get command line from /proc/{pid}/cmdline without any truncation + * @return negative value if error + */ +int proc_get_raw_cmdline(pid_t pid, char *buf, int len); + +/** + * @desc get symblolic link about /proc/{pid}/exe + * @return negative value if error + */ +int proc_get_exepath(pid_t pid, char *buf, int len); + +/** + * @desc get status from /proc/{pid}/status + * @return negative value if error + */ +int proc_get_status(pid_t pid, char *buf, int len); + +#endif /*__HELPER_PROCFS_H__*/ diff --git a/src/monitor/include/stc-application-lifecycle.h b/src/monitor/include/stc-app-ground-status.h similarity index 74% rename from src/monitor/include/stc-application-lifecycle.h rename to src/monitor/include/stc-app-ground-status.h index 8fa34af..fb02abc 100755 --- a/src/monitor/include/stc-application-lifecycle.h +++ b/src/monitor/include/stc-app-ground-status.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef __STC_APPLICATION_LIFECYCLE_H__ -#define __STC_APPLICATION_LIFECYCLE_H__ +#ifndef __STC_APP_GROUND_STATUS_H__ +#define __STC_APP_GROUND_STATUS_H__ #include "stc-error.h" #include "stc-manager.h" @@ -23,7 +23,7 @@ #include "stc-manager-util.h" #include "stc-monitor.h" -stc_error_e stc_application_lifecycle_monitor_init(stc_s *stc); -stc_error_e stc_application_lifecycle_monitor_deinit(stc_s *stc); +stc_error_e stc_app_ground_status_monitor_init(stc_s *stc); +stc_error_e stc_app_ground_status_monitor_deinit(stc_s *stc); -#endif /* __STC_APPLICATION_LIFECYCLE_H__ */ +#endif /* __STC_APP_GROUND_STATUS_H__ */ diff --git a/src/monitor/include/stc-app-lifecycle.h b/src/monitor/include/stc-app-lifecycle.h new file mode 100755 index 0000000..fae72ec --- /dev/null +++ b/src/monitor/include/stc-app-lifecycle.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __STC_APP_LIFECYCLE_H__ +#define __STC_APP_LIFECYCLE_H__ + +#include "stc-error.h" +#include "stc-manager.h" +#include "stc-manager-gdbus.h" +#include "stc-manager-util.h" +#include "stc-monitor.h" + +typedef enum { + STC_CMD_NONE, + STC_CMD_SET_FOREGRD, + STC_CMD_SET_BACKGRD, + STC_CMD_SET_APP_LAUNCHED, + STC_CMD_SET_SERVICE_LAUNCHED, + STC_CMD_SET_TERMINATED, + STC_CMD_MAX_ELEM +} stc_cmd_type_e; + +stc_error_e stc_manager_app_status_changed(stc_cmd_type_e cmd, + pid_t pid, + gchar *app_id, + gchar *pkg_id, + stc_app_type_e app_type); +void stc_app_lifecycle_monitor_init(void); +void stc_app_lifecycle_monitor_deinit(void); + +#endif /* __STC_APP_LIFECYCLE_H__ */ diff --git a/src/monitor/stc-app-ground-status.c b/src/monitor/stc-app-ground-status.c new file mode 100755 index 0000000..a5c24ec --- /dev/null +++ b/src/monitor/stc-app-ground-status.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stc-app-lifecycle.h" +#include "stc-app-ground-status.h" + +/* + * AUL + */ +#define AUL_APP_STATUS_DBUS_PATH "/Org/Tizen/Aul/AppStatus" +#define AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE "org.tizen.aul.AppStatus" +#define AUL_APP_STATUS_BUS_NAME AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE + +#define AUL_APP_STATUS_DBUS_STATUS_CHANGE "AppStatusChange" +#define AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE "(issss)" + +typedef struct { + guint sub_id; + const gchar *path; + const gchar *interface; + const gchar *member; + const gchar *param_type; + GDBusSignalCallback callback; + gpointer user_data; +} signal_map_s; + +static void __stc_gdbus_handle_aul_changestate(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + __STC_LOG_FUNC_ENTER__; + pid_t pid; + stc_cmd_type_e status; + stc_app_type_e apptype; + gchar *appid, *pkgid, *statstr, *pkgtype; + + RETURN_IF_DBUS_TYPE_MISMATCH(parameters, + AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE); + + g_variant_get(parameters, AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE, + &pid, &appid, &pkgid, &statstr, &pkgtype); + + if (!strncmp(statstr, "fg", 2)) { + status = STC_CMD_SET_FOREGRD; + } else if (!strncmp(statstr, "bg", 2)) { + status = STC_CMD_SET_BACKGRD; + } else { + __STC_LOG_FUNC_EXIT__; + goto handle_error; + } + + if (!strncmp(pkgtype, "svc", 3)) + apptype = STC_APP_TYPE_SERVICE; + else if (!strncmp(pkgtype, "widget", 6)) + apptype = STC_APP_TYPE_WIDGET; + else if (!strncmp(pkgtype, "watch", 5)) + apptype = STC_APP_TYPE_WATCH; + else + apptype = STC_APP_TYPE_GUI; + + stc_manager_app_status_changed(status, pid, appid, pkgid, apptype); + + __STC_LOG_FUNC_EXIT__; +handle_error: + FREE(appid); + FREE(pkgid); + FREE(statstr); + FREE(pkgtype); +} + +signal_map_s signal_map[] = { + + /* AMD DBUS */ + { + 0, + AUL_APP_STATUS_DBUS_PATH, + AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE, + AUL_APP_STATUS_DBUS_STATUS_CHANGE, + AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE, + __stc_gdbus_handle_aul_changestate, + NULL + }, + { + 0, + NULL, + NULL, + NULL, + NULL + } +}; + +stc_error_e stc_app_ground_status_monitor_init(stc_s *stc) +{ + guint i = 0; + ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data"); + + for (i = 0; signal_map[i].member != NULL; i++) { + signal_map[i].sub_id = + stc_manager_gdbus_subscribe_signal(stc->connection, + NULL, + signal_map[i].interface, + signal_map[i].member, + signal_map[i].path, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + signal_map[i].callback, + signal_map[i].user_data, + NULL); + STC_LOGI("Successfully subscribed [%s] signal", + signal_map[i].member); + } + + return STC_ERROR_NONE; +} + +stc_error_e stc_app_ground_status_monitor_deinit(stc_s *stc) +{ + guint i = 0; + ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data"); + + for (i = 0; signal_map[i].member != NULL; i++) { + stc_manager_gdbus_unsubscribe_signal(stc->connection, + signal_map[i].sub_id); + signal_map[i].sub_id = 0; + STC_LOGD("Successfully unsubscribed [%s] signal", + signal_map[i].member); + } + + return STC_ERROR_NONE; +} diff --git a/src/monitor/stc-app-lifecycle.c b/src/monitor/stc-app-lifecycle.c new file mode 100755 index 0000000..6036098 --- /dev/null +++ b/src/monitor/stc-app-lifecycle.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stc-app-lifecycle.h" +#include "helper-procfs.h" + +typedef struct { + pid_t pid; +} proc_key_s; + +typedef struct { + char cmdline[PROC_NAME_MAX]; + char status[PROC_BUF_MAX]; +} proc_value_s; + +typedef struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + enum proc_cn_mcast_op cn_mcast; + }; +} nl_connector_msg_s; + +typedef struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + struct proc_event proc_ev; + }; +} nl_connector_proc_event_s; + +static int nl_connector_sock = -1; +static guint nl_connector_gsource_id = 0; +static GTree *proc_tree; + + +static gboolean __process_nl_connector_message(GIOChannel *source, + GIOCondition condition, + gpointer user_data); + +static int __proc_tree_key_compare(gconstpointer a, gconstpointer b, + gpointer UNUSED user_data) +{ + proc_key_s *key_a = (proc_key_s *)a; + proc_key_s *key_b = (proc_key_s *)b; + + return key_a->pid - key_b->pid; +} + +static void __proc_tree_value_free(gpointer data) +{ + proc_value_s *value = (proc_value_s *)data; + + FREE(value); +} + +static void __proc_tree_key_free(gpointer data) +{ + proc_key_s *key = (proc_key_s *)data; + + FREE(key); +} + +static proc_value_s * __proc_tree_lookup(const proc_key_s *key) +{ + proc_value_s *lookup; + + if (proc_tree == NULL) { + STC_LOGE("tree is null"); + return NULL; + } + + lookup = g_tree_lookup(proc_tree, key); + return lookup; +} + +static void __proc_tree_add(proc_key_s *key, + proc_value_s *value) +{ + if (proc_tree == NULL) { + STC_LOGE("tree is null"); + return; + } + + g_tree_insert(proc_tree, key, value); + + stc_manager_app_status_changed(STC_CMD_SET_SERVICE_LAUNCHED, key->pid, + value->cmdline, value->cmdline, + STC_APP_TYPE_SERVICE); +} + +static void __proc_tree_remove(const proc_key_s *key) +{ + if (proc_tree == NULL) { + STC_LOGE("tree is null"); + return; + } + + stc_manager_app_status_changed(STC_CMD_SET_TERMINATED, key->pid, NULL, + NULL, STC_APP_TYPE_NONE); + g_tree_remove(proc_tree, key); +} + +static void __open_nl_connector_sock(void) +{ + __STC_LOG_FUNC_ENTER__; + GIOChannel *gio = NULL; + + if (nl_connector_sock != -1 && + nl_connector_gsource_id != 0) { + STC_LOGE("Socket is already open"); + __STC_LOG_FUNC_EXIT__; + return; + } + + if (nl_connector_sock != -1) { + close(nl_connector_sock); + nl_connector_sock = -1; + } + + if (nl_connector_gsource_id != 0) { + g_source_remove(nl_connector_gsource_id); + nl_connector_gsource_id = 0; + } + + nl_connector_sock = create_netlink(NETLINK_CONNECTOR, CN_IDX_PROC); + if (nl_connector_sock == -1) { + __STC_LOG_FUNC_EXIT__; + return; + } + + gio = g_io_channel_unix_new(nl_connector_sock); + nl_connector_gsource_id = + g_io_add_watch(gio, G_IO_IN | G_IO_ERR | G_IO_HUP, + (GIOFunc) __process_nl_connector_message, + NULL); + g_io_channel_unref(gio); + __STC_LOG_FUNC_EXIT__; +} + +static void __close_nl_connector_sock(void) +{ + __STC_LOG_FUNC_ENTER__; + if (nl_connector_sock != -1) { + close(nl_connector_sock); + nl_connector_sock = -1; + } + + if (nl_connector_gsource_id != 0) { + g_source_remove(nl_connector_gsource_id); + nl_connector_gsource_id = 0; + } + __STC_LOG_FUNC_EXIT__; +} + +static void __reopen_nl_connector_sock(void) +{ + __close_nl_connector_sock(); + __open_nl_connector_sock(); +} + +stc_error_e stc_manager_app_status_changed(stc_cmd_type_e cmd, + pid_t pid, + gchar *app_id, + gchar *pkg_id, + stc_app_type_e app_type) +{ + __STC_LOG_FUNC_ENTER__; + stc_error_e ret = STC_ERROR_NONE; + + switch (cmd) { + case STC_CMD_SET_FOREGRD: + { + stc_app_key_s app_key; + stc_app_value_s app_value; + stc_process_key_s proc_key; + stc_process_value_s proc_value; + + memset(&app_key, 0, sizeof(stc_app_key_s)); + memset(&app_value, 0, sizeof(stc_app_value_s)); + memset(&proc_key, 0, sizeof(stc_process_key_s)); + memset(&proc_value, 0, sizeof(stc_process_value_s)); + + app_key.pkg_id = g_strdup(pkg_id); + app_key.app_id = g_strdup(app_id); + + app_value.type = app_type; + app_value.processes = NULL; + + proc_key.pid = pid; + + proc_value.ground = STC_APP_STATE_FOREGROUND; + + stc_monitor_application_add(app_key, app_value); + stc_monitor_process_add(app_key, proc_key, proc_value); + stc_monitor_process_update_ground(app_key, proc_key, + STC_APP_STATE_FOREGROUND); + + FREE(app_key.pkg_id); + FREE(app_key.app_id); + break; + } + case STC_CMD_SET_BACKGRD: + { + stc_app_key_s app_key; + stc_app_value_s app_value; + stc_process_key_s proc_key; + stc_process_value_s proc_value; + + memset(&app_key, 0, sizeof(stc_app_key_s)); + memset(&app_value, 0, sizeof(stc_app_value_s)); + memset(&proc_key, 0, sizeof(stc_process_key_s)); + memset(&proc_value, 0, sizeof(stc_process_value_s)); + + app_key.pkg_id = g_strdup(pkg_id); + app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX, + NULL); + + app_value.type = app_type; + app_value.processes = NULL; + + proc_key.pid = pid; + + proc_value.ground = STC_APP_STATE_BACKGROUND; + + stc_monitor_application_add(app_key, app_value); + stc_monitor_process_add(app_key, proc_key, proc_value); + stc_monitor_process_update_ground(app_key, proc_key, + STC_APP_STATE_BACKGROUND); + + FREE(app_key.pkg_id); + FREE(app_key.app_id); + break; + } + case STC_CMD_SET_SERVICE_LAUNCHED: + { + stc_app_key_s app_key; + stc_app_value_s app_value; + stc_process_key_s proc_key; + stc_process_value_s proc_value; + + memset(&app_key, 0, sizeof(stc_app_key_s)); + memset(&app_value, 0, sizeof(stc_app_value_s)); + memset(&proc_key, 0, sizeof(stc_process_key_s)); + memset(&proc_value, 0, sizeof(stc_process_value_s)); + + app_key.pkg_id = g_strdup(pkg_id); + app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX, + NULL); + + app_value.type = app_type; + app_value.processes = NULL; + + proc_key.pid = pid; + + /* services will run always in background. */ + proc_value.ground = STC_APP_STATE_BACKGROUND; + + stc_monitor_application_add(app_key, app_value); + stc_monitor_process_add(app_key, proc_key, proc_value); + + FREE(app_key.pkg_id); + g_free(app_key.app_id); + break; + } + case STC_CMD_SET_TERMINATED: + { + stc_monitor_process_remove(pid); + break; + } + default: + STC_LOGE("Unhandled command"); + ret = STC_ERROR_INVALID_PARAMETER; + } + + __STC_LOG_FUNC_EXIT__; + return ret; +} + +static void __process_event_exec(int tid, int pid) +{ + char cmdline[PROC_NAME_MAX] = {0, }; + char status[PROC_BUF_MAX] = {0, }; + + if (STC_ERROR_NONE == proc_get_cmdline(pid, cmdline) && + STC_ERROR_NONE == proc_get_status(pid, status, PROC_BUF_MAX)) { + + if (!g_strcmp0(cmdline, "iptables") || !g_strcmp0(cmdline, "ip6tables") || + !g_strcmp0(cmdline, "modprobe") || !g_strcmp0(cmdline, "net-cls-release")) { + return; + } + + proc_key_s *key; + proc_value_s *value; + + key = MALLOC0(proc_key_s, 1); + if (key == NULL) { + STC_LOGE("memory allocation failed"); + return; + } + + value = MALLOC0(proc_value_s, 1); + if (value == NULL) { + STC_LOGE("memory allocation failed"); + FREE(key); + return; + } + + key->pid = pid; + g_strlcpy(value->status, status, sizeof(value->status)); + g_strlcpy(value->cmdline, cmdline, sizeof(value->cmdline)); + + __proc_tree_add(key, value); + + STC_LOGD("EXEC:pid=%d,tgid=%d\t[%s]\t[%s]", pid, tid, status, + cmdline); + } +} + +static void __process_event_exit(int tid, int pid, int exit_code) +{ + proc_key_s key; + proc_value_s *lookup; + + key.pid = pid; + lookup = __proc_tree_lookup(&key); + if (lookup == NULL) /* unmonitored process */ + return; + + __proc_tree_remove(&key); + + STC_LOGD("EXIT:pid=%d,%d ruid=%d,euid=%d", pid, tid, exit_code); +} + +static gboolean __process_nl_connector_message(GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + int ret; + int sock = g_io_channel_unix_get_fd(source); + nl_connector_proc_event_s msg; + + if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || + (condition & G_IO_NVAL)) { + /* G_IO_ERR/G_IO_HUP/G_IO_NVAL received */ + + STC_LOGE("Netlink Connector socket received G_IO event, closing" + " socket. G_IO_ERR [%d], G_IO_HUP [%d], G_IO_NVAL [%s]", + (condition & G_IO_ERR), (condition & G_IO_HUP), + (condition & G_IO_NVAL)); + __reopen_nl_connector_sock(); + __STC_LOG_FUNC_EXIT__; + return FALSE; + } + + memset(&msg, 0, sizeof(nl_connector_proc_event_s)); + + ret = read(sock, &msg, sizeof(nl_connector_proc_event_s)); + if (ret == 0) { + __STC_LOG_FUNC_EXIT__; + return TRUE; + } + + switch (msg.proc_ev.what) { + case PROC_EVENT_EXEC: + __process_event_exec(msg.proc_ev.event_data.exec.process_pid, + msg.proc_ev.event_data.exec.process_tgid); + break; + case PROC_EVENT_EXIT: + __process_event_exit(msg.proc_ev.event_data.exit.process_pid, + msg.proc_ev.event_data.exit.process_tgid, + msg.proc_ev.event_data.exit.exit_code); + break; + default: + ; /* Do nothing */ + } + + return TRUE; +} + +static int __subscribe_proc_events(void) +{ + __STC_LOG_FUNC_ENTER__; + nl_connector_msg_s msg; + int ret; + int sock = nl_connector_sock; + + if (sock == -1) { + __STC_LOG_FUNC_EXIT__; + return -1; + } + + memset(&msg, 0, sizeof(nl_connector_msg_s)); + + msg.nl_hdr.nlmsg_len = sizeof(nl_connector_msg_s); + msg.nl_hdr.nlmsg_pid = getpid(); + msg.nl_hdr.nlmsg_type = NLMSG_DONE; + + msg.cn_msg.id.idx = CN_IDX_PROC; + msg.cn_msg.id.val = CN_VAL_PROC; + msg.cn_msg.len = sizeof(enum proc_cn_mcast_op); + + msg.cn_mcast = PROC_CN_MCAST_LISTEN; + + ret = send(sock, &msg, sizeof(nl_connector_msg_s), 0); + if (ret == -1) { + STC_LOGE("Error sending netlink connector message"); + __STC_LOG_FUNC_EXIT__; + return -1; + } + + __STC_LOG_FUNC_EXIT__; + return 0; +} + +static int __unsubscribe_proc_events(void) +{ + __STC_LOG_FUNC_ENTER__; + nl_connector_msg_s msg; + int ret; + int sock = nl_connector_sock; + + if (sock == -1) { + __STC_LOG_FUNC_EXIT__; + return -1; + } + + memset(&msg, 0, sizeof(nl_connector_msg_s)); + + msg.nl_hdr.nlmsg_len = sizeof(nl_connector_msg_s); + msg.nl_hdr.nlmsg_pid = getpid(); + msg.nl_hdr.nlmsg_type = NLMSG_DONE; + + msg.cn_msg.id.idx = CN_IDX_PROC; + msg.cn_msg.id.val = CN_VAL_PROC; + msg.cn_msg.len = sizeof(enum proc_cn_mcast_op); + + msg.cn_mcast = PROC_CN_MCAST_IGNORE; + + ret = send(sock, &msg, sizeof(nl_connector_msg_s), 0); + if (ret == -1) { + STC_LOGE("Error sending netlink connector message"); + __STC_LOG_FUNC_EXIT__; + return -1; + } + + __STC_LOG_FUNC_EXIT__; + return 0; +} + +void stc_app_lifecycle_monitor_init(void) +{ + __STC_LOG_FUNC_ENTER__; + + proc_tree = g_tree_new_full(__proc_tree_key_compare, NULL, + __proc_tree_key_free, + __proc_tree_value_free); + + /* TODO: Fill proc tree with current procfs state */ + + __open_nl_connector_sock(); + __subscribe_proc_events(); + __STC_LOG_FUNC_EXIT__; +} + +void stc_app_lifecycle_monitor_deinit(void) +{ + __STC_LOG_FUNC_ENTER__; + + if (nl_connector_sock == -1) { + STC_LOGE("socket already closed"); + return; + } + + __unsubscribe_proc_events(); + __close_nl_connector_sock(); + + g_tree_destroy(proc_tree); + proc_tree = NULL; + + __STC_LOG_FUNC_EXIT__; +} diff --git a/src/monitor/stc-application-lifecycle.c b/src/monitor/stc-application-lifecycle.c deleted file mode 100755 index ee82320..0000000 --- a/src/monitor/stc-application-lifecycle.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stc-application-lifecycle.h" - -/* - * AUL - */ -#define AUL_APP_STATUS_DBUS_PATH "/Org/Tizen/Aul/AppStatus" -#define AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE "org.tizen.aul.AppStatus" -#define AUL_APP_STATUS_BUS_NAME AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE - -#define AUL_APP_STATUS_DBUS_LAUNCH_REQUEST "AppLaunch" -#define AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE "(isss)" - -#define AUL_APP_STATUS_DBUS_STATUS_CHANGE "AppStatusChange" -#define AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE "(issss)" - -#define AUL_APP_STATUS_DBUS_GROUP "AppGroup" -#define AUL_APP_STATUS_DBUS_GROUP_TYPE "(iis)" - -#define AUL_APP_STATUS_DBUS_TERMINATED "AppTerminated" -#define AUL_APP_STATUS_DBUS_TERMINATED_TYPE "(i)" - -typedef enum { - STC_CMD_NONE, - STC_CMD_SET_FOREGRD, - STC_CMD_SET_BACKGRD, - STC_CMD_SET_APP_LAUNCHED, - STC_CMD_SET_SERVICE_LAUNCHED, - STC_CMD_SET_TERMINATED, - STC_CMD_MAX_ELEM -} stc_cmd_type_e; - -typedef struct { - guint sub_id; - const gchar *path; - const gchar *interface; - const gchar *member; - const gchar *param_type; - GDBusSignalCallback callback; - gpointer user_data; -} signal_map_s; - -static stc_error_e __stc_manager_app_status_changed(stc_cmd_type_e cmd, - pid_t pid, - gchar *app_id, - gchar *pkg_id, - stc_app_type_e app_type) -{ - __STC_LOG_FUNC_ENTER__; - stc_error_e ret = STC_ERROR_NONE; - - switch (cmd) { - case STC_CMD_SET_FOREGRD: - { - stc_app_key_s app_key; - stc_app_value_s app_value; - stc_process_key_s proc_key; - stc_process_value_s proc_value; - - memset(&app_key, 0, sizeof(stc_app_key_s)); - memset(&app_value, 0, sizeof(stc_app_value_s)); - memset(&proc_key, 0, sizeof(stc_process_key_s)); - memset(&proc_value, 0, sizeof(stc_process_value_s)); - - app_key.pkg_id = g_strdup(pkg_id); - app_key.app_id = g_strdup(app_id); - - app_value.type = app_type; - app_value.processes = NULL; - - proc_key.pid = pid; - - proc_value.ground = STC_APP_STATE_FOREGROUND; - - stc_monitor_application_add(app_key, app_value); - stc_monitor_process_add(app_key, proc_key, proc_value); - stc_monitor_process_update_ground(app_key, proc_key, - STC_APP_STATE_FOREGROUND); - - FREE(app_key.pkg_id); - FREE(app_key.app_id); - break; - } - case STC_CMD_SET_BACKGRD: - { - stc_app_key_s app_key; - stc_app_value_s app_value; - stc_process_key_s proc_key; - stc_process_value_s proc_value; - - memset(&app_key, 0, sizeof(stc_app_key_s)); - memset(&app_value, 0, sizeof(stc_app_value_s)); - memset(&proc_key, 0, sizeof(stc_process_key_s)); - memset(&proc_value, 0, sizeof(stc_process_value_s)); - - app_key.pkg_id = g_strdup(pkg_id); - app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX, - NULL); - - app_value.type = app_type; - app_value.processes = NULL; - - proc_key.pid = pid; - - proc_value.ground = STC_APP_STATE_BACKGROUND; - - stc_monitor_application_add(app_key, app_value); - stc_monitor_process_add(app_key, proc_key, proc_value); - stc_monitor_process_update_ground(app_key, proc_key, - STC_APP_STATE_BACKGROUND); - - FREE(app_key.pkg_id); - FREE(app_key.app_id); - break; - } - case STC_CMD_SET_APP_LAUNCHED: - { - stc_app_key_s app_key; - stc_app_value_s app_value; - stc_process_key_s proc_key; - stc_process_value_s proc_value; - - memset(&app_key, 0, sizeof(stc_app_key_s)); - memset(&app_value, 0, sizeof(stc_app_value_s)); - memset(&proc_key, 0, sizeof(stc_process_key_s)); - memset(&proc_value, 0, sizeof(stc_process_value_s)); - - app_key.pkg_id = g_strdup(pkg_id); - app_key.app_id = g_strdup(app_id); - - app_value.type = app_type; - app_value.processes = NULL; - - proc_key.pid = pid; - - proc_value.ground = STC_APP_STATE_UNKNOWN; - - /* create foreground cgroup */ - stc_monitor_application_add(app_key, app_value); - stc_monitor_process_add(app_key, proc_key, proc_value); - - /* create background cgroup */ - FREE(app_key.app_id); - - app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX, - NULL); - stc_monitor_application_add(app_key, app_value); - - FREE(app_key.pkg_id); - g_free(app_key.app_id); - break; - } - case STC_CMD_SET_SERVICE_LAUNCHED: - { - stc_app_key_s app_key; - stc_app_value_s app_value; - stc_process_key_s proc_key; - stc_process_value_s proc_value; - - memset(&app_key, 0, sizeof(stc_app_key_s)); - memset(&app_value, 0, sizeof(stc_app_value_s)); - memset(&proc_key, 0, sizeof(stc_process_key_s)); - memset(&proc_value, 0, sizeof(stc_process_value_s)); - - app_key.pkg_id = g_strdup(pkg_id); - app_key.app_id = g_strconcat(app_id, STC_BACKGROUND_APP_SUFFIX, - NULL); - - app_value.type = app_type; - app_value.processes = NULL; - - proc_key.pid = pid; - - /* services will run always in background. */ - proc_value.ground = STC_APP_STATE_BACKGROUND; - - stc_monitor_application_add(app_key, app_value); - stc_monitor_process_add(app_key, proc_key, proc_value); - - FREE(app_key.pkg_id); - g_free(app_key.app_id); - break; - } - case STC_CMD_SET_TERMINATED: - { - stc_monitor_process_remove(pid); - break; - } - default: - STC_LOGE("Unhandled command"); - ret = STC_ERROR_INVALID_PARAMETER; - } - - __STC_LOG_FUNC_EXIT__; - return ret; -} - -static void __stc_gdbus_handle_aul_launch(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - __STC_LOG_FUNC_ENTER__; - pid_t pid; - stc_cmd_type_e status; - stc_app_type_e apptype; - gchar *appid, *pkgid, *pkgtype; - - RETURN_IF_DBUS_TYPE_MISMATCH(parameters, - AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE); - - g_variant_get(parameters, AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE, - &pid, &appid, &pkgid, &pkgtype); - - if (!strncmp(pkgtype, "svc", 3)) { - apptype = STC_APP_TYPE_SERVICE; - status = STC_CMD_SET_SERVICE_LAUNCHED; - - } else if (!strncmp(pkgtype, "ui", 2)) { - apptype = STC_APP_TYPE_GUI; - status = STC_CMD_SET_APP_LAUNCHED; - - } else if (!strncmp(pkgtype, "widget", 6)) { - apptype = STC_APP_TYPE_WIDGET; - status = STC_CMD_SET_APP_LAUNCHED; - - } else if (!strncmp(pkgtype, "watch", 5)) { - apptype = STC_APP_TYPE_WATCH; - status = STC_CMD_SET_APP_LAUNCHED; - - } else { - __STC_LOG_FUNC_EXIT__; - goto handle_error; - } - - __stc_manager_app_status_changed(status, pid, appid, pkgid, apptype); - - __STC_LOG_FUNC_EXIT__; -handle_error: - FREE(appid); - FREE(pkgid); - FREE(pkgtype); -} - -static void __stc_gdbus_handle_aul_changestate(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - __STC_LOG_FUNC_ENTER__; - pid_t pid; - stc_cmd_type_e status; - stc_app_type_e apptype; - gchar *appid, *pkgid, *statstr, *pkgtype; - - RETURN_IF_DBUS_TYPE_MISMATCH(parameters, - AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE); - - g_variant_get(parameters, AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE, - &pid, &appid, &pkgid, &statstr, &pkgtype); - - if (!strncmp(statstr, "fg", 2)) { - status = STC_CMD_SET_FOREGRD; - } else if (!strncmp(statstr, "bg", 2)) { - status = STC_CMD_SET_BACKGRD; - } else { - __STC_LOG_FUNC_EXIT__; - goto handle_error; - } - - if (!strncmp(pkgtype, "svc", 3)) - apptype = STC_APP_TYPE_SERVICE; - else if (!strncmp(pkgtype, "widget", 6)) - apptype = STC_APP_TYPE_WIDGET; - else if (!strncmp(pkgtype, "watch", 5)) - apptype = STC_APP_TYPE_WATCH; - else - apptype = STC_APP_TYPE_GUI; - - __stc_manager_app_status_changed(status, pid, appid, pkgid, apptype); - - __STC_LOG_FUNC_EXIT__; -handle_error: - FREE(appid); - FREE(pkgid); - FREE(statstr); - FREE(pkgtype); -} - -static void __stc_gdbus_handle_aul_group(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - __STC_LOG_FUNC_ENTER__; - pid_t ownerpid, childpid; - gchar *appid; - - RETURN_IF_DBUS_TYPE_MISMATCH(parameters, - AUL_APP_STATUS_DBUS_GROUP_TYPE); - - g_variant_get(parameters, AUL_APP_STATUS_DBUS_GROUP_TYPE, - &ownerpid, &childpid, &appid); - - if (ownerpid == childpid) { - STC_LOGD("Skip merge, when one app %d makes multiple window.", - ownerpid); - __STC_LOG_FUNC_EXIT__; - goto handle_error; - } - - STC_LOGD("received process grouping : owner %d, child %d, previous appid %s", - ownerpid, childpid, appid); - - /** - * TODO: app_set_group(ownerpid, childpid, appid) - */ - - __STC_LOG_FUNC_EXIT__; -handle_error: - FREE(appid); -} - -static void __stc_gdbus_handle_aul_terminated(GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - __STC_LOG_FUNC_ENTER__; - pid_t pid; - stc_cmd_type_e status = STC_CMD_SET_TERMINATED; - - RETURN_IF_DBUS_TYPE_MISMATCH(parameters, - AUL_APP_STATUS_DBUS_TERMINATED_TYPE); - - g_variant_get(parameters, AUL_APP_STATUS_DBUS_TERMINATED_TYPE, - &pid); - - __stc_manager_app_status_changed(status, pid, NULL, NULL, - STC_APP_TYPE_NONE); - - __STC_LOG_FUNC_EXIT__; -} - -signal_map_s signal_map[] = { - - /* AMD DBUS */ - { - 0, - AUL_APP_STATUS_DBUS_PATH, - AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE, - AUL_APP_STATUS_DBUS_LAUNCH_REQUEST, - AUL_APP_STATUS_DBUS_LAUNCH_REQUEST_TYPE, - __stc_gdbus_handle_aul_launch, - NULL - }, - { - 0, - AUL_APP_STATUS_DBUS_PATH, - AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE, - AUL_APP_STATUS_DBUS_STATUS_CHANGE, - AUL_APP_STATUS_DBUS_STATUS_CHANGE_TYPE, - __stc_gdbus_handle_aul_changestate, - NULL - }, - { - 0, - AUL_APP_STATUS_DBUS_PATH, - AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE, - AUL_APP_STATUS_DBUS_GROUP, - AUL_APP_STATUS_DBUS_GROUP_TYPE, - __stc_gdbus_handle_aul_group, - NULL - }, - { - 0, - AUL_APP_STATUS_DBUS_PATH, - AUL_APP_STATUS_DBUS_SIGNAL_INTERFACE, - AUL_APP_STATUS_DBUS_TERMINATED, - AUL_APP_STATUS_DBUS_TERMINATED_TYPE, - __stc_gdbus_handle_aul_terminated, - NULL - }, - { - 0, - NULL, - NULL, - NULL, - NULL - } -}; - -stc_error_e stc_application_lifecycle_monitor_init(stc_s *stc) -{ - guint i = 0; - ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data"); - - for (i = 0; signal_map[i].member != NULL; i++) { - signal_map[i].sub_id = - stc_manager_gdbus_subscribe_signal(stc->connection, - NULL, - signal_map[i].interface, - signal_map[i].member, - signal_map[i].path, - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - signal_map[i].callback, - signal_map[i].user_data, - NULL); - STC_LOGI("Successfully subscribed [%s] signal", - signal_map[i].member); - } - - return STC_ERROR_NONE; -} - -stc_error_e stc_application_lifecycle_monitor_deinit(stc_s *stc) -{ - guint i = 0; - ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data"); - - for (i = 0; signal_map[i].member != NULL; i++) { - stc_manager_gdbus_unsubscribe_signal(stc->connection, - signal_map[i].sub_id); - signal_map[i].sub_id = 0; - STC_LOGD("Successfully unsubscribed [%s] signal", - signal_map[i].member); - } - - return STC_ERROR_NONE; -} diff --git a/src/stc-manager-gdbus.c b/src/stc-manager-gdbus.c index 3bd6659..31a808d 100755 --- a/src/stc-manager-gdbus.c +++ b/src/stc-manager-gdbus.c @@ -18,7 +18,7 @@ #include "stc-statistics.h" #include "stc-restriction.h" #include "stc-default-connection.h" -#include "stc-application-lifecycle.h" +#include "stc-app-ground-status.h" static gboolean __stc_manager_gdbus_statistics_init(stc_s *stc) { @@ -153,7 +153,7 @@ static void __stc_manager_gdbus_on_bus_acquired(GDBusConnection *connection, g_dbus_object_manager_server_set_connection(stc->obj_mgr, stc->connection); - stc_application_lifecycle_monitor_init(stc); + stc_app_ground_status_monitor_init(stc); stc_default_connection_monitor_init(stc); __STC_LOG_FUNC_EXIT__; @@ -194,7 +194,7 @@ void stc_manager_gdbus_deinit(gpointer stc_data) { __STC_LOG_FUNC_ENTER__; stc_s *stc = (stc_s *)stc_data; - stc_application_lifecycle_monitor_deinit(stc); + stc_app_ground_status_monitor_deinit(stc); stc_default_connection_monitor_deinit(stc); g_bus_unown_name(stc->gdbus_owner_id); stc->statistics_obj = NULL; diff --git a/src/stc-manager.c b/src/stc-manager.c index dc923ff..0b91ce4 100755 --- a/src/stc-manager.c +++ b/src/stc-manager.c @@ -27,6 +27,7 @@ #include "helper-nfacct-rule.h" #include "stc-monitor.h" #include "stc-manager-plugin.h" +#include "stc-app-lifecycle.h" static stc_s *g_stc = NULL; @@ -39,6 +40,7 @@ static void __stc_manager_deinit(void) return; } + stc_app_lifecycle_monitor_deinit(); stc_monitor_deinit(); stc_deinit_db_guard(); stc_db_deinitialize(); @@ -73,6 +75,7 @@ static stc_s *__stc_manager_init(void) stc_manager_gdbus_init((gpointer)stc); stc_manager_plugin_init(); + stc_app_lifecycle_monitor_init(); STC_LOGI("stc manager initialized"); __STC_LOG_FUNC_EXIT__; -- 2.7.4