screen: add ds_tizen_screen
[platform/core/uifw/libds-tizen.git] / src / launch / appinfo.c
1 #include <stdlib.h>
2 #include <wayland-server.h>
3 #include <tizen-launch-server-protocol.h>
4 #include <libds/log.h>
5
6 #include "util.h"
7 #include <libds-tizen/launch.h>
8
9 #define TIZEN_APPINFO_VERSION 1
10
11 struct ds_tizen_launch_appinfo_mgr
12 {
13     struct wl_global *global;
14
15     struct wl_list clients;
16     struct wl_list infos;
17
18     struct wl_listener destroy;
19
20     struct {
21         struct wl_signal destroy;
22         struct wl_signal set_pid;
23         struct wl_signal set_appid;
24         struct wl_signal metadata_ready;
25     } events;
26
27     struct wl_resource *resource; //for gtest
28 };
29
30 struct ds_tizen_launch_appinfo_client
31 {
32     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
33
34     struct wl_resource *resource;
35     struct wl_client *wl_client;
36
37     struct wl_list link; // ds_tizen_launch_appinfo_mgr::clients
38 };
39
40 enum ds_tizen_launch_appinfo_owner
41 {
42     DS_TIZEN_LAUNCH_APPINFO_OWNER_SERVER,
43     DS_TIZEN_LAUNCH_APPINFO_OWNER_CLIENT,
44 };
45
46 struct ds_tizen_launch_appinfo
47 {
48     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
49
50     pid_t pid;
51     char *appid;
52     bool base_output_available;
53     int base_output_width;
54     int base_output_height;
55     enum ds_tizen_launch_appinfo_owner owner;
56
57     struct wl_list link; //ds_tizen_launch_appinfo_mgr::infos;
58 };
59
60 static void appinfo_mgr_handle_display_destroy(struct wl_listener *listener,
61         void *data);
62
63 static void appinfo_mgr_bind(struct wl_client *wl_client, void *data,
64         uint32_t version, uint32_t id);
65
66 WL_EXPORT struct ds_tizen_launch_appinfo_mgr *
67 ds_tizen_launch_appinfo_mgr_create(struct wl_display *display)
68 {
69     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
70
71     appinfo_mgr = calloc(1, sizeof *appinfo_mgr);
72     if (!appinfo_mgr) {
73         ds_err("calloc() failed.");
74         return NULL;
75     }
76
77     appinfo_mgr->global = wl_global_create(display, &tizen_launch_appinfo_interface,
78             TIZEN_APPINFO_VERSION, appinfo_mgr, appinfo_mgr_bind);
79     if (!appinfo_mgr->global) {
80         ds_err("wl_global_create() failed. tizen_launch_appinfo_interface");
81         free(appinfo_mgr);
82         return NULL;
83     }
84
85     wl_list_init(&appinfo_mgr->clients);
86     wl_list_init(&appinfo_mgr->infos);
87
88     appinfo_mgr->destroy.notify = appinfo_mgr_handle_display_destroy;
89     wl_display_add_destroy_listener(display, &appinfo_mgr->destroy);
90
91     wl_signal_init(&appinfo_mgr->events.destroy);
92     wl_signal_init(&appinfo_mgr->events.set_pid);
93     wl_signal_init(&appinfo_mgr->events.set_appid);
94     wl_signal_init(&appinfo_mgr->events.metadata_ready);
95
96     ds_inf("Global create: tizen_launch_appinfo. appinfo_mgr(%p)", appinfo_mgr);
97
98     return appinfo_mgr;
99 }
100
101 WL_EXPORT void
102 ds_tizen_launch_appinfo_mgr_add_destroy_listener(
103     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
104 {
105     wl_signal_add(&appinfo_mgr->events.destroy, listener);
106 }
107
108 WL_EXPORT void
109 ds_tizen_launch_appinfo_mgr_add_set_pid_listener(
110     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
111 {
112     wl_signal_add(&appinfo_mgr->events.set_pid, listener);
113 }
114
115 WL_EXPORT void
116 ds_tizen_launch_appinfo_mgr_add_set_appid_listener(
117     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
118 {
119     wl_signal_add(&appinfo_mgr->events.set_appid, listener);
120 }
121
122 WL_EXPORT void
123 ds_tizen_launch_appinfo_mgr_add_metadata_ready_listener(
124     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
125 {
126     wl_signal_add(&appinfo_mgr->events.metadata_ready, listener);
127 }
128
129 static void
130 appinfo_mgr_handle_display_destroy(struct wl_listener *listener, void *data)
131 {
132     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
133     struct ds_tizen_launch_appinfo_client *client, *tmp_client;
134     struct ds_tizen_launch_appinfo *info, *tmp_info;
135
136     appinfo_mgr = wl_container_of(listener, appinfo_mgr, destroy);
137
138     ds_inf("Global destroy: appinfo_mgr(%p)", appinfo_mgr);
139
140     wl_signal_emit_mutable(&appinfo_mgr->events.destroy, appinfo_mgr);
141     wl_list_remove(&appinfo_mgr->destroy.link);
142
143     wl_list_for_each_safe(client, tmp_client, &appinfo_mgr->clients, link) {
144         wl_list_remove(&client->link);
145         free(client);
146     }
147
148     wl_list_for_each_safe(info, tmp_info, &appinfo_mgr->infos, link) {
149         wl_list_remove(&info->link);
150         free(info->appid);
151         free(info);
152     }
153
154     wl_global_destroy(appinfo_mgr->global);
155     free(appinfo_mgr);
156 }
157
158 static void
159 appinfo_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource)
160 {
161     wl_resource_destroy(resource);
162 }
163
164 static struct ds_tizen_launch_appinfo *
165 appinfo_mgr_find_with_pid(struct ds_tizen_launch_appinfo_mgr *appinfo_mgr,
166     pid_t pid)
167 {
168     struct ds_tizen_launch_appinfo *info;
169
170     wl_list_for_each(info, &appinfo_mgr->infos, link) {
171         if (pid == info->pid)
172             return info;
173     }
174
175     return NULL;
176 }
177
178 static struct ds_tizen_launch_appinfo *
179 appinfo_mgr_find_with_appid(struct ds_tizen_launch_appinfo_mgr *appinfo_mgr,
180     const char *appid)
181 {
182     struct ds_tizen_launch_appinfo *info;
183
184     wl_list_for_each(info, &appinfo_mgr->infos, link) {
185         if (appid && !strcmp(appid, info->appid))
186             return info;
187     }
188
189     return NULL;
190 }
191 static struct ds_tizen_launch_appinfo *
192 appinfo_mgr_get_info(struct ds_tizen_launch_appinfo_mgr *appinfo_mgr,
193     pid_t pid, const char *appid)
194 {
195     struct ds_tizen_launch_appinfo *info = NULL;
196
197     if (pid > 0)
198         info = appinfo_mgr_find_with_pid(appinfo_mgr, pid);
199     else if (appid)
200         info = appinfo_mgr_find_with_appid(appinfo_mgr, appid);
201
202     if (info) {
203         return info;
204     }
205
206     info = calloc(1, sizeof *info);
207     if (info == NULL) {
208         ds_err("calloc() failed. tizen_appinfo");
209         return NULL;
210     }
211
212     if (pid > 0)
213         info->pid = pid;
214     else if (appid)
215         info->appid = strdup(appid);
216
217     info->appinfo_mgr = appinfo_mgr;
218
219     wl_list_insert(&appinfo_mgr->infos, &info->link);
220
221     return info;
222 }
223
224 static void
225 appinfo_destroy(struct ds_tizen_launch_appinfo *info)
226 {
227     wl_list_remove(&info->link);
228     free(info->appid);
229     free(info);
230 }
231
232 static bool
233 appinfo_set_pid(struct ds_tizen_launch_appinfo *info, pid_t pid)
234 {
235     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
236     struct ds_tizen_launch_appinfo *info2, *tmp;
237
238     if (!info) return false;
239     if (pid < 0) return false;
240
241     appinfo_mgr = info->appinfo_mgr;
242
243     wl_list_for_each_safe(info2, tmp, &appinfo_mgr->infos, link) {
244         if ((info2->pid == pid) && (info2 != info)) {
245             ds_inf("removed duplicated appinfo");
246
247             if (!info->appid) info->appid = strdup(info2->appid);
248             if (!info->base_output_available && info2->base_output_available) {
249                 ds_inf("copy base_output variable into appinfo.");
250                 info->base_output_available = true;
251                 info->base_output_width = info2->base_output_width;
252                 info->base_output_height = info2->base_output_height;
253             }
254             appinfo_destroy(info2);
255         }
256     }
257
258     info->pid = pid;
259     ds_inf("appinfo(%p) set pid(%u)", info, pid);
260
261     wl_signal_emit_mutable(&appinfo_mgr->events.set_pid, info);
262
263     return true;
264 }
265
266 static bool
267 appinfo_set_appid(struct ds_tizen_launch_appinfo *info, const char *appid)
268 {
269     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr;
270     struct ds_tizen_launch_appinfo *info2, *tmp;
271
272     if (!info) return false;
273     if (!appid) return false;
274
275     appinfo_mgr = info->appinfo_mgr;
276
277     wl_list_for_each_safe(info2, tmp, &appinfo_mgr->infos, link) {
278         if ((info2->appid && !strcmp(info2->appid, appid)) &&
279             (info2 != info)) {
280             ds_inf("removed duplicated appinfo");
281
282             if (info->pid < 0) info->pid = info2->pid;
283             if (!info->base_output_available && info2->base_output_available)
284             {
285                 ds_inf("copy base_output variable into appinfo.");
286                 info->base_output_available = true;
287                 info->base_output_width = info2->base_output_width;
288                 info->base_output_height = info2->base_output_height;
289             }
290             appinfo_destroy(info2);
291         }
292     }
293
294     free(info->appid);
295     info->appid = strdup(appid);
296     ds_inf("appinfo(%p) set appid(%u)", info, appid);
297
298     wl_signal_emit_mutable(&appinfo_mgr->events.set_appid, info);
299
300     return true;
301 }
302
303 static bool
304 appinfo_get_base_output_resolution(struct ds_tizen_launch_appinfo *info, int *width, int *height)
305 {
306     if (!info) return false;
307     if (!width) return false;
308     if (!height) return false;
309
310     if (!info->base_output_available) {
311         *width = 0;
312         *height = 0;
313         return false;
314     }
315     *width = info->base_output_width;
316     *height = info->base_output_height;
317
318     return true;
319 }
320
321 static void
322 appinfo_set_owner(struct ds_tizen_launch_appinfo *info, enum ds_tizen_launch_appinfo_owner owner)
323 {
324     if (!info) return;
325
326     info->owner = owner;
327 }
328
329 static void
330 appinfo_handle_register_pid(struct wl_client *wl_client,
331     struct wl_resource *resource, uint32_t pid)
332 {
333     struct ds_tizen_launch_appinfo_client *client;
334     struct ds_tizen_launch_appinfo *info;
335
336     client = wl_resource_get_user_data(resource);
337
338     if (pid <= 0) {
339         ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
340         return;
341     }
342
343     info = appinfo_mgr_get_info(client->appinfo_mgr, pid, NULL);
344     if (info == NULL) {
345         ds_err("appinfo_mgr_get_info() failed. tizen_appinfo");
346         wl_client_post_no_memory(wl_client);
347         return;
348     }
349
350     appinfo_set_pid(info, pid);
351     appinfo_set_owner(info, DS_TIZEN_LAUNCH_APPINFO_OWNER_CLIENT);
352 }
353
354
355 static void
356 appinfo_handle_deregister_pid(struct wl_client *wl_client,
357     struct wl_resource *resource, uint32_t pid)
358 {
359     struct ds_tizen_launch_appinfo_client *client;
360     struct ds_tizen_launch_appinfo *info;
361
362     client = wl_resource_get_user_data(resource);
363
364     info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
365     if (info == NULL) {
366         ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
367         return;
368     }
369
370     appinfo_destroy(info);
371 }
372
373 static void
374 appinfo_handle_set_appid(struct wl_client *wl_client,
375     struct wl_resource *resource, uint32_t pid, const char *appid)
376 {
377     struct ds_tizen_launch_appinfo_client *client;
378     struct ds_tizen_launch_appinfo *info;
379
380     client = wl_resource_get_user_data(resource);
381
382     if (pid <= 0) {
383         ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
384         return;
385     }
386
387     info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
388     if (info == NULL) {
389         ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
390         return;
391     }
392
393     appinfo_set_appid(info, appid);
394
395     /* TODO: base  output resolution */
396 }
397
398 //for gtest
399 WL_EXPORT struct wl_resource *
400 ds_tizen_launch_appinfo_mgr_get_appinfo_resource(
401         struct ds_tizen_launch_appinfo_mgr *appinfo_mgr)
402 {
403     return appinfo_mgr->resource;
404 }
405
406 static void
407 appinfo_handle_get_base_output_resolution(struct wl_client *wl_client,
408     struct wl_resource *resource, uint32_t pid)
409 {
410     struct ds_tizen_launch_appinfo_client *client;
411     struct ds_tizen_launch_appinfo *info;
412     int width = 0, height = 0;
413
414     client = wl_resource_get_user_data(resource);
415
416     if (pid <= 0) {
417         ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
418         goto finish;
419     }
420
421     info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
422     if (info == NULL) {
423         ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
424         goto finish;
425     }
426
427     appinfo_get_base_output_resolution(info, &width, &height);
428
429     client->appinfo_mgr->resource = resource;
430
431 finish:
432     if (width == 0 && height == 0) {
433         width = 1080; //e_config->configured_output_resolution.w;
434         height = 1920; //e_config->configured_output_resolution.h;
435     }
436
437     ds_inf("send base_output_resolution. size(%d x %d). pid(%u)", width, height, pid);
438     tizen_launch_appinfo_send_base_output_resolution_done(resource, pid, width, height);
439 }
440
441 static void
442 appinfo_handle_register_appid(struct wl_client *wl_client, struct wl_resource *resource,
443     const char *appid)
444 {
445     struct ds_tizen_launch_appinfo_client *client;
446     struct ds_tizen_launch_appinfo *info;
447
448     client = wl_resource_get_user_data(resource);
449
450     info = appinfo_mgr_get_info(client->appinfo_mgr, -1, appid);
451     if (info == NULL) {
452         ds_err("appinfo_mgr_get_info() failed. tizen_appinfo");
453         wl_client_post_no_memory(wl_client);
454         return;
455     }
456
457     appinfo_set_appid(info, appid);
458     appinfo_set_owner(info, DS_TIZEN_LAUNCH_APPINFO_OWNER_CLIENT);
459 }
460
461 static void
462 appinfo_handle_deregister_appid(struct wl_client *wl_client,
463     struct wl_resource *resource, const char *appid)
464 {
465     struct ds_tizen_launch_appinfo_client *client;
466     struct ds_tizen_launch_appinfo *info;
467
468     client = wl_resource_get_user_data(resource);
469
470     info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
471     if (info == NULL) {
472         ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
473         return;
474     }
475
476     appinfo_destroy(info);
477 }
478
479 static void
480 appinfo_handle_set_pid(struct wl_client *wl_client,
481     struct wl_resource *resource, const char *appid, uint32_t pid)
482 {
483     struct ds_tizen_launch_appinfo_client *client;
484     struct ds_tizen_launch_appinfo *info;
485
486     client = wl_resource_get_user_data(resource);
487
488     info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
489     if (info == NULL) {
490         ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
491         return;
492     }
493
494     appinfo_set_pid(info, pid);
495 }
496
497 static void
498 appinfo_handle_ready_metadata(struct wl_client *wl_client,
499     struct wl_resource *resource, const char *appid, uint32_t pid)
500 {
501     struct ds_tizen_launch_appinfo_client *client;
502     struct ds_tizen_launch_appinfo *info;
503
504     client = wl_resource_get_user_data(resource);
505
506     info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
507     if (info == NULL) {
508         ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
509         return;
510     }
511
512     if ((uint32_t)info->pid != pid)
513         appinfo_set_pid(info, pid);
514
515     wl_signal_emit_mutable(&client->appinfo_mgr->events.metadata_ready, info);
516
517     /* TODO: base  output resolution */
518 }
519
520 static const struct tizen_launch_appinfo_interface appinfo_impl =
521 {
522    appinfo_handle_destroy,
523    appinfo_handle_register_pid,
524    appinfo_handle_deregister_pid,
525    appinfo_handle_set_appid,
526    appinfo_handle_get_base_output_resolution,
527    appinfo_handle_register_appid,
528    appinfo_handle_deregister_appid,
529    appinfo_handle_set_pid,
530    appinfo_handle_ready_metadata,
531 };
532
533 static void
534 _tizen_appinfo_client_handle_destroy(struct wl_resource *resource)
535 {
536     struct ds_tizen_launch_appinfo_client *client;
537
538     client = wl_resource_get_user_data(resource);
539
540     ds_inf("_tizen_appinfo_client_handle_destroy (client:%p)", client);
541
542     wl_list_remove(&client->link);
543     free(client);
544 }
545
546 static void appinfo_mgr_bind(struct wl_client *wl_client, void *data,
547         uint32_t version, uint32_t id)
548 {
549     struct ds_tizen_launch_appinfo_mgr *appinfo_mgr = data;
550     struct ds_tizen_launch_appinfo_client *client;
551
552     client = calloc(1, sizeof *client);
553     if (client == NULL) {
554         ds_err("calloc() failed. tizen_appinfo");
555         wl_client_post_no_memory(wl_client);
556         return;
557     }
558
559     ds_inf("tizen_appinfo_client_binds. (client:%p)", client);
560
561     client->appinfo_mgr = appinfo_mgr;
562     client->wl_client = wl_client;
563
564     client->resource = wl_resource_create(wl_client,
565             &tizen_launch_appinfo_interface,
566             MIN(version, TIZEN_APPINFO_VERSION), id);
567
568     if (client->resource == NULL) {
569         ds_err("tizen_appinfo : wl_resource_create() failed.");
570         free(client);
571         wl_client_post_no_memory(wl_client);
572         return;
573     }
574
575     wl_resource_set_implementation(client->resource, &appinfo_impl, client,
576             _tizen_appinfo_client_handle_destroy);
577
578     wl_list_insert(&appinfo_mgr->clients, &client->link);
579 }