a7e6638f69930721df85f3b29ee1f226e8979f8f
[platform/core/system/deviced.git] / src / power / boot.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <bundle.h>
22 #include <eventsystem.h>
23 #include <libgdbus/dbus-system.h>
24
25 #include "core/log.h"
26 #include "core/device-notifier.h"
27 #include "core/common.h"
28 #include "display/poll.h"
29 #include "shared/deviced-systemd.h"
30
31 #define SIGNAL_BOOTING_DONE             "BootingDone"
32
33 #define SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED "StartupFinished"
34 #define SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED   "UserSessionStartupFinished"
35 #define SYSTEMD_DBUS_METHOD_SYSTEM_STATE     "SystemState"
36 #define SYSTEMD_STATE_RUNNING                "running"
37 #define SYSTEMD_STATE_DEGRADED               "degraded"
38
39 int booting_finished(void)
40 {
41         char *state = NULL;
42         int ret = 0;
43         size_t len;
44         GVariant *reply = NULL;
45
46         reply = deviced_systemd_get_manager_property(SYSTEMD_DBUS_METHOD_SYSTEM_STATE);
47         if (!reply) {
48                 _E("Failed to get System State: no reply");
49                 goto err;
50         }
51         if (!dh_get_param_from_var(reply, "s", &state)) {
52                 _E("Failed to get System State %s", g_variant_get_type_string(reply));
53                 goto err;
54         }
55
56         _I("System State: (%s)", state);
57
58         len = strlen(state) + 1;
59         if (!strncmp(state, SYSTEMD_STATE_RUNNING, len) ||
60                 !strncmp(state, SYSTEMD_STATE_DEGRADED, len))
61                 ret = 1;
62         else
63                 ret = 0;
64
65 err:
66         if (reply)
67                 g_variant_unref(reply);
68         free(state);
69
70         return ret;
71 }
72
73 static guint sig_id[2] = {0, 0};
74
75 void remove_booting_done_handler(void *data)
76 {
77         unsubscribe_dbus_signal(NULL, sig_id[0]);
78         unsubscribe_dbus_signal(NULL, sig_id[1]);
79 }
80
81 static void booting_done_received(GDBusConnection  *conn,
82         const gchar      *sender,
83         const gchar      *path,
84         const gchar      *iface,
85         const gchar      *name,
86         GVariant         *param,
87         gpointer          data)
88
89 {
90         static int system_done = 0;
91         static int user_done = 0;
92
93         if (strcmp(name, SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED) == 0) {
94                 if (system_done)
95                         return;
96
97                 system_done = booting_finished();
98                 if (system_done == 0) {
99                         _E("System Session is not ready yet");
100                         return;
101                 }
102                 _I("System Session is Ready");
103                 device_notify(DEVICE_NOTIFIER_BOOTING_DONE, &system_done);
104
105         } else if (strcmp(name, SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED) == 0) {
106                 if (user_done)
107                         return;
108                 user_done = 1;
109                 _I("User Session is Ready");
110         }
111
112         if (!system_done || !user_done)
113                 return;
114
115         remove_booting_done_handler(NULL);
116
117         _I("real booting done, unlock LCD_OFF");
118         pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
119
120         _I("signal booting done");
121
122         dbus_handle_broadcast_dbus_signal(DEVICED_PATH_CORE,
123                 DEVICED_INTERFACE_CORE,
124                 SIGNAL_BOOTING_DONE,
125                 NULL, NULL);
126 }
127
128 void add_booting_done_handler(void *data)
129 {
130         /* System Session is loaded completely */
131         /*ret = */
132         sig_id[0] = subscribe_dbus_signal(NULL,
133                                         SYSTEMD_DBUS_PATH,
134                                         SYSTEMD_DBUS_IFACE_MANAGER,
135                                         SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
136                                         booting_done_received,
137                                         NULL, NULL);
138
139         if (sig_id[0] <= 0)
140                 _E("fail to init dbus signal(%s)", SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED);
141
142         /* User Session is loaded completely */
143         sig_id[1] = subscribe_dbus_signal(NULL,
144                                         SYSTEMD_DBUS_PATH,
145                                         SYSTEMD_DBUS_IFACE_MANAGER,
146                                         SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED,
147                                         booting_done_received,
148                                         NULL, NULL);
149
150         if (sig_id[1] <= 0)
151                 _E("fail to init dbus signal(%s)", SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED);
152 }