From 008b408656ae9e68c826bbacb0323ff0056418d7 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Wed, 22 Feb 2023 12:53:46 +0200 Subject: 01_Application_Framework: Moved D-bus actvation to its own page The 02_Application_Startup pages actually contains quite a lot of D-Bus specific bits so move it to its own page, rather than adding items about the gRPC one. The gRPC part are inlined into the current page though. Bug-AGL: SPEC-4700 Signed-off-by: Marius Vlad Change-Id: I4808cc1773f071f2455e24b5417a8b30337cbb8a Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/documentation/+/28524 Reviewed-by: Jan-Simon Moeller Tested-by: Jan-Simon Moeller --- .../02_Application_Startup.md | 234 +++++++++------------ .../02_Application_Startup_Dbus.md | 190 +++++++++++++++++ 2 files changed, 287 insertions(+), 137 deletions(-) create mode 100644 docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup_Dbus.md diff --git a/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup.md b/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup.md index 2786bf6..6eeae02 100644 --- a/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup.md +++ b/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup.md @@ -4,181 +4,141 @@ title: Application Startup # Introduction -At system runtime, it may be necessary for applications to start other applications -on demand. Such actions can be executed in reaction to a user request, or they may -be needed to perform a specific task. +At system runtime, it may be necessary for applications to start other +applications on demand. Such actions can be executed in reaction to a user +request, or they may be needed to perform a specific task. In order to do so, running applications and services need an established way of -discovering installed applications and executing those. The -[Desktop Entry specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) -defines how applications can be discovered by using `.desktop` files, but there's no -simple reference implementation for this function. +discovering installed applications and executing those. -In order to provide a language-independent interface for applications and service to -use, AGL includes `applaunchd`, a user service part of the default session. - -*Note: as mentioned [previously](../01_Introduction/), services are managed using `systemd` -and are therefore not in the scope of this document.* +In order to provide a language-independent interface for applications and +service to use, AGL includes `applaunchd`, a system service. # Application launcher service -The purpose of `applaunchd` is to enumerate applications available on the system and -provide a way for other applications to query this list and start those on demand. -It is also able to notify clients of the startup and termination of applications it -manages. +The purpose of `applaunchd` is to enumerate applications available on the +system and provide a way for other applications to query this list and start +those on demand. It is also able to notify clients of the startup and +termination of applications it manages. -To that effect, `applaunchd` provides a D-Bus interface other applications can use -in order to execute those actions. +To that effect, `applaunchd` provides a gRPC interface which other applications +can use in order to execute those actions. -*Note: `applaunchd` will only send notifications for applications it started; it isn't -aware of applications started by other means (`systemd`, direct executable call...), -and therefore can't send notifications for those.* +*Note: `applaunchd` will only send notifications for applications it started; +it isn't aware of applications started by other means (`systemd`, direct +executable call...), and therefore can't send notifications for those.* ## Application discovery -On startup, `applaunchd` inspects all `.desktop` files present under the `applications/` -subfolder of any element of the `XDG_DATA_DIRS` environment variable, ignoring all entries -containing either the `NoDisplay=true` or `Hidden=true` lines. - -It then looks for the following keys: -- `Terminal` -- `DBusActivatable` - -If the desktop entry file contains the `Terminal` key set to `true`, then the application -is marked as a non-graphical one. As such, it won't be included in the applications list -if the client requests only graphical applications. - -If `DBusActivatable` is set to `true`, then the application is marked as D-Bus activated. -Additionally, `applaunchd` will search for a corresponding D-Bus service file in case this -line is missing. This is a workaround allowing D-Bus activated applications providing -an incomplete desktop entry file (i.e missing the `DBusActivatable` key) to be -identified as such. - -### Requirements for D-Bus activation - -`applaunchd` will always start D-Bus activatable applications using D-Bus activation -instead of executing the command line stated in the desktop entry file. - -This is handled by calling the `Activate` method of the -[org.freedesktop.Application](https://specifications.freedesktop.org/desktop-entry-spec/1.1/ar01s07.html) -interface with an empty argument. - -As a consequence, all D-Bus activatable applications **must** implement this D-Bus -interface. +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. ## Application identifiers -Each application is identified by a unique Application ID. Although this ID can be -any valid string, it is highly recommended to use the "reverse DNS" convention in order -to avoid potential name collisions and ease D-Bus integration. +Each application is identified by a unique Application ID. Although this ID can +be any valid string, it is highly recommended to use the "reverse DNS" +convention in order to avoid potential name collisions. -The application ID is set in the desktop entry file itself for -[graphical applications](/04_Developer_Guides/03_Creating_a_New_Application/#graphical-applications): -it is the value of the `StartupWMClass` field, which must be identical to the `app-id` -advertised through the Wayland XDG toplevel protocol. In case this field is missing -(as is usually the case for non-graphical application), the application ID will be the -desktop entry file name, stripped from its `.desktop` extension. +## gRPC interface -## D-Bus interface +The interface provides methods for the following actions: -The `applaunchd` D-Bus interface is named `org.automotivelinux.AppLaunch`. The object -path for `applaunchd` is `/org/automotivelinux/AppLaunch`. The interface provides methods -for the following actions: -- retrieve the list of available applications; the client can choose to retrieve all - available applications, or only those suitable for a graphical environment +- retrieve the list of available applications - request an application to be started +- subscribe to status events -Moreover, signals are available for clients to be notified when an application has -successfully started or its execution terminated. - -### Applications list - -The `listApplications` method allows clients to retrieve the list of available applications. -It takes one boolean argument named `graphical`: -- if set to `true`, only applications suitable for graphical environments are returned -- otherwise, the list contains all applications - -This method returns an array of variants (type `av`), each element being a structure made up -of 3 strings (type `(sss)`): -- the application ID -- the application's displayed name -- the full path to the application icon file (or an empty string if no icon was specified in - the application's desktop entry file) - -### Application startup request - -Applications can be started by using the `start` method, passing the corresponding application -ID as the only argument. This method doesn't return any data. - -If the application is already running, `applaunchd` won't start another instance, but instead -emit a `started` signal to notify clients the application is ready. +Moreover, with the gRPC the client subscribes to a status signal to be notified +when an application has successfully started or its execution terminated. -### Status notifications +The gRPC protobuf file provides a Request and Response arguments to RPC methods +even though in some cases these might be empty in order to allow forward +compatibility in case additional fields are required. +It is a good standard practice to follow up with these recommendation when +developing a new protobuf specification. -The `org.automotivelinux.AppLaunch` interface provides 2 signals clients can connect to: -- `started` indicates an application has started - - for D-Bus activated applications, it is emitted upon successful completion of the - call to the `Activate` method of the `org.freedesktop.Application` interface - - for other applications, this signal is emitted as soon as the child process has been - successfully created -- `terminated` is emitted when an application quits +### Applications list -Both signals have an additional argument named `appid`, containing the ID of the application -affected by the event. +The `ListApplications` method allows clients to retrieve the list of available +applications. -As mentioned above, the `started` signal is also emitted if `applaunchd` receives a request to -start an already running application. This can be useful, for example, when switching between -graphical applications: -- the application switcher doesn't need to track the state of each application; instead, it can - simply send a `start` request to `applaunchd` every time the user requests to switch to another - application -- the desktop environment then receives the `started` signal, indicating it should activate the - window with the corresponding `app-id` +The `ListRequest` is an empty message, while `ListResponse` contains the following: -## Testing +``` +message AppInfo { + string id = 1; + string name = 2; + string icon_path = 3; +} + +message ListResponse { + repeated AppInfo apps = 1; +} +``` -`applaunchd` can be manually tested using the `gdbus` command-line tool: +### Application startup request -1. Query the application list (graphical applications only): +Applications can be started by using the `StartApplication` method, passing the +`StartRequest` message, defined as: ``` -$ gdbus call --session --dest "org.automotivelinux.AppLaunch" \ - --object-path "/org/automotivelinux/AppLaunch" \ - --method "org.automotivelinux.AppLaunch.listApplications" \ - true +message StartRequest { + string id = 1; +} ``` -This command will output something similar to what follows: +In reply, the following `StartResponse` will be returned: ``` -([<('navigation', 'Navigation', '/usr/share/icons/hicolor/scalable/navigation.svg')>, - <('settings', 'Settings', '/usr/share/icons/hicolor/scalable/settings.svg')>, - <('dashboard', 'Dashboard', '/usr/share/icons/hicolor/scalable/dashboard.svg')>, - <('hvac', 'HVAC', '/usr/share/icons/hicolor/scalable/hvac.svg')>, - <('org.freedesktop.weston.wayland-terminal', 'Weston Terminal', '/usr/share/icons/Adwaita/scalable/apps/utilities-terminal-symbolic.svg')>],) +message StartResponse { + bool status = 1; + string message = 2; +} ``` -2. Request startup of the `org.freedesktop.weston.wayland-terminal` application: +The "message" string of `StartResponse` message will contain an error message +in case we couldn't start the application for whatever reason, or if the "id" +isn't a known application ID. The "status" string would be boolean set to +boolean `TRUE` otherwise. -``` -$ gdbus call --session --dest "org.automotivelinux.AppLaunch" \ - --object-path "/org/automotivelinux/AppLaunch" \ - --method "org.automotivelinux.AppLaunch.start" \ - "org.freedesktop.weston.wayland-terminal" -``` +If the application is already running, `applaunchd` won't start another +instance, but instead reply with a `AppStatus` message setting the `status` +string to "started". -3. Monitor signals emitted by `applaunchd`: +### Status notifications -``` -$ gdbus monitor --session --dest "org.automotivelinux.AppLaunch" -``` +The gRPC interface provides clients with a subscription model to receive +status events. Client should subscribe to `GetStatusEvents` method to receive +them. -This results in the following output when starting, then exiting, the -`org.freedesktop.weston.wayland-terminal` application: +The `StatusRequest` is empty, while the `StatusResponse` is defined as +following: ``` -Monitoring signals from all objects owned by org.automotivelinux.AppLaunch -The name org.automotivelinux.AppLaunch is owned by :1.4 -/org/automotivelinux/AppLaunch: org.automotivelinux.AppLaunch.started ('org.freedesktop.weston.wayland-terminal',) -/org/automotivelinux/AppLaunch: org.automotivelinux.AppLaunch.terminated ('org.freedesktop.weston.wayland-terminal',) +message AppStatus { + string id = 1; + string status = 2; +} + +message LauncherStatus { +} + +message StatusResponse { + oneof status { + AppStatus app = 1; + LauncherStatus launcher = 2; + } +} ``` + +As mentioned above, the `status` string is set to "started" and is also emitted +if `applaunchd` receives a request to start an already running application. +This can be useful, for example, when switching between graphical applications: + +- the application switcher doesn't need to track the state of each application; + instead, it can simply send a `StartApplication` request to `applaunchd` + every time the user requests to switch to another application +- the shell client then receives the `StatusResponse` with the message `status` + string set to "started" indicating it that it should activate the window with + the corresponding `id` string diff --git a/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup_Dbus.md b/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup_Dbus.md new file mode 100644 index 0000000..523ffc9 --- /dev/null +++ b/docs/04_Developer_Guides/01_Application_Framework/02_Application_Startup_Dbus.md @@ -0,0 +1,190 @@ +--- +title: Application Startup with D-Bus +--- + +*Note: The that the D-Bus interface is in deprecation phase and for the time +being only available for application & services that still rely on them. Once +we migrate everything to gRPC, we will remove D-Bus IPC support. Please see +[Application Startup with gRPC](../02_Application_Startup/) for the latest +information* + +# Introduction + +At system runtime, it may be necessary for applications to start other applications +on demand. Such actions can be executed in reaction to a user request, or they may +be needed to perform a specific task. + +In order to do so, running applications and services need an established way of +discovering installed applications and executing those. The +[Desktop Entry specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html) +defines how applications can be discovered by using `.desktop` files, but there's no +simple reference implementation for this function. + +In order to provide a language-independent interface for applications and service to +use, AGL includes `applaunchd`, a user service part of the default session. + +*Note: as mentioned [previously](../01_Introduction/), services are managed using `systemd` +and are therefore not in the scope of this document.* + +# Application launcher service + +The purpose of `applaunchd` is to enumerate applications available on the system and +provide a way for other applications to query this list and start those on demand. +It is also able to notify clients of the startup and termination of applications it +manages. + +To that effect, `applaunchd` provides a D-Bus interface other applications can use +in order to execute those actions. + +*Note: `applaunchd` will only send notifications for applications it started; it isn't +aware of applications started by other means (`systemd`, direct executable call...), +and therefore can't send notifications for those.* + +## Application discovery + +On startup, `applaunchd` inspects all `.desktop` files present under the `applications/` +subfolder of any element of the `XDG_DATA_DIRS` environment variable, ignoring all entries +containing either the `NoDisplay=true` or `Hidden=true` lines. + +It then looks for the following keys: +- `Terminal` +- `DBusActivatable` + +If the desktop entry file contains the `Terminal` key set to `true`, then the application +is marked as a non-graphical one. As such, it won't be included in the applications list +if the client requests only graphical applications. + +If `DBusActivatable` is set to `true`, then the application is marked as D-Bus activated. +Additionally, `applaunchd` will search for a corresponding D-Bus service file in case this +line is missing. This is a workaround allowing D-Bus activated applications providing +an incomplete desktop entry file (i.e missing the `DBusActivatable` key) to be +identified as such. + +### Requirements for D-Bus activation + +`applaunchd` will always start D-Bus activatable applications using D-Bus activation +instead of executing the command line stated in the desktop entry file. + +This is handled by calling the `Activate` method of the +[org.freedesktop.Application](https://specifications.freedesktop.org/desktop-entry-spec/1.1/ar01s07.html) +interface with an empty argument. + +As a consequence, all D-Bus activatable applications **must** implement this D-Bus +interface. + +## Application identifiers + +Each application is identified by a unique Application ID. Although this ID can be +any valid string, it is highly recommended to use the "reverse DNS" convention in order +to avoid potential name collisions and ease D-Bus integration. + +The application ID is set in the desktop entry file itself for +[graphical applications](/04_Developer_Guides/03_Creating_a_New_Application/#graphical-applications): +it is the value of the `StartupWMClass` field, which must be identical to the `app-id` +advertised through the Wayland XDG toplevel protocol. In case this field is missing +(as is usually the case for non-graphical application), the application ID will be the +desktop entry file name, stripped from its `.desktop` extension. + +## D-Bus interface + +The `applaunchd` D-Bus interface is named `org.automotivelinux.AppLaunch`. The object +path for `applaunchd` is `/org/automotivelinux/AppLaunch`. The interface provides methods +for the following actions: +- retrieve the list of available applications; the client can choose to retrieve all + available applications, or only those suitable for a graphical environment +- request an application to be started + +Moreover, signals are available for clients to be notified when an application has +successfully started or its execution terminated. + +### Applications list + +The `listApplications` method allows clients to retrieve the list of available applications. +It takes one boolean argument named `graphical`: +- if set to `true`, only applications suitable for graphical environments are returned +- otherwise, the list contains all applications + +This method returns an array of variants (type `av`), each element being a structure made up +of 3 strings (type `(sss)`): +- the application ID +- the application's displayed name +- the full path to the application icon file (or an empty string if no icon was specified in + the application's desktop entry file) + +### Application startup request + +Applications can be started by using the `start` method, passing the corresponding application +ID as the only argument. This method doesn't return any data. + +If the application is already running, `applaunchd` won't start another instance, but instead +emit a `started` signal to notify clients the application is ready. + +### Status notifications + +The `org.automotivelinux.AppLaunch` interface provides 2 signals clients can connect to: +- `started` indicates an application has started + - for D-Bus activated applications, it is emitted upon successful completion of the + call to the `Activate` method of the `org.freedesktop.Application` interface + - for other applications, this signal is emitted as soon as the child process has been + successfully created +- `terminated` is emitted when an application quits + +Both signals have an additional argument named `appid`, containing the ID of the application +affected by the event. + +As mentioned above, the `started` signal is also emitted if `applaunchd` receives a request to +start an already running application. This can be useful, for example, when switching between +graphical applications: +- the application switcher doesn't need to track the state of each application; instead, it can + simply send a `start` request to `applaunchd` every time the user requests to switch to another + application +- the desktop environment then receives the `started` signal, indicating it should activate the + window with the corresponding `app-id` + +## Testing + +`applaunchd` can be manually tested using the `gdbus` command-line tool: + +1. Query the application list (graphical applications only): + +``` +$ gdbus call --session --dest "org.automotivelinux.AppLaunch" \ + --object-path "/org/automotivelinux/AppLaunch" \ + --method "org.automotivelinux.AppLaunch.listApplications" \ + true +``` + +This command will output something similar to what follows: + +``` +([<('navigation', 'Navigation', '/usr/share/icons/hicolor/scalable/navigation.svg')>, + <('settings', 'Settings', '/usr/share/icons/hicolor/scalable/settings.svg')>, + <('dashboard', 'Dashboard', '/usr/share/icons/hicolor/scalable/dashboard.svg')>, + <('hvac', 'HVAC', '/usr/share/icons/hicolor/scalable/hvac.svg')>, + <('org.freedesktop.weston.wayland-terminal', 'Weston Terminal', '/usr/share/icons/Adwaita/scalable/apps/utilities-terminal-symbolic.svg')>],) +``` + +2. Request startup of the `org.freedesktop.weston.wayland-terminal` application: + +``` +$ gdbus call --session --dest "org.automotivelinux.AppLaunch" \ + --object-path "/org/automotivelinux/AppLaunch" \ + --method "org.automotivelinux.AppLaunch.start" \ + "org.freedesktop.weston.wayland-terminal" +``` + +3. Monitor signals emitted by `applaunchd`: + +``` +$ gdbus monitor --session --dest "org.automotivelinux.AppLaunch" +``` + +This results in the following output when starting, then exiting, the +`org.freedesktop.weston.wayland-terminal` application: + +``` +Monitoring signals from all objects owned by org.automotivelinux.AppLaunch +The name org.automotivelinux.AppLaunch is owned by :1.4 +/org/automotivelinux/AppLaunch: org.automotivelinux.AppLaunch.started ('org.freedesktop.weston.wayland-terminal',) +/org/automotivelinux/AppLaunch: org.automotivelinux.AppLaunch.terminated ('org.freedesktop.weston.wayland-terminal',) +``` -- cgit 1.2.3-korg