3cd7ca0929fa74cb57cb304abf29281d5c3b06b7
[AGL/documentation.git] / docs / 06_Component_Documentation / Application_Framework / 02_Application_Startup.md
1 ---
2 title: Application Startup
3 ---
4
5 # Introduction
6
7 At system runtime, it may be necessary for applications to start other
8 applications on demand. Such actions can be executed in reaction to a user
9 request, or they may be needed to perform a specific task.
10
11 In order to do so, running applications and services need an established way of
12 discovering installed applications and executing those.
13
14 In order to provide a language-independent interface for applications and
15 service to use, AGL includes `applaunchd`, a system service.
16
17 # Application launcher service
18
19 The purpose of `applaunchd` is to enumerate applications available on the
20 system and provide a way for other applications to query this list and start
21 those on demand.  It is also able to notify clients of the startup and
22 termination of applications it manages.
23
24 To that effect, `applaunchd` provides a gRPC interface which other applications
25 can use in order to execute those actions.
26
27 *Note: `applaunchd` will only send notifications for applications it started;
28 it isn't aware of applications started by other means (`systemd`, direct
29 executable call...), and therefore can't send notifications for those.*
30
31 ## Application discovery
32
33 Applications are enumerated from systemd's list of available units based on the
34 pattern `agl-app*@*.service`, and are started and controled using their systemd
35 unit.  Please note `applaunchd` allows only one instance of a given
36 application.
37
38 ## Application identifiers
39
40 Each application is identified by a unique Application ID. Although this ID can
41 be any valid string, it is highly recommended to use the "reverse DNS"
42 convention in order to avoid potential name collisions.
43
44 ## gRPC interface
45
46 The interface provides methods for the following actions:
47
48 - retrieve the list of available applications
49 - request an application to be started
50 - subscribe to status events
51
52 Moreover, with the gRPC the client subscribes to a status signal to be notified
53 when an application has successfully started or its execution terminated.
54
55 The gRPC protobuf file provides a Request and Response arguments to RPC methods
56 even though in some cases these might be empty in order to allow forward
57 compatibility in case additional fields are required.
58 It is a good standard practice to follow up with these recommendation when
59 developing a new protobuf specification.
60
61 ### Applications list
62
63 The `ListApplications` method allows clients to retrieve the list of available
64 applications. 
65
66 The `ListRequest` is an empty message, while `ListResponse` contains the following:
67
68 ```
69 message AppInfo {
70   string id = 1;
71   string name = 2;
72   string icon_path = 3;
73 }
74
75 message ListResponse {
76   repeated AppInfo apps = 1;
77 }
78 ```
79
80 ### Application startup request
81
82 Applications can be started by using the `StartApplication` method, passing the
83 `StartRequest` message, defined as:
84
85 ```
86 message StartRequest {
87   string id = 1;
88 }
89 ```
90
91 In reply, the following `StartResponse` will be returned:
92
93 ```
94 message StartResponse {
95   bool status = 1;
96   string message = 2;
97 }
98 ```
99
100 The "message" string  of `StartResponse` message will contain an error message
101 in case we couldn't start the application for whatever reason, or if the "id"
102 isn't a known application ID. The "status" string would be boolean set to
103 boolean `TRUE` otherwise.
104
105 If the application is already running, `applaunchd` won't start another
106 instance, but instead reply with a `AppStatus` message setting the `status`
107 string to "started".
108
109 ### Status notifications
110
111 The gRPC interface provides clients with a subscription model to receive
112 status events. Client should subscribe to `GetStatusEvents` method to receive
113 them.
114
115 The `StatusRequest` is empty, while the `StatusResponse` is defined as
116 following:
117
118 ```
119 message AppStatus {
120   string id = 1;
121   string status = 2;
122 }
123
124 message LauncherStatus {
125 }
126
127 message StatusResponse {
128   oneof status {
129     AppStatus app = 1;
130     LauncherStatus launcher = 2;
131   }
132 }
133 ```
134
135 As mentioned above, the `status` string is set to "started" and is also emitted
136 if `applaunchd` receives a request to start an already running application.
137 This can be useful, for example, when switching between graphical applications:
138
139 - the application switcher doesn't need to track the state of each application;
140   instead, it can simply send a `StartApplication` request to `applaunchd`
141   every time the user requests to switch to another application. Obviously, the
142   client needs to subscribe to get these events and act accordingly.
143 - the shell client then receives the `StatusResponse` with the message `status`
144   string set to "started" indicating it that it should activate the window with
145   the corresponding `id` string, or alternatively the string `status` is
146   set to "terminated" to denote that the application has been terminated,
147   forcibly or not
148
149 ## A deeper look at start-up, activation and application switching
150
151 Application start-up, activation and application switching are sometimes
152 conflated into a single operation but underneath some of these are distinct
153 steps, and a bit flaky in some circumstances.
154 The [AGL compositor](../02_agl_compositor.md) has
155 some additional events which one can use when creating an application
156 start-up & switching scheme in different run-times.
157
158 Start-up of application is handled entirely by `applaunchd` service while
159 activation -- the window which I want to display, but which has never been
160 shown, and application switching -- bring forward an application already
161 shown/displayed in the past, are operations handled entirely by the
162 AGL compositor.
163
164 The issue stems from the fact that underneath `applaunchd` can't make any
165 guarantees when the application actually started, as it calls into libsystemd
166 API to start the specific application systemd unit.
167
168 If `StartApplication` can't start the systemd unit, it returns a false
169 `status` boolean value and a error message in `StartResponse` message, but if
170 the application is indeed started we doesn't really know the *moment* when the
171 application is ready to be displayed. Additionally, the AGL compositor
172 performed the activation on its own when it detected that a new application
173 has been started, but that implicit activation can now be handled outside
174 by the desktop run-time/shell client.
175
176 *Note: Some of the run-times still rely on the compositor to perform activation
177 as this synchronization part between `applaunchd` has not been implemented. The
178 plan is to migrate all of remaining run-times to using this approach.*
179
180 ### Start-up & activation
181
182 This means that we require some sort of interaction between `StartApplication`
183 method and the events sent by the AGL compositor in order to correctly handle
184 start-up & activation of application.
185
186 There are couple of ways of achieving that, either using Wayland native calls,
187 or using the gRPC proxy interface, which underneath is using the same Wayland
188 native calls.
189
190 For the first approach, the AGL compositor has an `app_state` Wayland event
191 which contains the application ID, and an enum `app_state` that will propagate
192 the following application state events:
193
194 ```
195 <enum name="app_state" since="3">
196   <entry name="started" value="0"/>
197   <entry name="terminated" value="1"/>
198   <entry name="activated" value="2"/>
199   <entry name="deactivated" value="3"/>
200 </enum>
201 ```
202
203 The `started` event can be used in correlation with the `StartApplication`
204 method from `applaunchd` such that upon received the `started` even, it can
205 explicitly activate that particular appid in order for the compositor to
206 display it. See [AGL compositor](../02_agl_compositor.md)
207 about how activation should be handled.
208
209 *Note: These can only be received if by the client shell which binds to the
210 agl_shell interface*.
211
212 Alternatively, when using the gRPC proxy one can register to receive these
213 status events similar to the `applaunchd` events, subscribing to
214 `AppStatusState` method from the grpc-proxy helper application, which has the
215 following protobuf messages:
216
217 ```
218 message AppStateRequest {
219 }
220 message AppStateResponse {
221         int32 state = 1;
222         string app_id = 2;
223 }
224 ```
225
226 The integer state maps to the `enum app_state` from the Wayland protocol, so
227 they are a 1:1 match.
228
229 Here's the state diagram for the Qt homescreen implementation of the
230 application start-up:
231
232 ![Application_start](images/start_and_activation.png)
233
234 ### Application switching
235
236 With the compositor providing application status events, it might seem that the
237 `applaunchd`'s, `GetStatusEvents` might be redundant, but in fact it is being
238 used to perform application switching. The run-time/shell client would in fact
239 subscribe to `GetStatusEvents` and each application wanting to switch to another
240 application would basically call `StartApplication`. That would eventually reach
241 the run-time/shell-client and have a handler that would ultimately activate the
242 application ID.
243
244 ![Application_switching](images/application_switching.png)
245
246 *Note: In practice, the run-time/shell-client would subscribe to both `applaunchd`
247 and to the AGL compositor, either Wayland native events, or using the gPRC-proxy
248 helper client, although the diagrams show them partly decoupled*.