From 04ae05c69a1ee2934b139b179d15ba112ff18ab6 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 17 Oct 2023 16:48:46 -0400 Subject: [PATCH] Update application framework documentation Changes: - Moved "Creating a New Service" page back over to "Developer Guides" since it is not application framework specific. - Removed obsolete applaunchd D-Bus configuration documentation now that the functionality has been completely removed as of Pike. - Updated the application framework introduction discussion around protocols to document preference for gRPC over D-Bus for AGL projects. - Updated "Creating a New Application" documentation to document the requirements for having applications usable with applaunchd, as well as using the application templates, with BitBake recipe examples. - Added "Application Sandboxing" section that documents the existing example configurations and discusses other potential configuration options for systemd. Bug-AGL: SPEC-4928 Signed-off-by: Scott Murray Change-Id: I6e0c0afcf571d9214df5300d2082b15fa3bb2a27 Reviewed-on: https://gerrit.automotivelinux.org/gerrit/c/AGL/documentation/+/29284 Reviewed-by: Jan-Simon Moeller Tested-by: Jan-Simon Moeller --- .../03_Creating_a_New_Service.md | 11 +- .../01_AGL_components.md | 2 +- .../Application_Framework/01_Introduction.md | 174 +++++++-------- .../02_Application_Startup.md | 24 +-- .../02_Application_Startup_Dbus.md | 190 ----------------- .../03_Creating_a_New_Application.md | 233 +++++++++++++++++++++ .../04_Application_Sandboxing.md | 92 ++++++++ .../04_Creating_a_New_Application_Dbus.md | 139 ------------ 8 files changed, 416 insertions(+), 449 deletions(-) rename docs/{06_Component_Documentation/Application_Framework => 04_Developer_Guides}/03_Creating_a_New_Service.md (91%) delete mode 100644 docs/06_Component_Documentation/Application_Framework/02_Application_Startup_Dbus.md create mode 100644 docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Application.md create mode 100644 docs/06_Component_Documentation/Application_Framework/04_Application_Sandboxing.md delete mode 100644 docs/06_Component_Documentation/Application_Framework/04_Creating_a_New_Application_Dbus.md diff --git a/docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Service.md b/docs/04_Developer_Guides/03_Creating_a_New_Service.md similarity index 91% rename from docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Service.md rename to docs/04_Developer_Guides/03_Creating_a_New_Service.md index 69bde48..858715d 100644 --- a/docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Service.md +++ b/docs/04_Developer_Guides/03_Creating_a_New_Service.md @@ -22,8 +22,8 @@ location, determined by the service type (system or user): - `/usr/lib/systemd/user/` for user services -Below is an example of a simple user service, running in a graphical session and -therefore requiring a compositor to be already running before the service starts: +Below is an example of a simple system service that requires the compositor to be +already running before the service starts: ``` [Unit] @@ -34,15 +34,8 @@ After=agl-compositor.service Type=simple ExecStart=/usr/bin/homescreen Restart=on-failure - -[Install] -WantedBy=agl-session.target ``` -The `WantedBy=agl-session.target` indicates the service is part of the default AGL -user session, as mentioned in the [Application Framework](01_Introduction.md#user-session-management) -documentation. - The `Restart=on-failure` directive ensures the service will be automatically restarted by `systemd` in case it crashes. diff --git a/docs/06_Component_Documentation/01_AGL_components.md b/docs/06_Component_Documentation/01_AGL_components.md index b36580d..754c0ed 100644 --- a/docs/06_Component_Documentation/01_AGL_components.md +++ b/docs/06_Component_Documentation/01_AGL_components.md @@ -22,6 +22,6 @@ title: AGL Components - [Rule based arbitrator](04_Rule_Based_Arbitrator.md) -### Lifecycle management +### Application Lifecycle and Services - [Application Framework](Application_Framework/01_Introduction.md) diff --git a/docs/06_Component_Documentation/Application_Framework/01_Introduction.md b/docs/06_Component_Documentation/Application_Framework/01_Introduction.md index 1deaec4..41759da 100644 --- a/docs/06_Component_Documentation/Application_Framework/01_Introduction.md +++ b/docs/06_Component_Documentation/Application_Framework/01_Introduction.md @@ -4,75 +4,79 @@ title: Introduction # Foreword -The AGL Application Framework is nothing new. However, the implementation used -up until the `lamprey` release has been retired starting with the `marlin` -release and replaced by a redesigned Application Framework one. However, this -new implementation isn't a 1:1 replacement, and as such it doesn't provide all -of the features of the previous Application Framework. Some of those will be -added back over time, others have been discarded in favor of more modern and/or -widely-used alternatives. - -With the `needlefish` release, further changes have been added, including a -[gRPC IPC](https://grpc.io/about), alongside a deprecated D-Bus one, as well as -using as using systemd units as opposed on using -[Desktop Entry specification](https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/) -to list applications, and relies entirely on systemd to start application, -rather than spawning them directly. - -Once all platforms transitioned to gRPC, the D-Bus functionality will be -removed entirely, mentioning it in only in documentation for history purposes. +AGL has worked at providing the components of an application framework for many +years. However, the implementation used up until the `lamprey` release was retired +starting with the `marlin` release, and replaced with a redesigned one. +However, this new implementation does not aim to be a 1:1 replacement, and as such +it does not provide all of the features of the previous framework. Some of those +will be added back over time, while others have been discarded in favor of more +modern and/or widely-used alternatives. + +With the `needlefish` release, further evolution of the replacement framework included: + +- Using [gRPC IPC](https://grpc.io/about) for the application launcher API. + The interim D-Bus based API was deprecated at this time, and removed in the + `pike` release. +- Using only systemd unit metadata in the application launcher instead of using + [Desktop Entry specification](https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/) + to list applications, and relying entirely on systemd for the application + lifecycle, rather than spawning them directly. # Introduction -As a provider of an integrated solution to build up on, AGL needs to define a -reliable and well-specified method for managing the deployment and integration -of applications and services, as well as the way they can interact with the -rest of the system. +With a goal of being the provider of an integrated solution to build up on, it +is useful for AGL to define a reliable and well-specified method for managing +the deployment and integration of applications and services, as well as the way +they can interact with the rest of the system. This is achieved by providing a common set of rules and components, known as -the Application Framework. By ensuring conformity to those rules, application -developers can have a good understanding of the requirements for creating and -packaging applications targeting AGL-based systems. Likewise, system developers -and integrators have a clear path for including such applications in AGL-based -products. +the application framework. By documenting those rules, application developers can +have a good understanding of the requirements for creating and packaging applications +targeting AGL-based systems that leverage the upstream application framework components. +Likewise, system developers and integrators have a clear path for including such +applications in AGL-based products. + +The application framework's scope extends to the following areas: -The Application Framework's scope extends to the following areas: - system services integration and lifecycle management -- user session management, including user-level applications and services - lifecycle management +- user-level application lifecycle management - inter-process communication In order to be as simple as possible and avoid any unneeded custom -implementation, the Application Framework relies mainly on third-party -technologies and/or software components, most of those being maintained under -the [freedesktop.org](https://www.freedesktop.org) umbrella. Those include: - +implementation, the application framework relies mainly on third-party +technologies and/or software components. They include: - [systemd](https://www.freedesktop.org/wiki/Software/systemd/): system services and user session services management - -- [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/): inter-process - communication, with `needlefish' release deprecated phase. - - [gRPC](https://grpc.io/about): inter-process communication, new recommmended system-wide IPC, which should be used instead of D-Bus. - -- [Desktop Entry specification](https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/): - application enumeration and startup, now in deprecated phase, systemd being - the one would list out applications and handling start-up. +Note that while there are many open source software projects in the desktop Linux +space using [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) for inter-process +communication, AGL has decided to avoid using it for new development projects for the +following reasons: + +- It has proven challenging in the past to manage dependencies between and the + start-up of system and per-user D-Bus services in AGL. +- Managing the security of D-Bus APIs involves the use of PolicyKit, which is + somewhat heavyweight and not widely understood. As well, providing D-Bus + access to applications running inside containers or other sandbox schemes can + be significantly more complicated than e.g. using gRPC with authorization token + access control. +- D-Bus is not widely used in application development ecosystems outside of desktop + Linux. This matters when engaging with application developers in newer ecosystems + such as web applications or Flutter. AGL also provides reference implementations whenever possible and relevant, located in the [meta-agl](../../04_Developer_Guides/02_AGL_Layers/02_meta_agl.md) -layer under `meta-app-framework`. At the moment, the Application Framework -contains 2 such components: +layer under `meta-app-framework`. At the moment, the application framework +contains two such components: - `agl-session`: `systemd` unit files for user sessions management - - `applaunchd`: application launcher service -# Services management +# Service Management Both system and user services are managed by `systemd`, which provides a number of important features, such as dependency management or service monitoring: @@ -86,62 +90,38 @@ downtime. and other security-related options. It is also well integrated with D-Bus and can be used for a more fine-grained -control over D-Bus activated services: by delegating the actual service startup -to `systemd`, developers can take advantage of some of its advanced features, -allowing for improved reliability and security. +control over D-Bus activated services. By delegating the actual service start-up +to `systemd`, developers can take advantage of its advanced features, allowing +for improved reliability and security. Each service should be represented by a `systemd` unit file installed to the appropriate location. More details can be obtained from the [Creating a New -Service](03_Creating_a_New_Service.md) document. +Service](../../04_Developer_Guides/03_Creating_a_New_Service.md) document. -# User session management +# User Session Management Similarly, user sessions and the services they rely on are also managed by -`systemd`. - -AGL provides 2 `systemd` units: - - -1\. `agl-session@.service` is a template system service for managing user -sessions; it takes a username or UID as a parameter, creating a session for the -desired user. Instanciating this service can be achieved by enabling -`agl-session@USER.service`, for example by executing the following command on a -running system: +`systemd`. Prior to the `pike` release, AGL used a user session for the +`agl-driver` user for the running of user facing applications, including the +compositor. This has been replaced with using system units that use the +`User` directive. The reason for this is two-fold: -``` -$ systemctl enable agl-session@USER.service -``` +- Several useful systemd sandboxing features are unavailable to user session + units, or would require the use of unprivileged namespace mounting. The + latter is not necessarily available in vendor BSP kernels, and the security + characteristics of it are still a matter of some debate. +- Encoding dependencies between user session and system units is sometimes + not straightforward or impossible. -By default, AGL enables this service as `agl-session@agl-driver.service`, -running as user `agl-driver`. +# Inter-process Communication -*Note: while you can create sessions for as many users as needed, only one -instance of `agl-session@.service` is allowed per user.* - - -2\. `agl-session.target` is a user target for managing user services and their -dependencies. It is started by `agl-session@.service`. - -By default, `agl-compositor` is part of this target. It is therefore -automatically started for user `agl-driver`. - -Any other service needed as part of the user session should similarly depend on -this target by appending the following lines to their unit file: - -``` -[Install] -WantedBy=agl-session.target -``` - -# Inter-process communication - -In order to provide a "standard", language-independent IPC mechanism and avoid +In order to provide a language-independent, "standard", IPC mechanism and avoid the need for maintaining custom bindings for each programming language to be -used on top of AGL, the Application Framework used to promote the use of +used on top of AGL, the application framework previously promoted the use of [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) as the preferred way for applications to interact with services. Starting with `needlefish` release, -we instead switched to using [gRPC](https://grpc.io) for our system-wide IPC, -with D-Bus being kept to provide functionality to services and application +this has changed to recommending [gRPC](https://grpc.io) for our system-wide IPC, +with D-Bus being kept to provide functionality to services and applications which haven't transitioned yet to using gRPC. Most services already included in AGL provide one or several D-Bus interfaces, @@ -160,27 +140,25 @@ others: - [GeoClue](https://gitlab.freedesktop.org/geoclue/geoclue/-/wikis/home): geolocation -Similarly, we're in the phase of expanding various services to expose a +Similarly, ongoing work involves expanding various services to expose a gRPC interface. -# Application launcher service +# Application Launcher Service The Application Framework used to follow the guidelines of the [Desktop Entry specification](https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/) -for application enumeration and startup, but with the `needlefish` release +for application enumeration and start-up, but with the `needlefish` release instead it relies on systemd to provide that functionality, indirectly, by using the `applaunchd` application. As no simple reference implementation exists for this part of the specification, AGL provides an application launcher service named `applaunchd`. This service is part of the default user session, and as such is automatically -started on session startup. It can therefore be considered always available. +started on session start-up. It can therefore be considered always available. `applaunchd` enumerates applications installed on the system and provides a -D-bus (deprecated)/gRPC interface for services and applications to: +gRPC interface for services and applications to: + - query the list of available applications -- request the startup and/or activation of a specific application +- request the start-up of a specific application - be notified when applications are started or terminated - -`applaunchd` with the D-Bus interface is described with more details in -[the following document](02_Application_Startup_Dbus.md). diff --git a/docs/06_Component_Documentation/Application_Framework/02_Application_Startup.md b/docs/06_Component_Documentation/Application_Framework/02_Application_Startup.md index 3cd7ca0..8594426 100644 --- a/docs/06_Component_Documentation/Application_Framework/02_Application_Startup.md +++ b/docs/06_Component_Documentation/Application_Framework/02_Application_Startup.md @@ -1,5 +1,5 @@ --- -title: Application Startup +title: Application Launcher --- # Introduction @@ -14,11 +14,11 @@ discovering installed applications and executing those. In order to provide a language-independent interface for applications and service to use, AGL includes `applaunchd`, a system service. -# Application launcher 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 +those on demand. It is also able to notify clients of the start-up and termination of applications it manages. To that effect, `applaunchd` provides a gRPC interface which other applications @@ -28,20 +28,20 @@ can use in order to execute those actions. it isn't aware of applications started by other means (`systemd`, direct executable call...), and therefore can't send notifications for those.* -## Application discovery +## Application Discovery 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 +## 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. -## gRPC interface +## gRPC Interface The interface provides methods for the following actions: @@ -58,7 +58,7 @@ 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. -### Applications list +### Application Enumeration The `ListApplications` method allows clients to retrieve the list of available applications. @@ -77,7 +77,7 @@ message ListResponse { } ``` -### Application startup request +### Application Start-up Applications can be started by using the `StartApplication` method, passing the `StartRequest` message, defined as: @@ -106,7 +106,7 @@ 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". -### Status notifications +### Status Notifications The gRPC interface provides clients with a subscription model to receive status events. Client should subscribe to `GetStatusEvents` method to receive @@ -146,7 +146,7 @@ This can be useful, for example, when switching between graphical applications: set to "terminated" to denote that the application has been terminated, forcibly or not -## A deeper look at start-up, activation and application switching +## Start-up, Activation, and Application Switching Application start-up, activation and application switching are sometimes conflated into a single operation but underneath some of these are distinct @@ -177,7 +177,7 @@ by the desktop run-time/shell client. as this synchronization part between `applaunchd` has not been implemented. The plan is to migrate all of remaining run-times to using this approach.* -### Start-up & activation +### Start-up and Activation This means that we require some sort of interaction between `StartApplication` method and the events sent by the AGL compositor in order to correctly handle @@ -231,7 +231,7 @@ application start-up: ![Application_start](images/start_and_activation.png) -### Application switching +### Application Switching With the compositor providing application status events, it might seem that the `applaunchd`'s, `GetStatusEvents` might be redundant, but in fact it is being diff --git a/docs/06_Component_Documentation/Application_Framework/02_Application_Startup_Dbus.md b/docs/06_Component_Documentation/Application_Framework/02_Application_Startup_Dbus.md deleted file mode 100644 index f951e0e..0000000 --- a/docs/06_Component_Documentation/Application_Framework/02_Application_Startup_Dbus.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -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.md) 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.md), 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_Creating_a_New_Application_Dbus.md#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',) -``` diff --git a/docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Application.md b/docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Application.md new file mode 100644 index 0000000..aa528b1 --- /dev/null +++ b/docs/06_Component_Documentation/Application_Framework/03_Creating_a_New_Application.md @@ -0,0 +1,233 @@ +--- +title: Creating a New Application +--- + +In the context of AGL, "applications" are usually considered to be standalone +user facing infotainment applications that can be started in addition to the +default "homescreen" or similar user interface that will always be present. +Such applications can be enumerated and executed with `applaunchd`, the AGL +[application launcher service](02_Application_Startup.md). The following +sections walk through what is required to add an application to an AGL image +that uses applaunchd, as well as discussion of developer conveniences that +AGL provides to simplify doing so in the Yocto build environment. + +# Basic Requirements + +As described in the [applaunchd documentation](02_Application_Startup.md#application-discovery), +applications need to have a systemd system unit with a name matching the pattern `agl-app*@*.service`. +The portion of the unit name between `@` and `.service` is used as the application identifier +(see [Application Identifiers](02_Application_Startup.md#application-identifiers)). +The use of `@` in the unit filename indicates the use of a template unit, which `applaunchd` +assumes will be used for applications (see below). Template unit files are discussed in the +systemd unit file [man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description). + +The requirements on the unit file contents are: + +- The `Description` field is used as the desired display name of the application. + It is recommended that this be kept short, ideally to one or two words, in order to + avoid issues when applications are listed in a UI. +- While not a hard requirement, ideally the `User` field is used to specify running + the application as a non-privileged user. In the AGL demonstration images, the + `agl-driver` user is used. + +Blah blah icon... + +# Graphical Application Requirements + +In addition, graphical applications need to comply with a few more requirements: + +1. Each application must set a Wayland application ID appropriately as soon as its main window +is created. +2. The `app-id` used must match the application identifier specified in the systemd unit filename. + +Doing so will ensure other software can associate the actual `app-id` to the proper application. + +*Note: application ID's are set using the [XDG toplevel](https://wayland-book.com/xdg-shell-basics/xdg-toplevel.html) +Wayland interface.* + +# Application Templates + +To provide a working example of application template units, AGL includes templates +for generic, Flutter, and web applications as part of the `applaunchd` recipe in the +`meta-app-framework` layer in [meta-agl](../../04_Developer_Guides/02_AGL_Layers/02_meta_agl.md). +If applaunchd is built into an image using the recipe, these templates will be available +for applications to use for their systemd units by creating a symlink that includes the +application identifier. To simplify this, a `BitBake` class named `agl-app` is included in +the layer for use in application recipes. The different templates and their configuration +will be discussed further in the following sections. + +## Generic Graphical Application Template + +The `agl-app@.service` template unit is intended for simple standalone graphical applications. +It makes the following assumptions by default: + +- The application executable name is the same as the application identifier, and the + executable is available via the default `PATH`. +- The application `Description` will be the application identifier. +- The application should run as the `agl-driver` user. + +If using the `agl-app` class in a recipe (with `inherit agl-app`), these defaults can be +changed via the variables: + +- `AGL_APP_NAME`: overrides the value of the `Description` field to set the desired + application display name. +- `AGL_APP_EXEC`: overrides the application executable name. + +If set, these variables will trigger the generation of one or more systemd `drop-in` +override files by the logic in the `agl-app` class. The use of `drop-in` configuration +files is discussed in the systemd unit file [man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description). + +Additionally, the variable `AGL_APP_ID` may be used to override the assumption that the +application identifier is the same as the recipe name. If specified, its value should be +the desired application identifier. + +The following is a partial example BitBake recipe using the template for an application named +`foo`: + +```text + +SUMMARY = "foo application" +HOMEPAGE = "https://git.automotivelinux.org/apps/foo" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984" + +PV = "1.0+git${SRCREV}" + +SRC_URI = "git://git.automotivelinux.org/apps/foo;protocol=https;branch=master" +SRCREV = "abcdef012" + +S = "${WORKDIR}/git" + +inherit agl-app + +AGL_APP_NAME = "Foo" + + +``` + +Note that this assumes that the recipe is named `foo_git.bb`. If the recipe was instead named +something like `foo-app_git.bb`, then `AGL_APP_ID = "foo"` would need to be added. + +## Flutter Application Template + +The `agl-app-flutter@.service` template unit is intended for Flutter graphical applications +that use the `flutter-auto` Flutter embedder. It makes the following assumptions by default: + +- The Flutter application name in `pubspec.yaml` is the same as the application identifier, +and the application bundle will be installed under the directory: + ```text + /usr/share/flutter/// + ``` + For example: + ```text + /usr/share/flutter/flutter_hvac/3.3.7/release + ``` + +- The application `Description` will be the application identifier. +- The application should run as the `agl-driver` user. + +If using the `agl-app` class in a recipe (with `inherit agl-app`), the use of the Flutter +template can be triggered by setting the variable `AGL_APP_TEMPLATE` to `agl-app-flutter`, +and the above defaults can be changed via the variables: + +- `AGL_APP_NAME`: overrides the value of the `Description` field to set the desired + application display name. + +If set, this will trigger the generation of a systemd `drop-in` override file by the logic +in the `agl-app` class. The use of `drop-in` configuration files is discussed in the systemd +unit file [man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description). + +Additionally, the variable `AGL_APP_ID` may be used to override the assumption that the +application identifier is the same as the recipe name. If specified, its value should be +the desired application identifier and Flutter application / bundle name. + +The following is an example BitBake recipe using the template for a Flutter application +named `foo`: + +```text + +SUMMARY = "Flutter foo application" +HOMEPAGE = "https://git.automotivelinux.org/apps/flutter-foo" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://License.md;md5=f712ede8d4f845976061925d1416fc40" + +PV = "1.0+git${SRCREV}" + +SRC_URI = "git://git.automotivelinux.org/apps/flutter-foo;protocol=https;branch=master" +SRCREV = "abcdef012" + +S = "${WORKDIR}/git" + +inherit flutter-app agl-app + +PUBSPEC_APPNAME = "foo" +FLUTTER_APPLICATION_INSTALL_PREFIX = "/flutter" + +AGL_APP_TEMPLATE = "agl-app-flutter" +AGL_APP_NAME = "Foo" +``` + +Note that this assumes that the recipe is named `foo_git.bb`, and that the application name +in the Flutter `pubspec.yaml` is `foo`. If the recipe was instead named something like +`flutter-foo_git.bb`, then `AGL_APP_ID = "foo"` would need to be added. + +## Web Application Template + +The `agl-app-web@.service` template unit is intended for web applications run using the +Web Application Manager (WAM) service. It makes the following assumptions by default: + +- The web application bundle directory name is the same as the application identifier, and the + bundle will be installed in the directory hierarchy: + ``` + /usr/lib/wam_apps/ + ``` + For example: + ``` + /usr/lib/wam_apps/webapps-hvac + ``` +- The application `Description` will be the application identifier. +- The application should run as the `agl-driver` user. + +If using the `agl-app` class in a recipe (with `inherit agl-app`), the use of the Flutter +template can be triggered by setting the variable `AGL_APP_TEMPLATE` to `agl-app-web`, +and the above defaults can be changed via the variables: + +- `AGL_APP_NAME`: overrides the value of the `Description` field to set the desired + application display name. +- `AGL_APP_WAM_DIR`: overrides the application bundle directory name. This can be used if + the application bundle name does not match the application identifier. + +If set, these variables will trigger the generation of one or more systemd `drop-in` +override files by the logic in the `agl-app` class. The use of `drop-in` configuration +files is discussed in the systemd unit file [man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description). + +Additionally, the variable `AGL_APP_ID` may be used to override the assumption that the +application identifier is the same as the recipe name. + +The following is a partial example BitBake recipe using the template for a web application +named `foo`: + +```text + +SUMMARY = "Web foo application" +HOMEPAGE = "https://git.automotivelinux.org/apps/web-foo" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" + +PV = "1.0+git${SRCREV}" + +SRC_URI = "git://git.automotivelinux.org/apps/web-foo;protocol=https;branch=master" +SRCREV = "abcdef012" + +S = "${WORKDIR}/git" + +inherit agl-app + +AGL_APP_TEMPLATE = "agl-app-web" +AGL_APP_NAME = "Foo" + + +``` + +Note that this assumes that the recipe is named `foo_git.bb`. If the recipe was instead named +something like `foo-web_git.bb`, then `AGL_APP_ID = "foo"` would need to be added. diff --git a/docs/06_Component_Documentation/Application_Framework/04_Application_Sandboxing.md b/docs/06_Component_Documentation/Application_Framework/04_Application_Sandboxing.md new file mode 100644 index 0000000..356c0eb --- /dev/null +++ b/docs/06_Component_Documentation/Application_Framework/04_Application_Sandboxing.md @@ -0,0 +1,92 @@ +--- +title: Application Sandboxing +--- + +One of the motivations for leveraging systemd in `applaunchd` was to allow the use of its +advanced features such as [sandboxing](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Sandboxing), +[system call filtering](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#System%20Call%20Filtering), +[process limits](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Process%20Properties), and +Linux CGroup configuration via [slices](https://www.freedesktop.org/software/systemd/man/systemd.slice.html). +The scope of potential systemd configurations involving these options is broad, and so far AGL has focused on providing +some simple examples of basic sandboxing integrated with the application templates discussed above. + +## Network Access Restriction + +The systemd [`PrivateNetwork`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=) +service configuration option can be used to disable network access for the service started by a unit file. +The `applaunchd` packaging installs a systemd drop-in configuration file named `no-network.conf` in the +directory `/usr/lib/systemd/system/sandboxing` that may be used to disable network access with `PrivateNetwork`. +To use it, `no-network.conf` should be symlinked in an appropriate unit file drop-in override directory per +systemd naming expectations (see systemd unit file +[man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description)). +The following is a `BitBake` recipe snippet showing installation of the drop-in for an application named `foo` +that is using the generic application template: + +```text +... + +inherit agl-app + +AGL_APP_NAME = "Foo" + +do_install() { + # Enable systemd sandboxing override as a demonstration + install -d ${D}${systemd_system_unitdir}/agl-app@${AGL_APP_ID}.service.d/ + ln -sf ${systemd_system_unitdir}/sandboxing/no-network.conf ${D}${systemd_system_unitdir}/agl-app@${AGL_APP_ID}.service.d/ +} + +FILES:${PN} = " \ + ${sysconfdir}/systemd/system/agl-app@${AGL_APP_ID}.service.d \ +" + +... +``` + +This results in a `/usr/lib/systemd/system/agl-app@foo.service.d/no-network.conf` symlink being created +in the `foo` packaging, disabling network access when `foo` is started by `applaunchd` or directly via +`systemctl` on the command line. + +## Private Temporary Directories + +The systemd [`PrivateTmp`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=) +service configuration option can be used to prevent access to the host `/tmp` and `/var/tmp` directories +for the service started by a unit file. The service will instead have private temporary mounts of these +directories in a new mount namespace. The `applaunchd` packaging installs a systemd drop-in configuration +file named `private-tmp.conf` in the directory `/usr/lib/systemd/system/sandboxing` that may be used to +create private temporary directory mounts with `PrivateTmp`. To use it, `private-tmp.conf` should be +symlinked in an appropriate unit file drop-in override directory per systemd naming expectations (see +systemd unit file [man page](https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Description)). +See above for an example `BitBake` recipe snippet showing installation of a drop-in file when using the +generic application template. + +## Other Sandboxing Options + +In addition to the above, some other notable systemd sandbox options worth further consideration for +applications include: + +- [PrivateDevices](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=) + This option could be used to remove access to device files in /dev for applications that do not + require them, but it is likely that `DeviceAllow` may also need to be used to enable functionality in + some applications. +- [ProtectSystem](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=) + The default and `full` modes of this option likely can be enabled with little impact to most + applications, as they should not need write access to the directories that are made read-only. + Using the `strict` option would need investigation into interactions with usage of directory + hierarchies like `/run`. +- [ProtectHome](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=) + This option seems worthwhile if the system ends up with more than one active user for running + applications, but interactions with default application caching and configuration locations + needs to be investigated. It is likely that enforcing use of locations outside of `/home` + for these would need to be settled upon and documented for application developers. For + example using the [XDG directory scheme](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) + similar to the previous AGL application framework. +- [ReadWritePaths, etc.](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths=) + These options provide a more fine-grained approach to some of the above ones, and could be + used to enable something like an application only seeing its own files and the contents of + a specific set of directories like `/etc` and `/usr/lib`. Implementing such would likely + require settling on a custom application installation hierarchy as was done in the previous + AGL application framework. + +The above list is not exhaustive, and does not include some other likely possibilities involving +system call filtering and resource limits. Future AGL releases may expand the examples provided +with `applaunchd` along these lines. diff --git a/docs/06_Component_Documentation/Application_Framework/04_Creating_a_New_Application_Dbus.md b/docs/06_Component_Documentation/Application_Framework/04_Creating_a_New_Application_Dbus.md deleted file mode 100644 index 2ee6bdf..0000000 --- a/docs/06_Component_Documentation/Application_Framework/04_Creating_a_New_Application_Dbus.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Creating a New Application with D-bus activation ---- - -*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.* - -Applications are: - -- Software designed to perform a specific task during a limited amount of time. -- Graphical interface allowing user to interact with. - -Applications are executed by `applaunchd`, the AGL -[application launcher service](02_Application_Startup_Dbus.md). - -# Basic requirements - -In order to be enumerated by `applaunchd`, applications must provide the a `.desktop` file, as -defined by the [Desktop Entry specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html). - -The desktop entry file should be installed to `/usr/share/applications` (or the `applications` -sub-directory of any entry present in the `XDG_DATA_DIRS` environment variable) and have a -meaningful name. It is considered good practice to use reverse-DNS notation for the desktop -entry file name, following the recommendations of the [D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names): -- this avoids potential name collisions with other desktop entry files -- it makes it easier to enable [D-Bus activation](#d-bus-activation) during the application - development cycle if needed -- for [graphical applications](#graphical-applications), it ensures the chosen Wayland `app-id` - will be unique - -Such a file must contain at least the following keys: -- `Type`: desktop entry type, must be set to `Application` -- `Name`: application name, as it should be displayed in menus and application launchers -- `Exec`: full path to the main executable - -Below is an example of a minimal desktop entry file: - -``` -[Desktop Entry] -Type=Application -Name=Example Application -Exec=/usr/bin/example-app -``` - -Graphical applications must also provide an `Icon` entry pointing to the application icon. -The value for this entry must either be the full path to the icon's file or, for icons part -of an existing [icon theme](https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html), -the name of an element of this theme. - -In addition, a number of optional fields can be used to change how `applaunchd` will consider the -application: -- `Version`: version of the Desktop Entry Specification the file conforms to, must be `1.5` -- `Hidden`: boolean value, if `true` the application is always ignored by `applaunchd` and - won't be listed nor executed -- `Terminal`: boolean value, if `true` the application is excluded when requesting the list of - graphical applications from `applaunchd` -- `DBusActivatable`: boolean value, must be `true` for [D-Bus activated applications](#d-bus-activation) -- `Implements`: list of D-Bus interfaces the application implements, only used for D-Bus activated - applications. - -Finally, graphical applications may also define the `StartupWMClass` key in some cases. Please -refer to the [graphical applications](#graphical-applications) section for more information. - -# D-Bus activation - -Similarly to [services](03_Creating_a_New_Service.md#d-bus-activation), applications can -also be activated through D-Bus. - -Such applications must name their `.desktop` file after the D-Bus name they register. In addition, -this file must contain the following entries: - -``` -DBusActivatable=true -Implements=IFACE1;IFACE2;... -``` - -Where `IFACEn` are the names of the D-Bus interfaces the application implements. - -In addition, they must provide a D-Bus service file named `NAME.service` and installed -to `/usr/share/dbus-1/services`. - -The contents of the D-Bus service file must be the following: - -``` -[D-BUS Service] -Name=NAME -Exec=/path/to/executable -``` - -For example, an application registering the `org.automotivelinux.Example` D-Bus name -and implementing the `org.automotivelinux.Example.Search1` and `org.automotivelinux.Example.Execute1` -interfaces would provide the following files: - -* Desktop entry (`/usr/share/applications/org.automotivelinux.Example.desktop`): - -``` -[Desktop Entry] -Type=Application -Version=1.5 -Name=Example Application -Exec=/usr/bin/example-app -Icon=example-icon -Terminal=false -DBusActivatable=true -Implements=org.automotivelinux.Example.Search1;org.automotivelinux.Example.Execute1 -``` - -* D-Bus service file (`/usr/share/dbus-1/services/org.automotivelinux.Example.service`): - -``` -[D-BUS Service] -Name=org.automotivelinux.Example -Exec=/usr/bin/example-app -``` - -*Note: in addition to their own D-Bus interface, D-Bus activated applications must also -implement the `org.freedesktop.Application` interface as defined in the -[Desktop Entry specification](https://specifications.freedesktop.org/desktop-entry-spec/1.1/ar01s07.html).* - -# Graphical applications - -In addition, graphical applications need to comply with a few more requirements: - -1\. Each application must set a Wayland application ID appropriately as soon as its main window -is created. - -2\. The `app-id` must be specified in the desktop entry file by adding the following line: - -``` -StartupWMClass=APP_ID -``` - -3\. The desktop entry file must be named `APP_ID.desktop`. - -Doing so will ensure other software can associate the actual `app-id` to the proper application. - -*Note: application ID's are set using the [XDG toplevel](https://wayland-book.com/xdg-shell-basics/xdg-toplevel.html) -Wayland interface.* -- 2.16.6