Add surface creator pid managing logic
[platform/core/appfw/aul-1.git] / src / aul_rsm.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <glib.h>
19 #include <bundle.h>
20 #include <Ecore.h>
21 #include <Ecore_Wayland.h>
22 #include <tizen-remote-surface-client-protocol.h>
23 #include <tbm_surface.h>
24 #include "aul_util.h"
25 #include "aul_app_com.h"
26 #include "aul_api.h"
27 #include "aul_rsm_provider.h"
28 #include "aul_rsm_viewer.h"
29
30 struct __remote_surface_s {
31         struct wl_surface *surface;
32         struct tizen_remote_surface_provider *rsp;
33         char *id;
34         Ecore_Wl_Window *win;
35 };
36
37 struct __surface_s {
38         char *id;
39         int pid;
40         void (*update_cb)(struct tizen_remote_surface *trs, struct wl_buffer *buffer, uint32_t time, void *data);
41         void (*missing_cb)(struct tizen_remote_surface *trs, void *data);
42         void *data;
43         struct tizen_remote_surface *surface;
44         int resource_id;
45 };
46
47 static struct tizen_remote_surface_manager *__rsm;
48 static struct wayland_tbm_client *__tbm_client;
49 static struct wl_tbm *__tbm;
50 static int __init_count;
51 static GHashTable *__viewer_tbl;
52 static aul_app_com_connection_h __conn;
53
54 int aul_rsm_init()
55 {
56         struct wl_registry *registry;
57         Ecore_Wl_Global *global;
58         Eina_Inlist *globals;
59
60         if (__init_count > 0) {
61                 return 0;
62         }
63
64         ecore_wl_init(NULL);
65
66         registry = ecore_wl_registry_get();
67         globals = ecore_wl_globals_get();
68
69         if (!registry || !globals) {
70                 _E("could not get registry(%p) or global list(%p)", registry,
71                         globals);
72                 return -1;
73         }
74
75         EINA_INLIST_FOREACH(globals, global) {
76                 if (!strcmp(global->interface, "tizen_remote_surface_manager")) {
77                         __rsm = wl_registry_bind(registry, global->id,
78                                 &tizen_remote_surface_manager_interface, 1);
79                 }
80         }
81
82         if (!__rsm) {
83                 _E("could not get remote surface manager");
84                 return -1;
85         }
86
87         __init_count++;
88         return 0;
89 }
90
91
92 int aul_rsm_fini()
93 {
94         if (__init_count > 1)
95                 return 0;
96
97         if (__tbm_client)
98                 wayland_tbm_client_deinit(__tbm_client);
99
100         if (__rsm)
101                 tizen_remote_surface_manager_destroy(__rsm);
102
103         ecore_wl_shutdown();
104
105         __init_count--;
106
107         return 0;
108 }
109
110 API int aul_rsm_provider_init()
111 {
112         aul_rsm_init();
113
114         return 0;
115 }
116
117 API int aul_rsm_provider_fini()
118 {
119         aul_rsm_fini();
120
121         return 0;
122 }
123
124 static void __rsp_resource_id_cb(void *data, struct tizen_remote_surface_provider *provider, uint32_t res_id)
125 {
126         struct __remote_surface_s *remote = (struct __remote_surface_s *)data;
127         bundle *envelope = bundle_create();
128         int pid = getpid();
129
130         if (envelope == NULL) {
131                 _E("failed to create envelope");
132                 return;
133         }
134
135         bundle_add_str(envelope, "__AUL_RSP_RESOURCE_ID__", remote->id);
136         bundle_add_byte(envelope, "__AUL_RSP_SURFACE_ID__", &res_id, sizeof(uint32_t));
137         bundle_add_byte(envelope, "__AUL_RSP_SURFACE_CREATOR_PID__", &pid, sizeof(int));
138
139         if (aul_app_com_send("tbm_surface_notify", envelope) < 0) {
140                 _E("failed to send surface notify");
141         }
142
143         bundle_free(envelope);
144 }
145
146 static void __rsp_visibility_cb(void *data, struct tizen_remote_surface_provider *provider, uint32_t visibility)
147 {
148         struct __remote_surface_s *remote = (struct __remote_surface_s *)data;
149         Ecore_Wl_Event_Window_Visibility_Change *ev;
150
151         ev = calloc(1, sizeof(Ecore_Wl_Event_Window_Visibility_Change));
152         if (!ev) {
153                 _E("out of memory");
154                 return;
155         }
156
157         ev->win = ecore_wl_window_id_get(remote->win);
158
159         if (visibility == TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE)
160                 ev->fully_obscured = 0;
161         else
162                 ev->fully_obscured = 1;
163
164         _D("visibility changed:%d", visibility);
165
166         ecore_event_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE, ev, NULL, NULL);
167 }
168
169 static const struct tizen_remote_surface_provider_listener __rsp_listener = {
170         __rsp_resource_id_cb,
171         __rsp_visibility_cb,
172 };
173
174 API int aul_rsm_provider_remote_enable(const char *id, struct wl_surface *surface)
175 {
176         struct __remote_surface_s *remote;
177
178         if (!__rsm) {
179                 _E("__rsm is not ready");
180                 return -1;
181         }
182
183         if (!surface || !id) {
184                 _E("invalid parameter");
185                 return -1;
186         }
187
188         remote = (struct __remote_surface_s *)malloc(sizeof(struct __remote_surface_s));
189         if (!remote) {
190                 _E("out of memory");
191                 return -1;
192         }
193
194         remote->surface = surface;
195         remote->win = ecore_wl_window_surface_find(surface);
196         if (!remote->win) {
197                 _E("failed to find win");
198                 return -1;
199         }
200
201         remote->rsp = tizen_remote_surface_manager_create_provider(__rsm, surface);
202         if (!remote->rsp) {
203                 _E("failed to create provider");
204                 return -1;
205         }
206
207         remote->id = strdup(id);
208         if (!remote->id) {
209                 _E("out of memory");
210                 return -1;
211         }
212
213         tizen_remote_surface_provider_add_listener(remote->rsp, &__rsp_listener, remote);
214
215         wl_display_roundtrip(ecore_wl_display_get());
216         _D("%d surface remote enable");
217
218         return 0;
219 }
220
221 static void __rs_buffer_update_cb(void *data, struct tizen_remote_surface *trs,
222         struct wl_buffer *buffer, uint32_t time)
223 {
224         struct __surface_s *surface = data;
225         if (surface)
226                 surface->update_cb(trs, buffer, time, surface->data);
227 }
228
229 static void __rs_missing_cb(void *data, struct tizen_remote_surface *trs)
230 {
231         struct __surface_s *surface = data;
232         if (surface)
233                 surface->missing_cb(trs, surface->data);
234 }
235
236 static const struct tizen_remote_surface_listener __rs_listener = {
237         __rs_buffer_update_cb,
238         __rs_missing_cb,
239 };
240
241 static void __redirect_surface(struct __surface_s *surface)
242 {
243         tizen_remote_surface_add_listener(surface->surface, &__rs_listener,
244                                                         surface);
245         tizen_remote_surface_redirect(surface->surface);
246 }
247
248 static int __tbm_handler(const char *endpoint, aul_app_com_result_e e,
249         bundle *envelope, void *user_data)
250 {
251         char *id = NULL;
252         uint32_t *res_id = NULL;
253         size_t sz;
254         int *pid = NULL;
255         struct __surface_s *surface = NULL;
256
257         bundle_get_str(envelope, "__AUL_RSP_RESOURCE_ID__", &id);
258         bundle_get_byte(envelope, "__AUL_RSP_SURFACE_ID__", (void **)&res_id, &sz);
259         bundle_get_byte(envelope, "__AUL_RSP_SURFACE_CREATOR_PID__", (void **)&pid, &sz);
260         if (id) {
261                 surface = g_hash_table_lookup(__viewer_tbl, id);
262                 if (!surface) {
263                         _E("unknown surface");
264                         return 0;
265                 }
266         }
267
268         if (pid != NULL)
269                 surface->pid = (int)*pid;
270
271         surface->resource_id = *res_id;
272         surface->surface = tizen_remote_surface_manager_create_surface(__rsm,
273                                         (uint32_t)*res_id, __tbm);
274
275         _D("__tbm_handler %d, %d, %s", *pid, *res_id, id);
276
277         if (id && res_id)
278                 __redirect_surface(surface);
279         else
280                 _E("bad tbm message received. missing arguments");
281
282         return 0;
283 }
284
285 API int aul_rsm_viewer_init()
286 {
287         aul_rsm_init();
288
289         __tbm_client = (struct wayland_tbm_client *)wayland_tbm_client_init(ecore_wl_display_get());
290         if (!__tbm_client) {
291                 _E("could not get tbm client");
292                 return -1;
293         }
294
295         __tbm = (struct wl_tbm *)wayland_tbm_client_get_wl_tbm(__tbm_client);
296         if (!__tbm) {
297                 _E("could not get tbm");
298                 return -1;
299         }
300
301         aul_app_com_create("tbm_surface_notify", NULL, __tbm_handler, NULL, &__conn);
302         if (!__conn) {
303                 _E("failed to create app com");
304                 return -1;
305         }
306
307         return 0;
308 }
309
310 API int aul_rsm_viewer_fini()
311 {
312         aul_rsm_fini();
313
314         return 0;
315 }
316
317 API int aul_rsm_viewer_set_surface_handler(const char *id, aul_rsm_handler *cbs, void *data)
318 {
319         struct __surface_s *surface;
320
321         if (!id || !cbs) {
322                 _E("invalid parameter");
323                 return -1;
324         }
325
326         if (!__viewer_tbl) {
327                 __viewer_tbl = g_hash_table_new(g_str_hash, g_str_equal);
328                 if (!__viewer_tbl) {
329                         _E("unable to create hashtable");
330                         return -1;
331                 }
332         }
333
334         surface = (struct __surface_s *)malloc(sizeof(struct __surface_s));
335         if (!surface) {
336                 _E("out of memory");
337                 return -1;
338         }
339
340         surface->id = strdup(id);
341         if (!surface->id) {
342                 _E("out of memory");
343                 free(surface);
344                 return -1;
345         }
346
347         surface->resource_id = -1;
348         surface->data = data;
349         surface->update_cb = cbs->aul_rsm_surface_update_cb;
350         surface->missing_cb = cbs->aul_rsm_surface_missing_cb;
351
352         g_hash_table_insert(__viewer_tbl, surface->id, surface);
353
354         return 0;
355 }
356
357 API int aul_rsm_viewer_set_surface_handler_by_rid(int resource_id, aul_rsm_handler *cbs, void *data)
358 {
359         char buf[32];
360         struct __surface_s *surface;
361
362         snprintf(buf, sizeof(buf), "%d", resource_id);
363         aul_rsm_viewer_set_surface_handler(buf, cbs, data);
364         surface = g_hash_table_lookup(__viewer_tbl, buf);
365         __redirect_surface(surface);
366
367         return 0;
368 }
369
370 API int aul_rsm_viewer_get_surface_rid(const char *id, int *resource_id)
371 {
372         struct __surface_s *surface;
373
374         if (!id || !resource_id) {
375                 _E("illegal arguments");
376                 return -1;
377         }
378
379         surface = g_hash_table_lookup(__viewer_tbl, id);
380         if (!surface) {
381                 _E("unknown surface");
382                 return -1;
383         }
384
385         if (surface->resource_id < 0) {
386                 _E("resource id not yet initialized");
387                 return -1;
388         }
389
390         *resource_id = surface->resource_id;
391         return 0;
392 }
393
394 API int aul_rsm_viewer_get_surface_pid(const char *id, int *pid)
395 {
396         struct __surface_s *surface;
397
398         if (!id || !pid) {
399                 _E("illegal arguments");
400                 return -1;
401         }
402
403         surface = g_hash_table_lookup(__viewer_tbl, id);
404         if (!surface) {
405                 _E("unknown surface");
406                 return -1;
407         }
408
409         if (surface->pid < 1) {
410                 _E("resource id not yet initialized");
411                 return -1;
412         }
413
414         *pid = surface->pid;
415         return 0;
416 }