Apply Poweroff Wait sequence for CP detach 33/173833/6
authorsinikang <sinikang@samsung.com>
Mon, 26 Mar 2018 08:27:41 +0000 (17:27 +0900)
committersinikang <sinikang@samsung.com>
Fri, 6 Apr 2018 01:09:03 +0000 (10:09 +0900)
Change-Id: Idc12a60b6b84266e44a247fb9e6ff51b51d4db4f

CMakeLists.txt
include/manager_modem.h
packaging/tel-plugin-manager.spec
src/manager_core.c
src/manager_modem.c

index ad572f7..4c35807 100644 (file)
@@ -14,6 +14,7 @@ SET(DATAROOTDIR "\${prefix}/share")
 INCLUDE(FindPkgConfig)
 pkg_check_modules(pkgs REQUIRED
        glib-2.0
+       gio-2.0
        tcore
        libxml-2.0
        vconf
index 403f95b..29617cb 100644 (file)
 extern "C" {
 #endif
 
+#include <gio/gio.h>
+
+struct system_power_info {
+       GDBusConnection *conn;
+       GCancellable *ca;
+       guint subs_id_power_off;
+       int state;
+       gboolean set_poweroff_wait;
+       gint set_poweroff_timer;
+};
+
 struct manager_modem_private_info {
        CoreObject *co_modem;
        enum modem_state modem_status;
+       struct system_power_info sys_power;
 };
 
 gboolean manager_modem_initialize_private_info(ModemBoard *mb);
+gboolean manager_modem_clear_private_info(ModemBoard *mb);
+
 
 enum tcore_manager_return manager_modem_process_request(Server *server,
                                                        UserRequest *ur);
index 9cc752c..5eb0bad 100644 (file)
@@ -1,6 +1,6 @@
 %define major 0
 %define minor 1
-%define patchlevel 9
+%define patchlevel 10
 
 Name:           tel-plugin-manager
 Version:        %{major}.%{minor}.%{patchlevel}
@@ -11,6 +11,7 @@ Group:          System/Libraries
 Source0:        %{name}-%{version}.tar.gz
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
 BuildRequires:  pkgconfig(libtzplatform-config)
 BuildRequires:  pkgconfig(libxml-2.0)
 BuildRequires:  pkgconfig(tcore)
index 53201ec..7310b06 100644 (file)
@@ -51,6 +51,7 @@ static void __destroy_modem_board_sub_modules(ModemBoard *mb)
        dbg("enter");
        /* Clear network private info cache */
        manager_network_clear_private_info(mb);
+       manager_modem_clear_private_info(mb);
 }
 
 void manager_core_create_modem_board(TcorePlugin *manager_plugin, TcorePlugin *modem_plugin)
@@ -82,7 +83,7 @@ void manager_core_create_modem_board(TcorePlugin *manager_plugin, TcorePlugin *m
 
        /* Create Modem Board */
        mb = g_try_malloc0(sizeof(ModemBoard));
-       if(mb == NULL) {
+       if (mb == NULL) {
                err("Memory alloc failed");
                return;
        }
index bc63972..f11b98f 100644 (file)
 #define MANAGER_FLIGHT_MODE_REQUEST_TIMEOUT     (1000)  /* 1 seconds */
 #define MANAGER_MODEM_POWER_OFF_REQUEST_TIMEOUT (1000)  /* 1 seconds */
 
+/*
+ * Timeout for 5 seconds for poweroff wait timer set
+ */
+#define MANAGER_DEFAULT_TIMEOUT        (5 * 1000)
+#define MANAGER_RETRY_TIMEOUT  (1 * 1000)
+
+
+/*
+ * Dbus interface info for power off wait timer handling
+ */
+#define DEVICED_BUS_NAME                                       "org.tizen.system.deviced"
+#define DEVICED_OBJECT_PATH                                    "/Org/Tizen/System/DeviceD"
+#define DEVICED_INTERFACE_NAME              DEVICED_BUS_NAME
+
+#define DEVICED_PATH_REBOOT                                    DEVICED_OBJECT_PATH"/Reboot"
+#define DEVICED_PATH_POWEROFF                          DEVICED_OBJECT_PATH"/PowerOff"
+
+#define DEVICED_INTERFACE_REBOOT                       DEVICED_INTERFACE_NAME".reboot"
+#define DEVICED_INTERFACE_POWEROFF                     DEVICED_INTERFACE_NAME".PowerOff"
+
+#define DBUS_METHOD_ADD_POWEROFF_WAIT          "AddPoweroffWait"
+#define DBUS_METHOD_REMOVE_POWEROFF_WAIT       "RemovePoweroffWait"
+#define DBUS_SIGNAL_POWEROFF_STATE                     "ChangeState"
+
+static void __manager_modem_add_poweroff_wait(ModemPrivateInfo *modem_info);
+
 static enum tcore_hook_return on_noti_hook_manager_call_status_idle(Server *server,
                                                                       CoreObject *source, enum tcore_notification_command command,
                                                                       unsigned int data_len, void *data, void *user_data)
@@ -201,10 +227,283 @@ static void __update_private_info(Manager *manager, CoreObject *co_modem, enum m
 
 }
 
+static void __on_resp_modem_poweroff(UserRequest *ur, enum tcore_response_command command,
+                                    unsigned int data_len, const void *data, void *user_data)
+{
+       struct tresp_modem_power_off *poweroff_status = (struct tresp_modem_power_off *)data;
+       TcorePlugin *modem_plugin = (TcorePlugin *)user_data;
+
+       dbg("enter");
+
+       if (!poweroff_status || !modem_plugin) {
+               err("NULL data : poweroff_status[%p], modem_plugin[%p]", poweroff_status, modem_plugin);
+               return;
+       }
+
+}
+
+static void __request_modem_poweroff(TcorePlugin *modem_plugin)
+{
+       struct treq_modem_power_off poweroff_cmd = {};
+       gboolean ret = FALSE;
+
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_plugin))
+               return;
+
+       ret = manager_util_send_request(modem_plugin, TREQ_MODEM_POWER_OFF,
+                                       sizeof(poweroff_cmd), &poweroff_cmd, __on_resp_modem_poweroff, modem_plugin);
+
+       if (!ret) {
+               err("Fail to request modem power off!!");
+       }
+
+       dbg("done");
+}
+
+static void __manager_modem_poweroff_signal_handler(GDBusConnection *connection,
+                                                            const gchar *sender_name, const gchar *object_path,
+                                                            const gchar *interface_name, const gchar *signal_name,
+                                                            GVariant *parameters, gpointer user_data)
+{
+
+       ModemPrivateInfo *modem_info = user_data;
+       TcorePlugin *modem_plugin = NULL;
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info))
+               return;
+
+       if (g_strcmp0(signal_name, DBUS_SIGNAL_POWEROFF_STATE) == 0) {
+               modem_plugin = tcore_object_ref_plugin(modem_info->co_modem);
+               dbg("poweroff state changed is happened");
+               __request_modem_poweroff(modem_plugin);
+       }
+       dbg("done");
+
+}
+
+static void __manager_modem_poweroff_subscribe_signal(ModemPrivateInfo *modem_info)
+{
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info)) {
+               err("Invalid data");
+               return;
+       }
+
+       if (!modem_info->sys_power.conn) {
+               GError *error = NULL;
+
+               modem_info->sys_power.conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+               if (modem_info->sys_power.conn == NULL) {
+                       err("GDBusconnection is NULL: [%s]", error->message);
+                       g_error_free(error);
+                       return;
+               }
+               modem_info->sys_power.set_poweroff_wait = FALSE;
+       }
+
+       if (!modem_info->sys_power.ca) {
+               modem_info->sys_power.ca = g_cancellable_new();
+       }
+
+       if (modem_info->sys_power.subs_id_power_off) {
+               dbg("g_dbus_connection_signal_subscribe() for poweroff_state has been already done.");
+               return;
+       }
+
+       modem_info->sys_power.subs_id_power_off = g_dbus_connection_signal_subscribe(modem_info->sys_power.conn,
+                                                                                       NULL,
+                                                                                       DEVICED_INTERFACE_POWEROFF,
+                                                                                       DBUS_SIGNAL_POWEROFF_STATE,
+                                                                                       DEVICED_PATH_POWEROFF, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+                                                                                       __manager_modem_poweroff_signal_handler, modem_info, NULL);
+
+
+       if (modem_info->sys_power.subs_id_power_off == 0) {
+               err("g_dbus_connection_signal_subscribe() is failed.");
+               g_object_unref(modem_info->sys_power.conn);
+       }
+
+       dbg("done");
+
+}
+
+static void __manager_modem_poweroff_unsubscribe_signal(ModemPrivateInfo *modem_info)
+{
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info)) {
+               err("Invalid data");
+               return;
+       }
+
+       if (modem_info->sys_power.subs_id_power_off > 0) {
+               g_dbus_connection_signal_unsubscribe(modem_info->sys_power.conn, modem_info->sys_power.subs_id_power_off);
+               modem_info->sys_power.subs_id_power_off = 0;
+       }
+
+       if (modem_info->sys_power.ca) {
+               g_cancellable_cancel(modem_info->sys_power.ca);
+               g_object_unref(modem_info->sys_power.ca);
+       }
+
+       if (modem_info->sys_power.conn) {
+               g_object_unref(modem_info->sys_power.conn);
+               modem_info->sys_power.conn = NULL;
+       }
+
+       modem_info->sys_power.set_poweroff_wait = FALSE;
+
+       /* Remove Timer */
+       if (modem_info->sys_power.set_poweroff_timer > 0) {
+               g_source_remove(modem_info->sys_power.set_poweroff_timer);
+               modem_info->sys_power.set_poweroff_timer = -1;
+       }
+
+       dbg("done");
+
+}
+
+static gboolean __manager_modem_poweroff_wait_retry(gpointer user_data)
+{
+       ModemPrivateInfo *modem_info = user_data;
+
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info)) {
+               err("Invalid data");
+               return FALSE;
+       }
+
+       /* Remove Timer */
+       if (modem_info->sys_power.set_poweroff_timer > 0) {
+               g_source_remove(modem_info->sys_power.set_poweroff_timer);
+               modem_info->sys_power.set_poweroff_timer = -1;
+       }
+       __manager_modem_add_poweroff_wait(modem_info);
+
+       dbg("done");
+
+       return TRUE;
+}
+
+static void __manager_modem_add_poweroff_wait_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GError *error = NULL;
+       GDBusConnection *conn = NULL;
+       int result = -1;
+       GVariant *dbus_result = NULL;
+       ModemPrivateInfo *modem_info = user_data;
+
+       dbg("enter");
+
+       conn = G_DBUS_CONNECTION(source_object);
+       dbus_result = g_dbus_connection_call_finish(conn, res, &error);
+       if (error) {
+               err("Failed: %s", error->message);
+               g_error_free(error);
+               modem_info->sys_power.set_poweroff_timer = g_timeout_add(MANAGER_RETRY_TIMEOUT, __manager_modem_poweroff_wait_retry, modem_info);
+       } else {
+               dbg("PoweroffWait Added Successufully");
+               modem_info->sys_power.set_poweroff_wait = TRUE;
+       }
+
+       if (dbus_result) {
+               g_variant_get(dbus_result, "(i)", &result);
+               g_variant_unref(dbus_result);
+       }
+
+       dbg("result : %d", result);
+}
+
+
+static void __manager_modem_add_poweroff_wait(ModemPrivateInfo *modem_info)
+{
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info)) {
+               err("Invalid data");
+               return;
+       }
+
+       if (modem_info->sys_power.set_poweroff_wait == TRUE) {
+               return;
+       }
+
+       if (modem_info->sys_power.conn) {
+               g_dbus_connection_call(modem_info->sys_power.conn, DEVICED_BUS_NAME,
+                                       DEVICED_PATH_REBOOT, DEVICED_INTERFACE_REBOOT, DBUS_METHOD_ADD_POWEROFF_WAIT,
+                                       NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
+                                       MANAGER_DEFAULT_TIMEOUT, modem_info->sys_power.ca,
+                                       __manager_modem_add_poweroff_wait_cb, modem_info);
+       }
+
+       dbg("done");
+
+       return;
+}
+
+static void __manager_modem_remove_poweroff_wait_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+       GError *error = NULL;
+       GDBusConnection *conn = NULL;
+       int result = -1;
+       GVariant *dbus_result = NULL;
+       ModemPrivateInfo *modem_info = user_data;
+
+       dbg("enter");
+
+       conn = G_DBUS_CONNECTION(source_object);
+       dbus_result = g_dbus_connection_call_finish(conn, res, &error);
+       if (error) {
+               err("Failed: %s", error->message);
+               g_error_free(error);
+       } else {
+               dbg("PoweroffWait Removed Successufully");
+               modem_info->sys_power.set_poweroff_wait = FALSE;
+       }
+
+       if (dbus_result) {
+               g_variant_get(dbus_result, "(i)", &result);
+               g_variant_unref(dbus_result);
+       }
+
+       dbg("result : %d", result);
+}
+
+static void __manager_modem_remove_poweroff_wait(ModemPrivateInfo *modem_info)
+{
+       dbg("enter");
+
+       if (G_UNLIKELY(!modem_info)) {
+               err("Invalid data");
+               return;
+       }
+
+       if (modem_info->sys_power.conn) {
+               g_dbus_connection_call(modem_info->sys_power.conn, DEVICED_BUS_NAME,
+                                       DEVICED_PATH_REBOOT, DEVICED_INTERFACE_REBOOT, DBUS_METHOD_REMOVE_POWEROFF_WAIT,
+                                       NULL, NULL, G_DBUS_CALL_FLAGS_NONE,
+                                       MANAGER_DEFAULT_TIMEOUT, modem_info->sys_power.ca,
+                                       __manager_modem_remove_poweroff_wait_cb, NULL);
+
+               modem_info->sys_power.set_poweroff_wait = FALSE;
+       }
+
+       return;
+}
+
 gboolean manager_modem_initialize_private_info(ModemBoard *mb)
 {
-       if (G_UNLIKELY(!mb))
+       dbg("enter");
+
+       if (G_UNLIKELY(!mb)) {
+               err("Invalid data");
                return FALSE;
+       }
 
        if (mb->modem_info)
                mb->modem_info->modem_status = MODEM_STATE_UNKNOWN;
@@ -213,9 +512,41 @@ gboolean manager_modem_initialize_private_info(ModemBoard *mb)
        mb->modem_info->co_modem = tcore_plugin_ref_core_object(mb->modem_plugin, CORE_OBJECT_TYPE_MODEM);
        mb->modem_info->modem_status = MODEM_STATE_UNKNOWN;
 
+
+       mb->modem_info->sys_power.set_poweroff_timer = -1;
+
+       if (mb->index == MANAGER_MODEM_BOARD_INDEX_0) {
+               dbg("__manager_power_subscribe_signal() for modem index (%d)", mb->index);
+               __manager_modem_poweroff_subscribe_signal(mb->modem_info);
+       }
+
        dbg("Initialized modem private info");
        return TRUE;
 }
