744e805ec4a27a17a05531ba6b50b6c518e3e658
[platform/core/multimedia/mmsvc-core.git] / server / src / muse_server_system.c
1 /*
2  * muse-server
3  *
4  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include "muse_server_private.h"
23 #include <storage.h>
24 #include <system_info.h>
25 #include <runtime_info.h>
26
27 #define MUSE_STORAGE_EXTERNAL_FEATURE           "http://tizen.org/feature/storage.external"
28
29 enum muse_poweroff_type {
30         MUSE_POWER_OFF_NONE = 0,
31         MUSE_POWER_OFF_POPUP,
32         MUSE_POWER_OFF_DIRECT,
33         MUSE_POWER_OFF_RESTART,
34 };
35
36 #ifdef MUSE_USE_POWER_OFF_STATE_CHANGE
37 static int _ms_system_subscribe_poweroff_state_change(ms_system_t *system);
38 static void _ms_system_unsubscribe_poweroff_state_change(void);
39 static void _ms_poweroff_state_changed_cb(GDBusConnection *con, const gchar *sender_name, const gchar *object_path,
40                         const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data);
41 #endif
42
43 #ifdef MUSE_USE_EXTERNAL_STORAGE_STATE_CHANGE
44 static int _ms_system_subscribe_external_storage_state_change(ms_system_t *system);
45 static void _ms_system_unsubscribe_external_storage_state_change(void);
46 static void _ms_external_storage_state_changed_cb(int storage_id, storage_dev_e dev, storage_state_e state, const char *fstype,
47                         const char *fsuuid, const char *mount_path, bool primary, int flags, void *user_data);
48 #endif
49
50 #ifdef MUSE_USE_RM_READY
51 static int _ms_system_subscribe_resource_manager_state_change(ms_system_t *system);
52 static void _ms_system_unsubscribe_resource_manager_state_change(void);
53 static void _ms_resource_manager_owner_name_changed_cb(GDBusConnection *con, const gchar *sender_name, const gchar *object_path,
54                         const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data);
55 #endif
56
57 #ifdef MUSE_USE_POWER_OFF_STATE_CHANGE
58 static int _ms_system_subscribe_poweroff_state_change(ms_system_t *system)
59 {
60         LOGD("Enter");
61
62         muse_return_val_if_fail(system, MM_ERROR_INVALID_ARGUMENT);
63
64         muse_return_val_if_fail(system->connection, MM_ERROR_UNKNOWN);
65
66         system->muse_poweroff_id = g_dbus_connection_signal_subscribe(system->connection, NULL,
67                 MS_POWER_DBUS_INTERFACE, MS_POWER_DBUS_MSG, NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
68                 _ms_poweroff_state_changed_cb, NULL, NULL);
69
70         LOGD("Leave");
71
72         return MM_ERROR_NONE;
73 }
74
75 static void _ms_system_unsubscribe_poweroff_state_change(void)
76 {
77         ms_system_t *system = NULL;
78
79         muse_return_if_fail(ms_get_instance());
80
81         system = ms_get_instance()->system;
82         muse_return_if_fail(system);
83         muse_return_if_fail(system->connection);
84
85         g_dbus_connection_signal_unsubscribe(system->connection, system->muse_poweroff_id);
86 }
87
88 static void _ms_poweroff_state_changed_cb(GDBusConnection *con, const gchar *sender_name, const gchar *object_path,
89                         const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
90 {
91         int val_int = 0;
92         GQueue *queue;
93         ms_cmd_dispatcher_info_t dispatch;
94         ms_system_t *system = NULL;
95         ms_connection_t *connection = NULL;
96
97         LOGE("received power off signal");
98
99         muse_return_if_fail(ms_get_instance());
100         muse_return_if_fail(object_path);
101         muse_return_if_fail(signal_name);
102         muse_return_if_fail(parameters);
103
104         system = ms_get_instance()->system;
105         muse_return_if_fail(system);
106
107         connection = ms_get_instance()->connection;
108         muse_return_if_fail(connection);
109
110         if (g_strcmp0(object_path, MS_POWER_DBUS_PATH) || g_strcmp0(signal_name, MS_POWER_DBUS_MSG)) {
111                 LOGE("object_path : %s signal_name : %s", object_path, signal_name);
112                 return;
113         }
114
115         g_variant_get(parameters, "(i)", &val_int);
116
117         LOGE("POWER OFF TYPE = %d", val_int);
118
119         /* muse has to restart when MUSE_POWER_OFF_DIRECT and MUSE_POWER_OFF_RESTART */
120         muse_return_if_fail(val_int > MUSE_POWER_OFF_POPUP);
121
122         _ms_system_unsubscribe_poweroff_state_change();
123
124         g_mutex_lock(&system->lock);
125
126         ms_connection_lock(connection);
127
128         queue = connection->instance_queue;
129
130         dispatch.cmd = MUSE_MODULE_COMMAND_SHUTDOWN;
131
132         g_queue_foreach(queue, ms_cmd_dispatch_foreach_func, (gpointer)&dispatch);
133
134         ms_connection_unlock(connection);
135
136         g_mutex_unlock(&system->lock);
137
138         exit(EXIT_FAILURE);
139 }
140 #endif
141
142 #ifdef MUSE_USE_EXTERNAL_STORAGE_STATE_CHANGE
143 static int _ms_system_subscribe_external_storage_state_change(ms_system_t *system)
144 {
145         LOGD("Enter");
146
147         int ret = storage_set_changed_cb(STORAGE_TYPE_EXTERNAL, _ms_external_storage_state_changed_cb, system);
148
149         if (ret != STORAGE_ERROR_NONE) {
150                 LOGE("[0x%x] failed to register storage changed callback", ret);
151                 return MUSE_ERR;
152         }
153
154         LOGD("Leave");
155
156         return MM_ERROR_NONE;
157 }
158
159 static void _ms_system_unsubscribe_external_storage_state_change(void)
160 {
161         int ret = storage_unset_changed_cb(STORAGE_TYPE_EXTERNAL, _ms_external_storage_state_changed_cb);
162         if (ret != STORAGE_ERROR_NONE)
163                 LOGE("[0x%x] failed to unregister storage changed callback", ret);
164 }
165
166 static void _ms_external_storage_state_changed_cb(int storage_id, storage_dev_e dev, storage_state_e state, const char *fstype,
167                         const char *fsuuid, const char *mount_path, bool primary, int flags, void *user_data)
168 {
169         GQueue *queue;
170         ms_cmd_dispatcher_info_t dispatch;
171         ms_system_t *system = (ms_system_t *)user_data;
172         ms_connection_t *connection = NULL;
173
174         muse_return_if_fail(system);
175         muse_return_if_fail(ms_get_instance());
176
177         connection = ms_get_instance()->connection;
178         muse_return_if_fail(connection);
179
180         switch (state) {
181         case STORAGE_STATE_UNMOUNTABLE:
182                 LOGI("[%d] [%s] STORAGE_STATE_UNMOUNTABLE", state, mount_path);
183                 break;
184         case STORAGE_STATE_REMOVED:
185                 LOGI("[%d] [%s] STORAGE_STATE_REMOVED", state, mount_path);
186                 break;
187         case STORAGE_STATE_MOUNTED:
188                 LOGI("[%d] [%s] STORAGE_STATE_MOUNTED", state, mount_path);
189                 break;
190         case STORAGE_STATE_MOUNTED_READ_ONLY:
191                 LOGI("[%d] [%s] STORAGE_STATE_MOUNTED_READ_ONLY", state, mount_path);
192                 break;
193         default:
194                 break;
195         }
196
197         g_mutex_lock(&system->lock);
198
199         ms_connection_lock(connection);
200
201         queue = connection->instance_queue;
202
203         dispatch.cmd = MUSE_MODULE_COMMAND_EXTERNAL_STORAGE_STATE_CHANGED;
204
205         dispatch.storage.id = storage_id;
206         dispatch.storage.state = state;
207         dispatch.storage.path = mount_path;
208
209         g_queue_foreach(queue, ms_cmd_dispatch_foreach_func, (gpointer)&dispatch);
210
211         ms_connection_unlock(connection);
212
213         g_mutex_unlock(&system->lock);
214 }
215 #endif
216
217 #ifdef MUSE_USE_RM_READY
218 static int _ms_system_subscribe_resource_manager_state_change(ms_system_t *system)
219 {
220         LOGD("Enter");
221
222         muse_return_val_if_fail(system, MM_ERROR_INVALID_ARGUMENT);
223
224         muse_return_val_if_fail(system->connection, MM_ERROR_UNKNOWN);
225
226         system->muse_rm_id = g_dbus_connection_signal_subscribe(system->connection, MS_DBUS_SERVICE,
227                 MS_DBUS_INTERFACE, MS_RM_DBUS_MSG, NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
228                 _ms_resource_manager_owner_name_changed_cb, NULL, NULL);
229         LOGD("Leave");
230
231         return MM_ERROR_NONE;
232 }
233
234 static void _ms_system_unsubscribe_resource_manager_state_change(void)
235 {
236         ms_system_t *system = NULL;
237
238         muse_return_if_fail(ms_get_instance());
239
240         system = ms_get_instance()->system;
241
242         muse_return_if_fail(system);
243         muse_return_if_fail(system->connection);
244
245         g_dbus_connection_signal_unsubscribe(system->connection, system->muse_rm_id);
246 }
247
248 static void _ms_resource_manager_owner_name_changed_cb(GDBusConnection *con, const gchar *sender_name, const gchar *object_path,
249                         const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
250 {
251         GQueue *queue;
252         ms_cmd_dispatcher_info_t dispatch;
253         ms_system_t *system = NULL;
254         ms_connection_t *connection = NULL;
255         gchar *owner_name = NULL;
256         gchar *old_owner = NULL;
257         gchar *new_owner = NULL;
258
259         muse_return_if_fail(ms_get_instance());
260         muse_return_if_fail(object_path);
261         muse_return_if_fail(signal_name);
262         muse_return_if_fail(parameters);
263
264         system = ms_get_instance()->system;
265         muse_return_if_fail(system);
266
267         connection = ms_get_instance()->connection;
268         muse_return_if_fail(connection);
269
270         if (g_strcmp0(object_path, MS_DBUS_PATH) || g_strcmp0(signal_name, MS_RM_DBUS_MSG))
271                 return;
272
273         g_variant_get(parameters, "(sss)", &owner_name, &old_owner, &new_owner);
274
275         if (g_strcmp0(owner_name, MS_RM_DBUS_SENDER) || *new_owner == '\0')
276                 goto out;
277
278         g_mutex_lock(&system->lock);
279
280         ms_connection_lock(connection);
281
282         queue = connection->instance_queue;
283
284         dispatch.cmd = MUSE_MODULE_COMMAND_RESOURCE_MANAGER_SHUTDOWN;
285
286         g_queue_foreach(queue, ms_cmd_dispatch_foreach_func, (gpointer)&dispatch);
287         LOGE("resource manager shutdown");
288
289         ms_connection_unlock(connection);
290
291         g_mutex_unlock(&system->lock);
292 out:
293         g_free(owner_name);
294         g_free(old_owner);
295         g_free(new_owner);
296 }
297 #endif
298
299 void ms_system_init(ms_system_t *system)
300 {
301         GError *error = NULL;
302
303         muse_return_if_fail(system);
304
305         LOGD("Enter");
306
307         system->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
308         if (!system->connection) {
309                 if (error) {
310                         LOGE("fail to get gdbus connection (%s)", error->message);
311                         g_error_free(error);
312                 }
313         }
314
315         system->platform_info_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
316         muse_return_if_fail(system->platform_info_table);
317
318         g_mutex_init(&system->lock);
319
320         LOGD("Leave");
321 }
322
323 void ms_system_deinit(ms_system_t *system)
324 {
325         muse_return_if_fail(system);
326 #ifdef MUSE_USE_POWER_OFF_STATE_CHANGE
327         _ms_system_unsubscribe_poweroff_state_change();
328 #endif
329 #ifdef MUSE_USE_EXTERNAL_STORAGE_STATE_CHANGE
330         _ms_system_unsubscribe_external_storage_state_change();
331 #endif
332 #ifdef MUSE_USE_RM_READY
333         _ms_system_unsubscribe_resource_manager_state_change();
334 #endif
335         if (system->connection)
336                 g_object_unref(system->connection);
337
338         g_mutex_clear(&system->lock);
339
340         g_hash_table_destroy(system->platform_info_table);
341
342         g_free(system);
343 }
344
345 int ms_system_get_platform_info(const char *key, bool *value)
346 {
347         int ret = MM_ERROR_NONE;
348         gpointer orig_value;
349         ms_system_t *system = NULL;
350
351         muse_return_val_if_fail(ms_get_instance(), MM_ERROR_UNKNOWN);
352
353         system = ms_get_instance()->system;
354
355         muse_return_val_if_fail(system, MM_ERROR_INVALID_ARGUMENT);
356         muse_return_val_if_fail(key, MM_ERROR_INVALID_ARGUMENT);
357         muse_return_val_if_fail(value, MM_ERROR_INVALID_ARGUMENT);
358
359         g_mutex_lock(&system->lock);
360
361         if (g_hash_table_lookup_extended(system->platform_info_table, key, NULL, &orig_value)) {
362                 *value = GPOINTER_TO_INT(orig_value);
363         } else {
364                 ret = system_info_get_platform_bool(key, value);
365                 switch (ret) {
366                 case SYSTEM_INFO_ERROR_NONE: /* Successful */
367                         g_hash_table_insert(system->platform_info_table, g_strdup(key), GINT_TO_POINTER(*value));
368                         ret = MM_ERROR_NONE;
369                         break;
370                 case SYSTEM_INFO_ERROR_INVALID_PARAMETER: /* Cannot find the key in the model config file */
371                         ret = MM_ERROR_COMMON_ATTR_NOT_EXIST;
372                         break;
373                 case SYSTEM_INFO_ERROR_IO_ERROR: /* An input/output error occurred while reading the value from the model config file */
374                         ret = MM_ERROR_UNKNOWN;
375                         break;
376                 case SYSTEM_INFO_ERROR_PERMISSION_DENIED: /* No permission to use the API */
377                         ret = MM_ERROR_COMMON_INVALID_PERMISSION;
378                         break;
379                 default:
380                         LOGE("system_info_get_platform_bool returns 0x%x", ret);
381                         ret = MM_ERROR_UNKNOWN;
382                         break;
383                 }
384         }
385
386         g_mutex_unlock(&system->lock);
387
388         return ret;
389 }
390
391 void ms_system_subscribe_external_event(ms_system_t *system)
392 {
393 #ifdef MUSE_USE_EXTERNAL_STORAGE_STATE_CHANGE
394         int ret = MM_ERROR_NONE;
395         bool is_external_storage_enabled = false;
396 #endif
397         muse_return_if_fail(system);
398
399 #ifdef MUSE_USE_POWER_OFF_STATE_CHANGE
400         if (_ms_system_subscribe_poweroff_state_change(system) != MM_ERROR_NONE)
401                 LOGE("Fail to subscribe poweroff state change");
402 #endif
403
404 #ifdef MUSE_USE_EXTERNAL_STORAGE_STATE_CHANGE
405         /* external storage feature is supported as of tizen_5.5 */
406         ret = system_info_get_platform_bool(MUSE_STORAGE_EXTERNAL_FEATURE, &is_external_storage_enabled);
407
408         if (ret != MM_ERROR_NONE) /* get the value of mused.conf until tizen_5.0 */
409                 is_external_storage_enabled = (bool)ms_config_is_external_storage_enabled();
410
411         if (is_external_storage_enabled == true && _ms_system_subscribe_external_storage_state_change(system) != MM_ERROR_NONE)
412                 LOGE("Fail to subscribe external storage state change");
413 #endif
414
415 #ifdef MUSE_USE_RM_READY
416         if (_ms_system_subscribe_resource_manager_state_change(system) != MM_ERROR_NONE)
417                 LOGE("Fail to subscribe resource manager state change");
418 #endif
419 }
420
421 int ms_system_get_memory_usage(int pid)
422 {
423         int used_pss = 0;
424         process_memory_info_s *info = NULL;
425         int ret = runtime_info_get_process_memory_info(&pid, 1, &info);
426
427         if (MM_ERROR_NONE == ret && info)
428                 used_pss = info->pss;
429         else
430                 LOGE("Fail to get process (%d) memory %s", pid, get_error_message(ret));
431
432         MUSE_FREE(info);
433
434         return used_pss;
435 }
436
437 gboolean ms_system_get_gdbus(GDBusConnection **connection)
438 {
439         LOGD("Enter");
440
441         ms_system_t *system = NULL;
442
443         muse_return_val_if_fail(ms_get_instance(), FALSE);
444
445         system = ms_get_instance()->system;
446         muse_return_val_if_fail(system, FALSE);
447         muse_return_val_if_fail(system->connection, FALSE);
448
449         *connection = system->connection;
450
451         return TRUE;
452 }
453