summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--src/app_info.c32
-rw-r--r--src/app_info.h7
-rw-r--r--src/app_launcher.c149
-rw-r--r--src/meson.build1
-rw-r--r--src/process_manager.c220
-rw-r--r--src/process_manager.h38
-rw-r--r--src/systemd_manager.c120
-rw-r--r--src/systemd_manager.h10
9 files changed, 186 insertions, 397 deletions
diff --git a/README.md b/README.md
index 943679c..83ea36d 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,9 @@ This interface can be used to:
For more details about the D-Bus interface, please refer to the file
`data/org.automotivelinux.AppLaunch.xml`.
-Applications can be started either through D-Bus activation (using their D-Bus
-name) or by specifying a command line to be executed, and are monitored until
-they exit. Please note `applaunchd` allows only one instance of a given
+Applications are enumerated from systemd's list of available units based on
+the pattern agl-app*@*.service, and are started and controled using their
+systemd unit. Please note `applaunchd` allows only one instance of a given
application.
AGL repo for source code:
diff --git a/src/app_info.c b/src/app_info.c
index 0d25d37..97ecf7e 100644
--- a/src/app_info.c
+++ b/src/app_info.c
@@ -24,9 +24,7 @@ struct _AppInfo {
gchar *app_id;
gchar *name;
gchar *icon_path;
- gchar *command;
- gboolean systemd_activated;
- gboolean graphical;
+ gchar *service;
AppStatus status;
@@ -50,7 +48,7 @@ static void app_info_dispose(GObject *object)
g_clear_pointer(&self->app_id, g_free);
g_clear_pointer(&self->name, g_free);
g_clear_pointer(&self->icon_path, g_free);
- g_clear_pointer(&self->app_id, g_free);
+ g_clear_pointer(&self->service, g_free);
g_clear_pointer(&self->runtime_data, g_free);
G_OBJECT_CLASS(app_info_parent_class)->dispose(object);
@@ -78,18 +76,14 @@ static void app_info_init(AppInfo *self)
*/
AppInfo *app_info_new(const gchar *app_id, const gchar *name,
- const gchar *icon_path, const gchar *command,
- gboolean systemd_activated,
- gboolean graphical)
+ const gchar *icon_path, const gchar *service)
{
AppInfo *self = g_object_new(APPLAUNCHD_TYPE_APP_INFO, NULL);
self->app_id = g_strdup(app_id);
self->name = g_strdup(name);
self->icon_path = g_strdup(icon_path);
- self->command = g_strdup(command);
- self->systemd_activated = systemd_activated;
- self->graphical = graphical;
+ self->service = g_strdup(service);
return self;
}
@@ -115,25 +109,11 @@ const gchar *app_info_get_icon_path(AppInfo *self)
return self->icon_path;
}
-const gchar *app_info_get_command(AppInfo *self)
+const gchar *app_info_get_service(AppInfo *self)
{
g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), NULL);
- return self->command;
-}
-
-gboolean app_info_get_systemd_activated(AppInfo *self)
-{
- g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), FALSE);
-
- return self->systemd_activated;
-}
-
-gboolean app_info_get_graphical(AppInfo *self)
-{
- g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), FALSE);
-
- return self->graphical;
+ return self->service;
}
AppStatus app_info_get_status(AppInfo *self)
diff --git a/src/app_info.h b/src/app_info.h
index 5e69dc3..f420965 100644
--- a/src/app_info.h
+++ b/src/app_info.h
@@ -33,16 +33,13 @@ G_DECLARE_FINAL_TYPE(AppInfo, app_info, APPLAUNCHD,
APP_INFO, GObject);
AppInfo *app_info_new(const gchar *app_id, const gchar *name,
- const gchar *icon_path, const gchar *command,
- gboolean systemd_activated, gboolean graphical);
+ const gchar *icon_path, const gchar *service);
/* Accessors for read-only members */
const gchar *app_info_get_app_id(AppInfo *self);
const gchar *app_info_get_name(AppInfo *self);
const gchar *app_info_get_icon_path(AppInfo *self);
-const gchar *app_info_get_command(AppInfo *self);
-gboolean app_info_get_systemd_activated(AppInfo *self);
-gboolean app_info_get_graphical(AppInfo *self);
+const gchar *app_info_get_service(AppInfo *self);
/* Accessors for read-write members */
AppStatus app_info_get_status(AppInfo *self);
diff --git a/src/app_launcher.c b/src/app_launcher.c
index 423bf19..417f59a 100644
--- a/src/app_launcher.c
+++ b/src/app_launcher.c
@@ -14,11 +14,8 @@
* limitations under the License.
*/
-#include <gio/gdesktopappinfo.h>
-
#include "app_info.h"
#include "app_launcher.h"
-#include "process_manager.h"
#include "systemd_manager.h"
#include "utils.h"
@@ -29,7 +26,6 @@ typedef struct _AppLauncher {
sd_event *event;
sd_bus *bus;
- ProcessManager *process_manager;
SystemdManager *systemd_manager;
GList *apps_list;
@@ -57,114 +53,87 @@ static void app_launcher_started_cb(AppLauncher *self,
/*
* This function is executed during the object initialization. It goes through
* all available applications on the system and creates a static list
- * containing all the relevant info (ID, name, command, icon...) for further
+ * containing all the relevant info (ID, name, unit, icon...) for further
* processing.
*/
static void app_launcher_update_applications_list(AppLauncher *self)
{
- g_autoptr(GList) app_list = g_app_info_get_all();
g_auto(GStrv) dirlist = NULL;
- guint len = g_list_length(app_list);
char *xdg_data_dirs = getenv("XDG_DATA_DIRS");
if (xdg_data_dirs)
dirlist = g_strsplit(getenv("XDG_DATA_DIRS"), ":", -1);
- for (guint i = 0; i < len; i++) {
- GAppInfo *appinfo = g_list_nth_data(app_list, i);
- const gchar *desktop_id = g_app_info_get_id(appinfo);
- GIcon *icon = g_app_info_get_icon(appinfo);
- g_autoptr(GDesktopAppInfo) desktop_info = g_desktop_app_info_new(desktop_id);
+ GList *units = NULL;
+ if (!systemd_manager_enumerate_app_units(self->systemd_manager, self, &units)) {
+ return;
+ }
+
+ GList *iterator;
+ for (iterator = units; iterator != NULL; iterator = iterator->next) {
g_autofree const gchar *app_id = NULL;
g_autofree const gchar *icon_path = NULL;
AppInfo *app_info = NULL;
- gboolean systemd_activated, graphical;
- if (!desktop_info) {
- g_warning("Unable to find .desktop file for application '%s'", desktop_id);
+ if (!iterator->data)
continue;
- }
- /* Check the application should be part of the apps list */
- if (!g_app_info_should_show(appinfo)) {
- g_debug("Application '%s' shouldn't be shown, skipping...", desktop_id);
- continue;
- }
+ // Parse service and app id out of unit filename
+ gchar *service = g_strrstr(iterator->data, "/");
+ if (!service)
+ service = iterator->data;
+ else
+ service += 1;
- if (g_desktop_app_info_get_is_hidden(desktop_info)) {
- g_debug("Application '%s' is hidden, skipping...", desktop_id);
- continue;
+ g_autofree char *tmp = g_strdup(service);
+ char *end = tmp + strlen(tmp);
+ while (end > tmp && *end != '.') {
+ --end;
}
- if (g_desktop_app_info_get_nodisplay(desktop_info)) {
- g_debug("Application '%s' has NoDisplay set, skipping...", desktop_id);
+ if (end > tmp) {
+ *end = '\0';
+ } else {
+ g_free(tmp);
continue;
}
-
- /*
- * The application ID is usually the .desktop file name. However, a common practice
- * is that .desktop files are named after the executable name, in which case the
- * "StartupWMClass" property indicates the wayland app-id.
- */
- app_id = g_strdup(g_desktop_app_info_get_startup_wm_class(desktop_info));
- if (!app_id) {
- app_id = g_strdup(desktop_id);
- gchar *extension = g_strrstr(app_id, ".desktop");
- if (extension)
- *extension = 0;
+ while (end > tmp && *end != '@') {
+ --end;
}
-
- /*
- * An application can be D-Bus activated if one of those conditions are met:
- * - its .desktop file contains a "DBusActivatable=true" line
- * - it provides a corresponding D-Bus service file
- * HACK: Use "DBusActivatable=true" in .desktop to mark systemd-based service
- */
-
- /* Default to non-DBus-activatable */
- systemd_activated = FALSE;
- if (g_desktop_app_info_get_boolean(desktop_info,
- G_KEY_FILE_DESKTOP_KEY_DBUS_ACTIVATABLE)) {
- systemd_activated = TRUE;
- } else if (dirlist) {
- const gchar *desktop_filename = g_desktop_app_info_get_filename(desktop_info);
- g_autofree gchar *service_file = g_strconcat(app_id, ".service", NULL);
-
- for (GStrv xdg_data_dir = dirlist; *xdg_data_dir != NULL ; xdg_data_dir++) {
- g_autofree gchar *service_path = NULL;
-
- /* Search only in the XDG_DATA_DIR where the .desktop file is located */
- if (!g_str_has_prefix(desktop_filename, *xdg_data_dir))
- continue;
-
- service_path = g_build_filename(*xdg_data_dir, "dbus-1", "services",
- service_file, NULL);
- if (g_file_test(service_path, G_FILE_TEST_EXISTS)) {
- systemd_activated = TRUE;
- break;
- }
- }
+ if (end > tmp) {
+ app_id = g_strdup(end + 1);
+ }
+ // Potentially handle non-template agl-app-foo.service units here
+
+ // Try getting display name from unit Description property
+ char *name = NULL;
+ if (!systemd_manager_get_app_description(self->systemd_manager,
+ self,
+ service,
+ &name) ||
+ name == NULL) {
+
+ // Fall back to the application ID
+ g_warning("Could not retrieve Description of '%s'", service);
+ name = app_id;
}
-
- /* Applications with "Terminal=True" are not graphical apps */
- graphical = !g_desktop_app_info_get_boolean(desktop_info,
- G_KEY_FILE_DESKTOP_KEY_TERMINAL);
/*
* GAppInfo retrieves the icon data but doesn't provide a way to retrieve
* the corresponding file name, so we have to look it up by ourselves.
*/
- if (icon && dirlist)
- icon_path = applaunchd_utils_get_icon(dirlist, g_icon_to_string(icon));
+ if (app_id && dirlist)
+ icon_path = applaunchd_utils_get_icon(dirlist, app_id);
- app_info = app_info_new(app_id, g_app_info_get_name(appinfo),
+ app_info = app_info_new(app_id,
+ name,
icon_path ? icon_path : "",
- g_app_info_get_commandline(appinfo),
- systemd_activated, graphical);
+ service);
- g_debug("Adding application '%s'", app_id);
+ g_debug("Adding application '%s' with display name '%s'", app_id, name);
self->apps_list = g_list_append(self->apps_list, app_info);
}
+ g_list_free_full(units, g_free);
}
/*
@@ -186,9 +155,6 @@ static GVariant *app_launcher_get_list_variant(AppLauncher *self, gboolean graph
GVariantBuilder app_builder;
AppInfo *app_info = g_list_nth_data(self->apps_list, i);
- if (graphical && !app_info_get_graphical(app_info))
- continue;
-
g_variant_builder_init (&app_builder, G_VARIANT_TYPE("(sss)"));
/* Create application entry */
@@ -229,10 +195,7 @@ static gboolean app_launcher_start_app(AppLauncher *self, AppInfo *app_info)
app_launcher_started_cb(self, app_id, NULL);
return TRUE;
case APP_STATUS_INACTIVE:
- if (app_info_get_systemd_activated(app_info))
- systemd_manager_start_app(self->systemd_manager, app_info);
- else
- process_manager_start_app(self->process_manager, app_info);
+ systemd_manager_start_app(self->systemd_manager, app_info);
return TRUE;
default:
g_critical("Unknown status %d for application '%s'", app_status, app_id);
@@ -257,7 +220,7 @@ static gboolean app_launcher_handle_start(applaunchdAppLaunch *object,
AppLauncher *self = APPLAUNCHD_APP_LAUNCHER(object);
g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(self), FALSE);
- /* Seach the apps list for the given app-id */
+ /* Search the apps list for the given app-id */
app = app_launcher_get_app_info(self, app_id);
if (!app) {
g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR,
@@ -343,7 +306,6 @@ static void app_launcher_dispose(GObject *object)
if (self->apps_list)
g_list_free_full(g_steal_pointer(&self->apps_list), g_object_unref);
- g_clear_object(&self->process_manager);
g_clear_object(&self->systemd_manager);
G_OBJECT_CLASS(app_launcher_parent_class)->dispose(object);
@@ -375,17 +337,6 @@ static void app_launcher_init (AppLauncher *self)
g_source_attach(g_sd_event_create_source(self->event, self->bus), g_main_loop_get_context(main_loop));
/*
- * Create the process manager and connect to its signals
- * so we get notified on app startup/termination
- */
- self->process_manager = g_object_new(APPLAUNCHD_TYPE_PROCESS_MANAGER,
- NULL);
- g_signal_connect_swapped(self->process_manager, "started",
- G_CALLBACK(app_launcher_started_cb), self);
- g_signal_connect_swapped(self->process_manager, "terminated",
- G_CALLBACK(app_launcher_terminated_cb), self);
-
- /*
* Create the systemd manager and connect to its signals
* so we get notified on app startup/termination
*/
diff --git a/src/meson.build b/src/meson.build
index 761ad9b..f44aef3 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,7 +28,6 @@ executable (
'main.c',
'app_info.c', 'app_info.h',
'app_launcher.c', 'app_launcher.h',
- 'process_manager.c', 'process_manager.h',
'systemd_manager.c', 'systemd_manager.h',
'utils.c', 'utils.h',
],
diff --git a/src/process_manager.c b/src/process_manager.c
deleted file mode 100644
index ad3ea33..0000000
--- a/src/process_manager.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2021 Collabora Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "app_launcher.h"
-#include "process_manager.h"
-
-struct _ProcessManager {
- GObject parent_instance;
-
- GList *process_data;
-};
-
-G_DEFINE_TYPE(ProcessManager, process_manager, G_TYPE_OBJECT);
-
-enum {
- STARTED,
- TERMINATED,
- N_SIGNALS
-};
-static guint signals[N_SIGNALS];
-
-/*
- * Application info structure, used for storing relevant data
- * in the `running_apps` list
- */
-struct process_runtime_data {
- guint watcher;
- GPid pid;
- const gchar *app_id;
-};
-
-/*
- * Initialization & cleanup functions
- */
-
-static void process_manager_dispose(GObject *object)
-{
- ProcessManager *self = APPLAUNCHD_PROCESS_MANAGER(object);
-
- g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self));
-
- if (self->process_data)
- g_list_free_full(g_steal_pointer(&self->process_data), g_free);
-
- G_OBJECT_CLASS(process_manager_parent_class)->dispose(object);
-}
-
-static void process_manager_finalize(GObject *object)
-{
- G_OBJECT_CLASS(process_manager_parent_class)->finalize(object);
-}
-
-static void process_manager_class_init(ProcessManagerClass *klass)
-{
- GObjectClass *object_class = (GObjectClass *)klass;
-
- object_class->dispose = process_manager_dispose;
- object_class->finalize = process_manager_finalize;
-
- signals[STARTED] = g_signal_new("started", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, 0 ,
- NULL, NULL, NULL, G_TYPE_NONE,
- 1, G_TYPE_STRING);
-
- signals[TERMINATED] = g_signal_new("terminated", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, 0 ,
- NULL, NULL, NULL, G_TYPE_NONE,
- 1, G_TYPE_STRING);
-}
-
-static void process_manager_init(ProcessManager *self)
-{
-}
-
-/*
- * Internal functions
- */
-
-static const gchar *get_app_id_for_pid(ProcessManager *self, GPid pid)
-{
- g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), NULL);
-
- AppLauncher *app_launcher = app_launcher_get_default();
- guint len = g_list_length(self->process_data);
-
- for (guint i = 0; i < len; i++) {
- struct process_runtime_data *runtime_data =
- g_list_nth_data(self->process_data, i);
-
- if (runtime_data->pid == pid)
- return runtime_data->app_id;
- }
-
- return NULL;
-}
-
-/*
- * Internal callbacks
- */
-
-/*
- * This function is called when a watched process terminated, so we can:
- * - cleanup this application's data (and reap the process so it
- * doesn't become a zombie)
- * - notify listeners that the process terminated
- */
-static void process_manager_app_terminated_cb(GPid pid,
- gint wait_status,
- gpointer data)
-{
- ProcessManager *self = data;
- AppLauncher *app_launcher = app_launcher_get_default();
- struct process_runtime_data *runtime_data;
- const gchar *app_id;
- AppInfo *app_info;
-
- g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self));
-
- app_id = get_app_id_for_pid(self, pid);
- if (!app_id) {
- g_warning("Unable to retrieve app id for pid %d", pid);
- return;
- }
-
- app_info = app_launcher_get_app_info(app_launcher, app_id);
- if (!app_info) {
- g_warning("Unable to find running app with pid %d", pid);
- return;
- }
-
- if (g_spawn_check_exit_status(wait_status, NULL))
- g_debug("Application '%s' terminated with exit code %i",
- app_id, WEXITSTATUS(wait_status));
- else
- g_warning("Application '%s' crashed", app_id);
-
- g_spawn_close_pid(pid);
-
- runtime_data = app_info_get_runtime_data(app_info);
- g_source_remove(runtime_data->watcher);
-
- app_info_set_status(app_info, APP_STATUS_INACTIVE);
- app_info_set_runtime_data(app_info, NULL);
-
- self->process_data = g_list_remove(self->process_data, runtime_data);
- g_free(runtime_data);
-
- g_signal_emit(self, signals[TERMINATED], 0, app_id);
-}
-
-/*
- * Public functions
- */
-
-ProcessManager *process_manager_new(void)
-{
- return g_object_new(APPLAUNCHD_TYPE_PROCESS_MANAGER, NULL);
-}
-
-/*
- * Start an application by executing the provided command line.
- */
-gboolean process_manager_start_app(ProcessManager *self,
- AppInfo *app_info)
-{
- g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), FALSE);
- g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(app_info), FALSE);
-
- gboolean success;
- g_autofree GStrv args = NULL;
- const gchar *app_id = app_info_get_app_id(app_info);
- const gchar *command = app_info_get_command(app_info);
- struct process_runtime_data *runtime_data;
-
- runtime_data = g_new0(struct process_runtime_data, 1);
- if (!runtime_data) {
- g_critical("Unable to allocate runtime data structure for '%s'",
- app_id);
- return FALSE;
- }
-
- runtime_data->app_id = app_id;
-
- args = g_strsplit(command, " ", -1);
- success = g_spawn_async(NULL, args, NULL,
- G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
- NULL, NULL, &runtime_data->pid, NULL);
- if (!success) {
- g_critical("Unable to start application '%s'", app_id);
- g_free(runtime_data);
- return FALSE;
- }
-
- /*
- * Add a watcher for the child PID in order to get notified when it dies
- */
- runtime_data->watcher = g_child_watch_add(runtime_data->pid,
- process_manager_app_terminated_cb,
- self);
- self->process_data = g_list_append(self->process_data, runtime_data);
- app_info_set_runtime_data(app_info, runtime_data);
- app_info_set_status(app_info, APP_STATUS_RUNNING);
-
- g_signal_emit(self, signals[STARTED], 0, app_id);
-
- return TRUE;
-}
diff --git a/src/process_manager.h b/src/process_manager.h
deleted file mode 100644
index 1979cba..0000000
--- a/src/process_manager.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2021 Collabora Ltd
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PROCESSMANAGER_H
-#define PROCESSMANAGER_H
-
-#include <glib-object.h>
-
-#include "app_info.h"
-
-G_BEGIN_DECLS
-
-#define APPLAUNCHD_TYPE_PROCESS_MANAGER process_manager_get_type()
-
-G_DECLARE_FINAL_TYPE(ProcessManager, process_manager,
- APPLAUNCHD, PROCESS_MANAGER, GObject);
-
-ProcessManager *process_manager_new(void);
-
-gboolean process_manager_start_app(ProcessManager *self,
- AppInfo *app_info);
-
-G_END_DECLS
-
-#endif
diff --git a/src/systemd_manager.c b/src/systemd_manager.c
index 3fae7fc..63e7094 100644
--- a/src/systemd_manager.c
+++ b/src/systemd_manager.c
@@ -147,7 +147,119 @@ SystemdManager *systemd_manager_new(void)
}
/*
- * Start an application by executing the provided command line.
+ * Get app unit list
+ */
+gboolean systemd_manager_enumerate_app_units(SystemdManager *self,
+ AppLauncher *launcher,
+ GList **units)
+{
+ g_return_val_if_fail(APPLAUNCHD_IS_SYSTEMD_MANAGER(self), FALSE);
+ g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(launcher), FALSE);
+ g_return_val_if_fail(units != NULL, FALSE);
+
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus_message *m = NULL;
+ const char *path;
+ int r;
+
+ r = sd_bus_call_method(
+ app_launcher_get_bus(launcher), /* bus */
+ "org.freedesktop.systemd1", /* service to contact */
+ "/org/freedesktop/systemd1", /* object path */
+ "org.freedesktop.systemd1.Manager", /* interface name */
+ "ListUnitFilesByPatterns", /* method name */
+ &error, /* object to return error in */
+ &m, /* return message on success */
+ "asas", /* input signature */
+ 0, /* first argument (empty array) */
+ 1, /* second argument (array) */
+ "agl-app*@*.service"
+ );
+ if (r < 0) {
+ g_critical("Failed to issue method call: %s", error.message);
+ goto finish;
+ }
+
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0) {
+ g_critical("Failed to parse response message: %s", strerror(-r));
+ goto finish;
+ }
+
+ const char *unit;
+ const char *state;
+ while ((r = sd_bus_message_read(m, "(ss)", &unit, &state)) > 0) {
+ if (!g_str_has_suffix(unit, "@.service"))
+ *units = g_list_prepend(*units, g_strdup(unit));
+ }
+ if (r < 0) {
+ g_critical("Failed to parse unit entry: %s", strerror(-r));
+ goto finish;
+ }
+
+ // Exit array
+ r = sd_bus_message_exit_container(m);
+ if (r < 0) {
+ g_critical("Failed to parse response message 5: %s", strerror(-r));
+ goto finish;
+ }
+
+ return TRUE;
+
+finish:
+ sd_bus_error_free(&error);
+ sd_bus_message_unref(m);
+ g_list_free_full(*units, g_free);
+ *units = NULL;
+ return FALSE;
+}
+
+/*
+ * Get app unit description property
+ */
+gboolean systemd_manager_get_app_description(SystemdManager *self,
+ AppLauncher *launcher,
+ gchar *service,
+ gchar **description)
+{
+ g_return_val_if_fail(APPLAUNCHD_IS_SYSTEMD_MANAGER(self), FALSE);
+ g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(launcher), FALSE);
+ g_return_val_if_fail(service != NULL, FALSE);
+ g_return_val_if_fail(description != NULL, FALSE);
+
+ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus_message *m = NULL;
+ gchar *esc_service = NULL;
+ const char *path;
+ int r;
+
+ /* Get the escaped unit name in the systemd hierarchy */
+ sd_bus_path_encode("/org/freedesktop/systemd1/unit", service, &esc_service);
+
+ r = sd_bus_get_property_string(
+ app_launcher_get_bus(launcher), /* bus */
+ "org.freedesktop.systemd1", /* service to contact */
+ esc_service, /* object path */
+ "org.freedesktop.systemd1.Unit",
+ "Description",
+ &error,
+ description);
+ if (r < 0) {
+ g_critical("Failed to issue method call: %s", error.message);
+ goto finish;
+ }
+ return TRUE;
+
+finish:
+ sd_bus_error_free(&error);
+ sd_bus_message_unref(m);
+ g_free(*description);
+ *description = NULL;
+ return FALSE;
+}
+
+/*
+ * Start an application by executing its service.
*/
gboolean systemd_manager_start_app(SystemdManager *self,
AppInfo *app_info)
@@ -156,10 +268,9 @@ gboolean systemd_manager_start_app(SystemdManager *self,
g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(app_info), FALSE);
AppLauncher *launcher = app_launcher_get_default();
- g_autofree gchar *service = NULL;
gchar *esc_service = NULL;
const gchar *app_id = app_info_get_app_id(app_info);
- const gchar *command = app_info_get_command(app_info);
+ const gchar *service = app_info_get_service(app_info);
struct systemd_runtime_data *runtime_data;
sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -173,10 +284,9 @@ gboolean systemd_manager_start_app(SystemdManager *self,
return FALSE;
}
- /* Compose the corresponding service name */
- service = g_strdup_printf("agl-app@%s.service", command);
/* Get the escaped unit name in the systemd hierarchy */
sd_bus_path_encode("/org/freedesktop/systemd1/unit", service, &esc_service);
+ g_debug("Trying to start service '%s', unit path '%s'", service, esc_service);
runtime_data->mgr = self;
runtime_data->esc_service = esc_service;
diff --git a/src/systemd_manager.h b/src/systemd_manager.h
index a8a4ac7..b866948 100644
--- a/src/systemd_manager.h
+++ b/src/systemd_manager.h
@@ -20,6 +20,7 @@
#include <glib-object.h>
#include "app_info.h"
+#include "app_launcher.h"
G_BEGIN_DECLS
@@ -30,6 +31,15 @@ G_DECLARE_FINAL_TYPE(SystemdManager, systemd_manager,
SystemdManager *systemd_manager_new(void);
+gboolean systemd_manager_enumerate_app_units(SystemdManager *self,
+ AppLauncher *launcher,
+ GList **units);
+
+gboolean systemd_manager_get_app_description(SystemdManager *self,
+ AppLauncher *launcher,
+ gchar *service,
+ gchar **description);
+
gboolean systemd_manager_start_app(SystemdManager *self,
AppInfo *app_info);