+
+gboolean manager_modem_clear_private_info(ModemBoard *mb)
+{
+
+       dbg("enter");
+
+       if (G_UNLIKELY(!mb || !mb->modem_info)) {
+               err("Invalid data");
+               return FALSE;
+       }
+
+       if (mb->index == MANAGER_MODEM_BOARD_INDEX_0) {
+               dbg("__manager_power_unsubscribe_signal() for modem index (%d)", mb->index);
+               __manager_modem_poweroff_unsubscribe_signal(mb->modem_info);
+       }
+
+       g_free(mb->modem_info);
+       mb->modem_info = NULL;
+
+       dbg("done");
+
+       return TRUE;
+}
+
 enum tcore_manager_return manager_modem_process_notification(Manager *manager,
                                                             CoreObject *source, enum tcore_notification_command command,
                                                             unsigned int data_len, void *data)
@@ -224,7 +555,9 @@ enum tcore_manager_return manager_modem_process_notification(Manager *manager,
        TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
        PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
 
-       if (!data || !priv_data) {
+       ModemBoard *mb = manager_core_get_modem_board(manager, tcore_object_ref_plugin(source));
+
+       if (!data || !priv_data || !mb || !mb->modem_info) {
                err("Invalid data");
                return ret;
        }
@@ -246,6 +579,33 @@ enum tcore_manager_return manager_modem_process_notification(Manager *manager,
                        dbg("Write MODEM_STATE to /sys/class/sec/bsp/boot_stat");
                        manager_util_write_to_proc_file(msg, strlen(msg));
                        g_free(msg);
+
+                       /* For executing CP detach process when Device Power off */
+                       /* It should be subscribed power off waiting timer to deviced */
+                       /* Poweroff timer should be added only one time, in case of modem index (0) */
+                       if (mb->index == MANAGER_MODEM_BOARD_INDEX_0) {
+                               dbg("Should add poweroff timer in case of modem index(0)");
+                               if (!mb->modem_info->sys_power.set_poweroff_wait) {
+                                       //__manager_power_subscribe_signal(mb->modem_info);
+                                       __manager_modem_add_poweroff_wait(mb->modem_info);
+                               }
+                       }
+               }
+               break;
+
+               case MODEM_STATE_OFFLINE: {
+                       dbg("MODEM_STATE has been changed to OFFLINE");
+
+                       /* Once MODEM has been power off successufully, */
+                       /* It should be removed  power off waiting timer from deviced */
+                       /* Poweroff timer should be removed only one time, in case of modem index (0) */
+                       if (mb->index == MANAGER_MODEM_BOARD_INDEX_0) {
+                               dbg("Should removed poweroff timer in case of modem index (0)");
+
+                               if (mb->modem_info->sys_power.set_poweroff_wait == TRUE) {
+                                       __manager_modem_remove_poweroff_wait(mb->modem_info);
+                               }
+                       }
                }
                break;