1 /* vi:set et ai sw=2 sts=2 ts=2: */
3 * Copyright (c) 2012 GENIVI.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 #include <glib-object.h>
19 #include <common/nsm-consumer-dbus.h>
20 #include <common/shutdown-consumer-dbus.h>
22 #include <boot-manager/job-manager.h>
23 #include <boot-manager/la-handler-dbus.h>
24 #include <boot-manager/la-handler-service.h>
28 DLT_IMPORT_CONTEXT (la_handler_context);
32 /* property identifiers */
42 typedef struct _LAHandlerServiceConsumerBundle LAHandlerServiceConsumerBundle;
43 typedef struct _LAHandlerServiceShutdownConsumer LAHandlerServiceShutdownConsumer;
47 static void la_handler_service_constructed (GObject *object);
48 static void la_handler_service_finalize (GObject *object);
49 static void la_handler_service_get_property (GObject *object,
53 static void la_handler_service_set_property (GObject *object,
57 static gboolean la_handler_service_handle_register (LAHandler *interface,
58 GDBusMethodInvocation *invocation,
62 LAHandlerService *service);
63 static void la_handler_service_handle_register_finish (NSMConsumer *nsm_consumer,
65 GDBusMethodInvocation *invocation);
66 static gboolean la_handler_service_handle_deregister (LAHandler *interface,
67 GDBusMethodInvocation *invocation,
69 LAHandlerService *service);
70 static void la_handler_service_handle_consumer_lifecycle_request (ShutdownConsumer *interface,
71 GDBusMethodInvocation *invocation,
74 LAHandlerService *service);
75 static void la_handler_service_handle_consumer_lifecycle_request_finish (JobManager *manager,
81 struct _LAHandlerServiceClass
83 GObjectClass __parent__;
86 struct _LAHandlerService
90 GDBusConnection *connection;
92 JobManager *job_manager;
94 /* Associations of shutdown consumers and their units */
95 GHashTable *units_to_consumers;
96 GHashTable *consumers_to_units;
102 /* connection to the NSM consumer interface */
103 NSMConsumer *nsm_consumer;
108 G_DEFINE_TYPE (LAHandlerService, la_handler_service, G_TYPE_OBJECT);
113 la_handler_service_class_init (LAHandlerServiceClass *klass)
115 GObjectClass *gobject_class;
117 gobject_class = G_OBJECT_CLASS (klass);
118 gobject_class->constructed = la_handler_service_constructed;
119 gobject_class->finalize = la_handler_service_finalize;
120 gobject_class->get_property = la_handler_service_get_property;
121 gobject_class->set_property = la_handler_service_set_property;
123 g_object_class_install_property (gobject_class,
125 g_param_spec_object ("connection",
128 G_TYPE_DBUS_CONNECTION,
130 G_PARAM_CONSTRUCT_ONLY |
131 G_PARAM_STATIC_STRINGS));
132 g_object_class_install_property (gobject_class,
134 g_param_spec_object ("job-manager",
136 "The internal handler of Start()"
140 G_PARAM_CONSTRUCT_ONLY |
141 G_PARAM_STATIC_STRINGS));
147 la_handler_service_constructed (GObject *object)
149 LAHandlerService *service = LA_HANDLER_SERVICE (object);
150 GError *error = NULL;
153 /* connect to the node state manager */
154 service->nsm_consumer =
155 nsm_consumer_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
156 "com.contiautomotive.NodeStateManager",
157 "/com/contiautomotive/NodeStateManager/Consumer",
161 log_text = g_strdup_printf ("Error occurred connecting to NSM Consumer: %s",
163 DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text));
165 g_error_free (error);
172 la_handler_service_init (LAHandlerService *service)
174 service->interface = la_handler_skeleton_new ();
176 /* the number that follows the prefix in the shutdown consumer's object path,
177 * making every shutdown consumer unique */
180 /* the string that precedes the index in the shutdown consumer's object path */
181 service->prefix = "/org/genivi/BootManager1/ShutdownConsumer";
183 /* initialize the association of shutdown consumers to units */
184 service->units_to_consumers =
185 g_hash_table_new_full (g_str_hash, g_str_equal,
186 (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref);
187 service->consumers_to_units =
188 g_hash_table_new_full (g_direct_hash, g_direct_equal,
189 (GDestroyNotify) g_object_unref, (GDestroyNotify) g_free);
191 /* implement the Register() handler */
192 g_signal_connect (service->interface, "handle-register",
193 G_CALLBACK (la_handler_service_handle_register),
196 /* implement the Deregister() handler */
197 g_signal_connect (service->interface, "handle-deregister",
198 G_CALLBACK (la_handler_service_handle_deregister),
205 la_handler_service_finalize (GObject *object)
207 LAHandlerService *service = LA_HANDLER_SERVICE (object);
209 /* release the bus name */
210 g_bus_unown_name (service->bus_name_id);
212 /* release the D-Bus connection object */
213 if (service->connection != NULL)
214 g_object_unref (service->connection);
216 /* release the interface skeleton */
217 g_signal_handlers_disconnect_matched (service->interface,
219 0, 0, NULL, NULL, service);
220 g_object_unref (service->interface);
222 /* release the job manager skeleton */
223 g_object_unref (service->job_manager);
225 /* release the shutdown consumers */
226 g_hash_table_destroy (service->units_to_consumers);
227 g_hash_table_destroy (service->consumers_to_units);
229 (*G_OBJECT_CLASS (la_handler_service_parent_class)->finalize) (object);
235 la_handler_service_get_property (GObject *object,
240 LAHandlerService *service = LA_HANDLER_SERVICE (object);
244 case PROP_CONNECTION:
245 g_value_set_object (value, service->connection);
247 case PROP_JOB_MANAGER:
248 g_value_set_object (value, service->job_manager);
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259 la_handler_service_set_property (GObject *object,
264 LAHandlerService *service = LA_HANDLER_SERVICE (object);
268 case PROP_CONNECTION:
269 service->connection = g_value_dup_object (value);
271 case PROP_JOB_MANAGER:
272 service->job_manager = g_value_dup_object (value);
275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
283 la_handler_service_handle_register (LAHandler *interface,
284 GDBusMethodInvocation *invocation,
288 LAHandlerService *service)
290 /* delegate registration of the legacy app to a more generalised function */
291 la_handler_service_register (service, unit, mode, timeout,
292 (GAsyncReadyCallback) la_handler_service_handle_register_finish, invocation);
300 la_handler_service_handle_register_finish (NSMConsumer *nsm_consumer,
302 GDBusMethodInvocation *invocation)
304 GError *error = NULL;
308 nsm_consumer_call_register_shutdown_client_finish (nsm_consumer, &error_code, res,
312 log_text = g_strdup_printf ("Error occurred registering legacy app: %s",
314 DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text));
316 g_error_free (error);
319 /* notify the caller that we have handled the registration request */
320 g_dbus_method_invocation_return_value (invocation, NULL);
326 la_handler_service_handle_deregister (LAHandler *object,
327 GDBusMethodInvocation *invocation,
329 LAHandlerService *service)
331 /* notify the caller that we have handled the registration request */
332 g_dbus_method_invocation_return_value (invocation, NULL);
339 la_handler_service_handle_consumer_lifecycle_request (ShutdownConsumer *interface,
340 GDBusMethodInvocation *invocation,
343 LAHandlerService *service)
345 GVariant *return_type;
346 gchar *unit_name = g_hash_table_lookup (service->consumers_to_units, interface);
348 /* call job_manager_stop */
349 job_manager_stop (service->job_manager, unit_name, NULL,
350 la_handler_service_handle_consumer_lifecycle_request_finish,
351 GUINT_TO_POINTER (request_id));
353 /* returns for the invocation (with error code) */
354 return_type = g_variant_new_int32 (1); /* bare number because enum comes later */
355 g_dbus_method_invocation_return_value (invocation, return_type);
356 g_variant_unref (return_type);
362 la_handler_service_handle_consumer_lifecycle_request_finish (JobManager *manager,
373 log_text = g_strdup_printf ("Error occurred handling lifecycle request: %s",
375 DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text));
379 if (g_strcmp0 (result, "failed") == 0)
381 DLT_LOG (la_handler_context, DLT_LOG_ERROR,
382 DLT_STRING ("Error occurred handling lifecycle request"));
390 la_handler_service_new (GDBusConnection *connection,
391 JobManager *job_manager)
393 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
394 g_return_val_if_fail (IS_JOB_MANAGER (job_manager), NULL);
396 return g_object_new (LA_HANDLER_TYPE_SERVICE,
397 "connection", connection,
398 "job-manager", job_manager,
404 la_handler_service_start (LAHandlerService *service,
407 g_return_val_if_fail (LA_HANDLER_IS_SERVICE (service), FALSE);
408 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
410 /* announce the org.genivi.BootManager1.LegacyAppHandler service on the bus */
411 return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (service->interface),
413 "/org/genivi/BootManager1/LegacyAppHandler",
420 la_handler_service_register (LAHandlerService *service,
424 GAsyncReadyCallback callback,
427 ShutdownConsumer *consumer;
428 GError *error = NULL;
432 g_return_if_fail (LA_HANDLER_IS_SERVICE (service));
433 g_return_if_fail (unit != NULL && *unit != '\0');
434 g_return_if_fail (mode != NULL && *mode != '\0');
436 /* find out if this unit is already registered with a shutdown consumer */
437 if (g_hash_table_lookup (service->units_to_consumers, unit))
440 /* create a new ShutdownConsumer and store it in service */
441 consumer = shutdown_consumer_skeleton_new ();
442 g_hash_table_insert (service->units_to_consumers, g_strdup (unit),
443 g_object_ref (consumer));
444 g_hash_table_insert (service->consumers_to_units, g_object_ref (consumer),
448 /* set up signal handling and skeleton exporting */
449 object_path = g_strdup_printf ("%s/%u", service->prefix, service->index);
450 g_signal_connect (consumer, "handle-lifecycle-request",
451 G_CALLBACK (la_handler_service_handle_consumer_lifecycle_request),
453 g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (consumer),
454 service->connection, object_path, &error);
458 g_strdup_printf ("Error exporting shutdown consumer interface skeleton: %s",
460 DLT_LOG (la_handler_context, DLT_LOG_ERROR, DLT_STRING (log_text));
462 g_error_free (error);
465 /* register the shutdown consumer with the NSM Consumer */
466 nsm_consumer_call_register_shutdown_client (service->nsm_consumer,
467 "org.genivi.BootManager1", object_path, 0,
468 timeout, NULL, callback, user_data);
470 g_free (object_path);