• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 Advanced Driver Information Technology Joint Venture GmbH
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <limits.h>
27 
28 #include <weston.h>
29 #include <libweston-desktop.h>
30 #include "config-parser.h"
31 #include <ivi-layout-export.h>
32 
33 #ifndef INVALID_ID
34 #define INVALID_ID 0xFFFFFFFF
35 #endif
36 
37 struct db_elem
38 {
39     struct wl_list link;
40     uint32_t surface_id;
41     char *cfg_app_id;
42     char *cfg_title;
43     struct ivi_layout_surface *layout_surface;
44 };
45 
46 struct ivi_id_agent
47 {
48     uint32_t default_behavior_set;
49     uint32_t default_surface_id;
50     uint32_t default_surface_id_max;
51     struct wl_list app_list;
52     struct weston_compositor *compositor;
53     const struct ivi_layout_interface *interface;
54 
55     struct wl_listener desktop_surface_configured;
56     struct wl_listener destroy_listener;
57     struct wl_listener surface_removed;
58 };
59 
60 static int32_t
check_config_parameter(char * cfg_val,char * val)61 check_config_parameter(char *cfg_val, char *val)
62 {
63     if (cfg_val == NULL)
64         return IVI_SUCCEEDED;
65     else if (val == NULL || strcmp(cfg_val, val) != 0)
66         return IVI_FAILED;
67 
68     return IVI_SUCCEEDED;
69 }
70 
71 static int32_t
get_id_from_config(struct ivi_id_agent * ida,struct ivi_layout_surface * layout_surface)72 get_id_from_config(struct ivi_id_agent *ida, struct ivi_layout_surface
73         *layout_surface) {
74     struct db_elem *db_elem;
75     char *temp_app_id = NULL;
76     char *temp_title = NULL;
77     int ret = IVI_FAILED;
78 
79     struct weston_surface *weston_surface =
80             ida->interface->surface_get_weston_surface(layout_surface);
81 
82     /* Get app id and title */
83     struct weston_desktop_surface *wds = weston_surface_get_desktop_surface(
84             weston_surface);
85 
86     if (weston_desktop_surface_get_app_id(wds) != NULL)
87         temp_app_id = strdup(weston_desktop_surface_get_app_id(wds));
88 
89     if (weston_desktop_surface_get_title(wds) != NULL)
90         temp_title = strdup(weston_desktop_surface_get_title(wds));
91 
92     /*
93      * Check for every config parameter to be fulfilled. This part must be
94      * extended, if additional attributes are desired to be checked.
95      */
96     wl_list_for_each(db_elem, &ida->app_list, link)
97     {
98         if (check_config_parameter(db_elem->cfg_app_id, temp_app_id) == 0) {
99             if (check_config_parameter(db_elem->cfg_title, temp_title) == 0) {
100                 /* Found configuration for application. */
101                 int res = ida->interface->surface_set_id(layout_surface,
102                         db_elem->surface_id);
103                 if (res)
104                     continue;
105 
106                 db_elem->layout_surface = layout_surface;
107                 ret = IVI_SUCCEEDED;
108 
109                 break;
110             }
111         }
112     }
113 
114     free(temp_app_id);
115     free(temp_title);
116 
117     return ret;
118 }
119 
120 /*
121  * This function generates the id of a surface in regard to the desired
122  * parameters. For implementation of different behavior in id generation please
123  * adjust this function.
124  * In this implementation the app_id and/or title of the application is used for
125  * identification. It is also possible to use the pid, uid or gid for example.
126  */
127 static int32_t
get_id(struct ivi_id_agent * ida,struct ivi_layout_surface * layout_surface)128 get_id(struct ivi_id_agent *ida, struct ivi_layout_surface *layout_surface)
129 {
130     if (get_id_from_config(ida, layout_surface) == IVI_SUCCEEDED)
131         return IVI_SUCCEEDED;
132 
133     /* No default layer available */
134     if (ida->default_behavior_set == 0) {
135         weston_log("ivi-id-agent: Could not find configuration for application\n");
136         goto ivi_failed;
137 
138     /* Default behavior for unknown applications */
139     } else if (ida->default_surface_id < ida->default_surface_id_max) {
140         weston_log("ivi-id-agent: No configuration for application adding to "
141                 "default layer\n");
142 
143         /*
144          * Check if ivi-shell application already created an application with
145          * desired surface_id
146          */
147         struct ivi_layout_surface *temp_layout_surf =
148                 ida->interface->get_surface_from_id(
149                         ida->default_surface_id);
150         if ((temp_layout_surf != NULL) && (temp_layout_surf != layout_surface)) {
151             weston_log("ivi-id-agent: surface_id already used by an ivi-shell "
152                                 "application\n");
153             goto ivi_failed;
154         }
155 
156         ida->interface->surface_set_id(layout_surface,
157                                               ida->default_surface_id);
158         ida->default_surface_id++;
159 
160     } else {
161         weston_log("ivi-id-agent: Interval for default surface_id generation "
162                 "exceeded\n");
163         goto ivi_failed;
164     }
165 
166     return IVI_SUCCEEDED;
167 
168 ivi_failed:
169     return IVI_FAILED;
170 }
171 
172 static void
desktop_surface_event_configure(struct wl_listener * listener,void * data)173 desktop_surface_event_configure(struct wl_listener *listener,
174         void *data)
175 {
176     struct ivi_id_agent *ida = wl_container_of(listener, ida,
177             desktop_surface_configured);
178 
179     struct ivi_layout_surface *layout_surface =
180             (struct ivi_layout_surface *) data;
181 
182     if (get_id(ida, layout_surface) == IVI_FAILED)
183         weston_log("ivi-id-agent: Could not create surface_id for application\n");
184 }
185 
186 static void
surface_event_remove(struct wl_listener * listener,void * data)187 surface_event_remove(struct wl_listener *listener, void *data) {
188     struct ivi_id_agent *ida = wl_container_of(listener, ida,
189                 surface_removed);
190     struct ivi_layout_surface *layout_surface =
191                 (struct ivi_layout_surface *) data;
192     struct db_elem *db_elem = NULL;
193 
194     wl_list_for_each(db_elem, &ida->app_list, link)
195     {
196         if(db_elem->layout_surface == layout_surface) {
197             db_elem->layout_surface = NULL;
198             break;
199         }
200     }
201 }
202 
203 static int32_t deinit(struct ivi_id_agent *ida);
204 
205 static void
id_agent_module_deinit(struct wl_listener * listener,void * data)206 id_agent_module_deinit(struct wl_listener *listener, void *data) {
207     (void)data;
208     struct ivi_id_agent *ida = wl_container_of(listener, ida, destroy_listener);
209 
210     deinit(ida);
211 }
212 
213 static int32_t
check_config(struct db_elem * curr_db_elem,struct ivi_id_agent * ida)214 check_config(struct db_elem *curr_db_elem, struct ivi_id_agent *ida)
215 {
216     struct db_elem *db_elem;
217 
218     if (ida->default_surface_id <= curr_db_elem->surface_id
219             && curr_db_elem->surface_id <= ida->default_surface_id_max) {
220         weston_log("ivi-id-agent: surface_id: %d in default id interval "
221                 "[%d, %d] (CONFIG ERROR)\n", curr_db_elem->surface_id,
222                 ida->default_surface_id, ida->default_surface_id_max);
223         goto ivi_failed;
224     }
225 
226     wl_list_for_each(db_elem, &ida->app_list, link)
227     {
228         if(curr_db_elem == db_elem)
229             continue;
230 
231         if (db_elem->surface_id == curr_db_elem->surface_id) {
232             weston_log("ivi-id-agent: Duplicate surface_id: %d (CONFIG ERROR)\n",
233                     curr_db_elem->surface_id);
234             goto ivi_failed;
235         }
236     }
237 
238     return IVI_SUCCEEDED;
239 
240 ivi_failed:
241     return IVI_FAILED;
242 }
243 
244 static int32_t
read_config(struct ivi_id_agent * ida)245 read_config(struct ivi_id_agent *ida)
246 {
247     struct weston_config *config = NULL;
248     struct weston_config_section *section = NULL;
249     const char *name = NULL;
250 
251     config = wet_get_config(ida->compositor);
252     if (!config)
253         goto ivi_failed;
254 
255     section = weston_config_get_section(config, "desktop-app-default", NULL,
256             NULL);
257 
258     if (section) {
259         weston_log("ivi-id-agent: Default behavior for unknown applications is "
260                 "set\n");
261         ida->default_behavior_set = 1;
262 
263         weston_config_section_get_uint(section, "default-surface-id",
264                 &ida->default_surface_id, INVALID_ID);
265         weston_config_section_get_uint(section, "default-surface-id-max",
266                 &ida->default_surface_id_max, INVALID_ID);
267 
268         if (ida->default_surface_id == INVALID_ID ||
269                 ida->default_surface_id_max == INVALID_ID) {
270             weston_log("ivi-id-agent: Missing configuration for default "
271                     "behavior\n");
272             ida->default_behavior_set = 0;
273         }
274     } else {
275         ida->default_behavior_set = 0;
276     }
277 
278     section = NULL;
279     while (weston_config_next_section(config, &section, &name)) {
280         struct db_elem *db_elem = NULL;
281 
282         if (strcmp(name, "desktop-app") != 0)
283             continue;
284 
285         db_elem = calloc(1, sizeof *db_elem);
286         if (db_elem == NULL) {
287             weston_log("ivi-id-agent: No memory to allocate\n");
288             goto ivi_failed;
289         }
290 
291         wl_list_insert(&ida->app_list, &db_elem->link);
292 
293         weston_config_section_get_uint(section, "surface-id",
294                          &db_elem->surface_id, INVALID_ID);
295 
296         if (db_elem->surface_id == INVALID_ID) {
297             weston_log("ivi-id-agent: surface-id is not set in configuration\n");
298             goto ivi_failed;
299         }
300 
301         weston_config_section_get_string(section, "app-id",
302                          &db_elem->cfg_app_id, NULL);
303         weston_config_section_get_string(section, "app-title",
304                          &db_elem->cfg_title, NULL);
305 
306         if (db_elem->cfg_app_id == NULL && db_elem->cfg_title == NULL) {
307             weston_log("ivi-id-agent: Every parameter is NULL in app "
308                     "configuration\n");
309             goto ivi_failed;
310         }
311 
312         if (check_config(db_elem, ida) == IVI_FAILED) {
313             weston_log("ivi-id-agent: No valid config found, deinit...\n");
314             goto ivi_failed;
315         }
316     }
317 
318     if(ida->default_behavior_set == 0 && wl_list_empty(&ida->app_list)) {
319         weston_log("ivi-id-agent: No valid config found, deinit...\n");
320         goto ivi_failed;
321     }
322 
323     return IVI_SUCCEEDED;
324 
325 ivi_failed:
326     return IVI_FAILED;
327 }
328 
329 WL_EXPORT int32_t
id_agent_module_init(struct weston_compositor * compositor,const struct ivi_layout_interface * interface)330 id_agent_module_init(struct weston_compositor *compositor,
331         const struct ivi_layout_interface *interface)
332 {
333     struct ivi_id_agent *ida = NULL;
334 
335     ida = calloc(1, sizeof *ida);
336     if (ida == NULL) {
337         weston_log("failed to allocate ivi_id_agent\n");
338         goto ivi_failed;
339     }
340 
341     ida->compositor = compositor;
342     ida->interface = interface;
343     ida->desktop_surface_configured.notify = desktop_surface_event_configure;
344     ida->destroy_listener.notify = id_agent_module_deinit;
345     ida->surface_removed.notify = surface_event_remove;
346 
347     wl_signal_add(&compositor->destroy_signal, &ida->destroy_listener);
348     ida->interface->add_listener_configure_desktop_surface(
349             &ida->desktop_surface_configured);
350     interface->add_listener_remove_surface(&ida->surface_removed);
351 
352     wl_list_init(&ida->app_list);
353     if(read_config(ida) != 0) {
354         weston_log("ivi-id-agent: Read config failed\n");
355         deinit(ida);
356         goto ivi_failed;
357     }
358 
359     return IVI_SUCCEEDED;
360 
361 ivi_failed:
362     return IVI_FAILED;
363 }
364 
365 static int32_t
deinit(struct ivi_id_agent * ida)366 deinit(struct ivi_id_agent *ida)
367 {
368     struct db_elem *db_elem;
369     wl_list_for_each(db_elem, &ida->app_list, link) {
370         free(db_elem->cfg_app_id);
371         free(db_elem->cfg_title);
372         free(db_elem);
373     }
374 
375     wl_list_remove(&ida->desktop_surface_configured.link);
376     wl_list_remove(&ida->destroy_listener.link);
377     wl_list_remove(&ida->surface_removed.link);
378     free(ida);
379 
380     return IVI_SUCCEEDED;
381 }
382