2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "daemon/mm_resource_manager_daemon_dbus.h"
18 #include "common/mm_resource_manager_dbus.h"
19 #include "daemon/mm_resource_manager_daemon_priv.h"
20 #include "common/mm_resource_manager_utils.h"
21 #include "daemon/mm_resource_manager_daemon_conf.h"
24 static MMResourceManager *interface;
26 extern int notify_fd[2];
29 static void __gv2c_array(GVariantIter *gv, mm_resource_manager_dmn_res_request_s **c);
30 static gboolean on_get_conf(MMResourceManager *interface,
31 GDBusMethodInvocation *invocation, gpointer user_data);
32 static gboolean on_create_handle(MMResourceManager *interface,
33 GDBusMethodInvocation *invocation, const gint app_class,
35 static gboolean on_destroy_handle(MMResourceManager *interface,
36 GDBusMethodInvocation *invocation, const guint64 id, gpointer user_data);
37 static gboolean on_commit_handle(MMResourceManager *interface,
38 GDBusMethodInvocation *invocation, const guint64 id,
39 GVariant *release, GVariant *acquire, gpointer user_data);
40 static void on_bus_acquired(GDBusConnection *connection, const gchar *name,
43 static gboolean _type_is_valid(int type)
45 if ((type != MM_RESOURCE_MANAGER_NO_RES) &&
46 (type < MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER || type >= MM_RESOURCE_MANAGER_RES_TYPE_MAX))
53 static gboolean _create_pid_file(void)
57 char pid_buf[PID_MSG_LEN] = {'\0',};
59 fd = open(PID_FILE, O_WRONLY | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
60 MM_RM_RETVM_IF(fd < 0, FALSE, "PID file cannot be created (%d)", errno);
62 lock.l_type = F_WRLCK;
64 lock.l_whence = SEEK_SET;
67 if (fcntl(fd, F_SETLK, &lock) < 0) {
68 if (errno != EACCES && errno != EAGAIN)
69 MM_RM_ERROR("Fail to lock pidfile [%d]", errno);
71 MM_RM_ERROR("process is already running");
76 if (ftruncate(fd, 0) < 0) {
77 MM_RM_ERROR("Fail to truncate pidfile [%d]", errno);
81 memset(pid_buf, 0, sizeof(pid_buf));
82 snprintf(pid_buf, sizeof(pid_buf), "%u", getpid());
84 if (write(fd, pid_buf, strlen(pid_buf)) != (int)strlen(pid_buf)) {
85 MM_RM_ERROR("Fail to write pid to pidfile [%d]", errno);
91 MM_RM_INFO("PID file (%s) is created", PID_FILE);
99 static gboolean _create_ready_file(void)
103 if ((fd = creat(MM_RESOURCE_MANAGER_READY, 0644)) != -1) {
104 MM_RM_INFO("ready file(%s) file was created", MM_RESOURCE_MANAGER_READY);
107 MM_RM_ERROR("cannot create ready file(%s), errno(%d)", MM_RESOURCE_MANAGER_READY, errno);
114 static gboolean _create_daemon_setup_file(void)
116 _mmrm_dmn_notify_fork_done();
117 return _create_pid_file() && _create_ready_file();
120 int _mmrm_dmn_dbus_init(void)
122 interface = mmresource_manager_skeleton_new();
123 MM_RM_RETVM_IF(interface == NULL,
124 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
125 "Interface cannot be created");
126 g_bus_own_name(G_BUS_TYPE_SYSTEM, RMD_GDBUS_NAME,
127 G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, NULL, NULL, NULL,
129 return MM_RESOURCE_MANAGER_ERROR_NONE;
132 int _mmrm_dmn_dbus_deinit(void)
134 MM_RM_RETVM_IF(interface == NULL,
135 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Interface is NULL");
136 g_object_unref(interface);
138 return MM_RESOURCE_MANAGER_ERROR_NONE;
141 int _mmrm_dmn_dbus_get_conf(mm_resource_manager_res_volume **max_volume,
142 mm_resource_manager_condition_volume_a **cond_volume, int **max_instance)
144 mm_resource_manager_conf_s *conf;
146 conf = mm_resource_manager_get_conf();
148 MM_RM_RETVM_IF(conf == NULL,
149 MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
150 "mm_resource_manager_conf is NULL");
152 *max_volume = conf->max_volume;
153 *cond_volume = &conf->condition_volume;
154 *max_instance = conf->max_instance;
156 return MM_RESOURCE_MANAGER_ERROR_NONE;
159 int _mmrm_dmn_dbus_create(mm_resource_manager_app_class_e app_class,
160 mm_resource_manager_id *id)
162 return _mmrm_dmn_create(app_class, id);
165 int _mmrm_dmn_dbus_destroy(mm_resource_manager_id id)
167 return _mmrm_dmn_destroy(id);
170 int _mmrm_dmn_dbus_commit(mm_resource_manager_id id, GVariantIter *release,
171 GVariantIter *acquire, gboolean **is_acquired)
175 mm_resource_manager_res_type_e type;
176 mm_resource_manager_dmn_res_request_s *release_requests = NULL, *acquire_requests = NULL;
177 gsize release_len = 0, acquire_len = 0;
179 __gv2c_array(release, &release_requests);
181 type = release_requests->type;
182 release_len = g_variant_iter_n_children(release);
184 if (!_type_is_valid(type)) {
185 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
189 MM_RM_DEBUG("Commit release request of %"G_GSIZE_FORMAT" items [type %d]", release_len, type);
191 __gv2c_array(acquire, &acquire_requests);
193 type = acquire_requests->type;
194 acquire_len = g_variant_iter_n_children(acquire);
196 if (!_type_is_valid(type)) {
197 ret = MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
201 MM_RM_DEBUG("Commit acquire request of %"G_GSIZE_FORMAT" items [type %d]", acquire_len, type);
203 *is_acquired = (gboolean *) g_malloc0_n(acquire_len, sizeof(**is_acquired));
205 ret = _mmrm_dmn_commit(id, release_requests, acquire_requests);
207 for (i = 0; acquire_requests[i].type != MM_RESOURCE_MANAGER_NO_RES; i++)
208 (*is_acquired)[i] = acquire_requests[i].priority_error;
211 g_free(release_requests);
212 g_free(acquire_requests);
217 int _mmrm_dmn_dbus_release_callback(mm_resource_manager_id id,
218 mm_resource_manager_res_type_e type,
219 mm_resource_manager_res_volume volume)
221 mmresource_manager_emit_release_callback(interface, id, type, volume);
222 return MM_RESOURCE_MANAGER_ERROR_NONE;
225 int _mmrm_dmn_dbus_status_callback(mm_resource_manager_status_e status)
227 MM_RM_DEBUG("Emitting %d status", status);
228 mmresource_manager_emit_status_callback(interface, status);
229 return MM_RESOURCE_MANAGER_ERROR_NONE;
232 void _mmrm_dmn_notify_fork_done(void)
234 /* Send "string" through the output side of pipe */
235 MM_RM_RETM_IF(write(notify_fd[1], MSG_DONE, strlen(MSG_DONE) + 1) < 0,
236 "Failed to notify parent process that child initialization is done");
238 MM_RM_DEBUG("[%d] Notify parent process that child initialization is done", notify_fd[1]);
243 static void __gv2c_array(GVariantIter *gv, mm_resource_manager_dmn_res_request_s **c)
246 mm_resource_manager_res_type_e type;
247 mm_resource_manager_dmn_res_request_s *rs;
249 rs = (mm_resource_manager_dmn_res_request_s *)g_malloc0_n(g_variant_iter_n_children(gv), sizeof(*rs));
250 for (i = 0; g_variant_iter_next(gv, "(ii)", &rs[i].type, &rs[i].volume); i++) {
252 if (!_type_is_valid(type)) {
253 MM_RM_ERROR("type %d is wrong", type);
257 MM_RM_DEBUG("(type, vol) = (%d, %d)", type, rs[i].volume);
263 static gboolean on_get_conf(MMResourceManager *interface,
264 GDBusMethodInvocation *invocation, gpointer user_data)
268 mm_resource_manager_res_volume *max_volume = NULL;
269 mm_resource_manager_condition_volume_a *cond_volume = NULL;
270 int *max_instance = NULL;
271 GVariantBuilder *res_type_builder;
272 GVariantBuilder *res_cond_builder;
273 GVariantBuilder *res_instance_builder;
274 GVariant *res_type_conf;
275 GVariant *res_cond_conf;
276 GVariant *res_instance_conf;
278 error = _mmrm_dmn_dbus_get_conf(&max_volume, &cond_volume, &max_instance);
280 res_type_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
281 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
282 g_variant_builder_add_value(res_type_builder, g_variant_new("i", max_volume[i]));
284 res_type_conf = g_variant_builder_end(res_type_builder);
285 g_variant_builder_unref(res_type_builder);
287 res_type_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
288 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++) {
289 res_cond_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
290 for (j = 0; j < MM_RESOURCE_MANAGER_RES_TYPE_COND_MAX; j++)
291 g_variant_builder_add_value(res_cond_builder, g_variant_new("i", (*cond_volume)[i][j]));
293 g_variant_builder_add_value(res_type_builder, g_variant_builder_end(res_cond_builder));
294 g_variant_builder_unref(res_cond_builder);
296 res_cond_conf = g_variant_builder_end(res_type_builder);
297 g_variant_builder_unref(res_type_builder);
299 res_instance_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
300 for (i = 0; i < MM_RESOURCE_MANAGER_RES_TYPE_MAX; i++)
301 g_variant_builder_add_value(res_instance_builder, g_variant_new("i", max_instance[i]));
302 res_instance_conf = g_variant_builder_end(res_instance_builder);
303 g_variant_builder_unref(res_instance_builder);
305 mmresource_manager_complete_conf(interface, invocation, error, res_type_conf, res_cond_conf, res_instance_conf);
310 static gboolean on_create_handle(MMResourceManager *interface,
311 GDBusMethodInvocation *invocation, const gint app_class,
317 error = _mmrm_dmn_dbus_create(app_class, &id);
319 MM_RM_DEBUG("Receive create message for RM");
321 mmresource_manager_complete_create(interface, invocation, id, error);
326 static gboolean on_destroy_handle(MMResourceManager *interface,
327 GDBusMethodInvocation *invocation, const guint64 id, gpointer user_data)
331 MM_RM_DEBUG("Receive destroy message for RM");
332 error = _mmrm_dmn_dbus_destroy(id);
334 mmresource_manager_complete_destroy(interface, invocation, error);
338 static gboolean on_commit_handle(MMResourceManager *interface,
339 GDBusMethodInvocation *invocation, const guint64 id,
340 GVariant *release, GVariant *acquire, gpointer user_data)
343 gboolean ret = TRUE, *flags;
344 GVariantBuilder *flags_builder;
345 GVariantIter *release_array;
346 GVariantIter *acquire_array;
349 MM_RM_DEBUG("Receive commit message");
351 release_array = g_variant_iter_new(release);
352 acquire_array = g_variant_iter_new(acquire);
354 error = _mmrm_dmn_dbus_commit(id, release_array, acquire_array, &flags);
355 if (error != MM_RESOURCE_MANAGER_ERROR_NONE) {
356 MM_RM_ERROR("dbus commit error");
361 flags_builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
362 for (i = 0; i < g_variant_iter_n_children(acquire_array); i++)
363 g_variant_builder_add_value(flags_builder, g_variant_new("b", flags[i]));
364 mmresource_manager_complete_commit(interface, invocation, error, g_variant_builder_end(flags_builder));
367 g_variant_builder_unref(flags_builder);
370 g_variant_iter_free(release_array);
371 g_variant_iter_free(acquire_array);
376 static void on_bus_acquired(GDBusConnection *connection, const gchar *name,
379 GError *error = NULL;
380 MM_RM_DEBUG("name of bus = %s, userID = %d", name, getuid());
382 g_signal_connect(interface, "handle-conf", G_CALLBACK(on_get_conf), NULL);
383 g_signal_connect(interface, "handle-create", G_CALLBACK(on_create_handle), NULL);
384 g_signal_connect(interface, "handle-destroy", G_CALLBACK(on_destroy_handle), NULL);
385 g_signal_connect(interface, "handle-commit", G_CALLBACK(on_commit_handle), NULL);
387 if (!g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(interface),
388 connection, RMD_GDBUS_PATH, &error)) {
389 MM_RM_ERROR("failed to export interface. msg : %s", error->message);
394 MM_RM_RETM_IF(!_create_daemon_setup_file(), "Daemon cannot create setup file");