launch: implement appinfo interface 27/278627/1
authorduna.oh <duna.oh@samsung.com>
Thu, 21 Jul 2022 17:41:29 +0000 (02:41 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 22 Jul 2022 14:00:29 +0000 (23:00 +0900)
Change-Id: I6afd36726e16ed967bffc6f9b24c772c1740bab8

include/libds-tizen/launch/appinfo.h [new file with mode: 0644]
packaging/libds-tizen.spec
src/launch/appinfo.c [new file with mode: 0644]
src/launch/meson.build [new file with mode: 0644]
src/meson.build
tests/meson.build
tests/tc_launch_appinfo.cpp [new file with mode: 0644]

diff --git a/include/libds-tizen/launch/appinfo.h b/include/libds-tizen/launch/appinfo.h
new file mode 100644 (file)
index 0000000..bd62e9b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef LIBDS_TIZEN_APPINFO_H
+#define LIBDS_TIZEN_APPINFO_H
+
+#include <stdint.h>
+#include <wayland-server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ds_tizen_appinfo_mgr;
+struct ds_tizen_appinfo;
+
+struct ds_tizen_appinfo_mgr *
+ds_tizen_appinfo_mgr_create(struct wl_display *display);
+
+void
+ds_tizen_appinfo_mgr_add_destroy_listener(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener);
+
+void
+ds_tizen_appinfo_mgr_add_set_pid_listener(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener);
+
+void
+ds_tizen_appinfo_mgr_add_set_appid_listener(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener);
+
+void
+ds_tizen_appinfo_mgr_add_metadata_ready_listener(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener);
+
+//for gtest
+struct wl_resource *
+ds_tizen_appinfo_mgr_get_appinfo_resource(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 16e6ce7..27af91c 100644 (file)
@@ -14,6 +14,8 @@ BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  pkgconfig(wayland-protocols)
 BuildRequires:  pkgconfig(tizen-extension-server)
 BuildRequires:  pkgconfig(tizen-extension-client)
+BuildRequires:  pkgconfig(tizen-launch-server)
+BuildRequires:  pkgconfig(tizen-launch-client)
 BuildRequires:  pkgconfig(pixman-1)
 BuildRequires:  pkgconfig(libdrm)
 BuildRequires:  pkgconfig(xkbcommon)
@@ -152,6 +154,21 @@ Group:   Development/Libraries
 %description clipboard-devel
 Development package for tizen clipboard
 
+## libds-tizen-launch
+%package launch
+Summary: Library for tizen launch
+Group:   Development/Libraries
+
+%description launch
+Library for tizen launch
+
+%package launch-devel
+Summary: Development package for tizen launch
+Group:   Development/Libraries
+
+%description launch-devel
+Development package for tizen launch
+
 %prep
 %setup -q
 cp %{SOURCE1001} .
@@ -292,3 +309,18 @@ ninja -C builddir install
 %{_libdir}/pkgconfig/libds-tizen-clipboard.pc
 %{_libdir}/libds-tizen-clipboard.so
 %{_bindir}/libds-tizen-clipboard-tests
+
+%files launch
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_libdir}/libds-tizen-launch.so.*
+
+%files launch-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%license LICENSE
+%{_includedir}/libds-tizen/launch/appinfo.h
+%{_libdir}/pkgconfig/libds-tizen-launch.pc
+%{_libdir}/libds-tizen-launch.so
+%{_bindir}/libds-tizen-launch-appinfo-tests
diff --git a/src/launch/appinfo.c b/src/launch/appinfo.c
new file mode 100644 (file)
index 0000000..0b6c8c2
--- /dev/null
@@ -0,0 +1,579 @@
+#include <stdlib.h>
+#include <wayland-server.h>
+#include <tizen-launch-server-protocol.h>
+#include <libds/log.h>
+
+#include "util.h"
+#include <libds-tizen/launch/appinfo.h>
+
+#define TIZEN_APPINFO_VERSION 1
+
+struct ds_tizen_appinfo_mgr
+{
+    struct wl_global *global;
+
+    struct wl_list clients;
+    struct wl_list infos;
+
+    struct wl_listener destroy;
+
+    struct {
+        struct wl_signal destroy;
+        struct wl_signal set_pid;
+        struct wl_signal set_appid;
+        struct wl_signal metadata_ready;
+    } events;
+
+    struct wl_resource *resource; //for gtest
+};
+
+struct ds_tizen_appinfo_client
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+
+    struct wl_resource *resource;
+    struct wl_client *wl_client;
+
+    struct wl_list link; // ds_tizen_appinfo_mgr::clients
+};
+
+enum ds_tizen_appinfo_owner
+{
+    DS_TIZEN_APPINFO_OWNER_SERVER,
+    DS_TIZEN_APPINFO_OWNER_CLIENT,
+};
+
+struct ds_tizen_appinfo
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+
+    pid_t pid;
+    char *appid;
+    bool base_output_available;
+    int base_output_width;
+    int base_output_height;
+    enum ds_tizen_appinfo_owner owner;
+
+    struct wl_list link; //ds_tizen_appinfo_mgr::infos;
+};
+
+static void appinfo_mgr_handle_display_destroy(struct wl_listener *listener,
+        void *data);
+
+static void appinfo_mgr_bind(struct wl_client *wl_client, void *data,
+        uint32_t version, uint32_t id);
+
+WL_EXPORT struct ds_tizen_appinfo_mgr *
+ds_tizen_appinfo_mgr_create(struct wl_display *display)
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+
+    appinfo_mgr = calloc(1, sizeof *appinfo_mgr);
+    if (!appinfo_mgr) {
+        ds_err("calloc() failed.");
+        return NULL;
+    }
+
+    appinfo_mgr->global = wl_global_create(display, &tizen_launch_appinfo_interface,
+            TIZEN_APPINFO_VERSION, appinfo_mgr, appinfo_mgr_bind);
+    if (!appinfo_mgr->global) {
+        ds_err("wl_global_create() failed. tizen_launch_appinfo_interface");
+        free(appinfo_mgr);
+        return NULL;
+    }
+
+    wl_list_init(&appinfo_mgr->clients);
+    wl_list_init(&appinfo_mgr->infos);
+
+    appinfo_mgr->destroy.notify = appinfo_mgr_handle_display_destroy;
+    wl_display_add_destroy_listener(display, &appinfo_mgr->destroy);
+
+    wl_signal_init(&appinfo_mgr->events.destroy);
+    wl_signal_init(&appinfo_mgr->events.set_pid);
+    wl_signal_init(&appinfo_mgr->events.set_appid);
+    wl_signal_init(&appinfo_mgr->events.metadata_ready);
+
+    ds_inf("Global create: tizen_launch_appinfo. appinfo_mgr(%p)", appinfo_mgr);
+
+    return appinfo_mgr;
+}
+
+WL_EXPORT void
+ds_tizen_appinfo_mgr_add_destroy_listener(
+    struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
+{
+    wl_signal_add(&appinfo_mgr->events.destroy, listener);
+}
+
+WL_EXPORT void
+ds_tizen_appinfo_mgr_add_set_pid_listener(
+    struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
+{
+    wl_signal_add(&appinfo_mgr->events.set_pid, listener);
+}
+
+WL_EXPORT void
+ds_tizen_appinfo_mgr_add_set_appid_listener(
+    struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
+{
+    wl_signal_add(&appinfo_mgr->events.set_appid, listener);
+}
+
+WL_EXPORT void
+ds_tizen_appinfo_mgr_add_metadata_ready_listener(
+    struct ds_tizen_appinfo_mgr *appinfo_mgr, struct wl_listener *listener)
+{
+    wl_signal_add(&appinfo_mgr->events.metadata_ready, listener);
+}
+
+static void
+appinfo_mgr_handle_display_destroy(struct wl_listener *listener, void *data)
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+    struct ds_tizen_appinfo_client *client, *tmp_client;
+    struct ds_tizen_appinfo *info, *tmp_info;
+
+    appinfo_mgr = wl_container_of(listener, appinfo_mgr, destroy);
+
+    ds_inf("Global destroy: appinfo_mgr(%p)", appinfo_mgr);
+
+    wl_signal_emit(&appinfo_mgr->events.destroy, appinfo_mgr);
+    wl_list_remove(&appinfo_mgr->destroy.link);
+
+    wl_list_for_each_safe(client, tmp_client, &appinfo_mgr->clients, link) {
+        wl_list_remove(&client->link);
+        free(client);
+    }
+
+    wl_list_for_each_safe(info, tmp_info, &appinfo_mgr->infos, link) {
+        wl_list_remove(&info->link);
+        free(info->appid);
+        free(info);
+    }
+
+    wl_global_destroy(appinfo_mgr->global);
+    free(appinfo_mgr);
+}
+
+static void
+appinfo_handle_destroy(struct wl_client *wl_client, struct wl_resource *resource)
+{
+    wl_resource_destroy(resource);
+}
+
+static struct ds_tizen_appinfo *
+appinfo_mgr_find_with_pid(struct ds_tizen_appinfo_mgr *appinfo_mgr,
+    pid_t pid)
+{
+    struct ds_tizen_appinfo *info;
+
+    wl_list_for_each(info, &appinfo_mgr->infos, link) {
+        if (pid == info->pid)
+            return info;
+    }
+
+    return NULL;
+}
+
+static struct ds_tizen_appinfo *
+appinfo_mgr_find_with_appid(struct ds_tizen_appinfo_mgr *appinfo_mgr,
+    const char *appid)
+{
+    struct ds_tizen_appinfo *info;
+
+    wl_list_for_each(info, &appinfo_mgr->infos, link) {
+        if (appid && !strcmp(appid, info->appid))
+            return info;
+    }
+
+    return NULL;
+}
+static struct ds_tizen_appinfo *
+appinfo_mgr_get_info(struct ds_tizen_appinfo_mgr *appinfo_mgr,
+    pid_t pid, const char *appid)
+{
+    struct ds_tizen_appinfo *info = NULL;
+
+    if (pid > 0)
+        info = appinfo_mgr_find_with_pid(appinfo_mgr, pid);
+    else if (appid)
+        info = appinfo_mgr_find_with_appid(appinfo_mgr, appid);
+
+    if (info) {
+        return info;
+    }
+
+    info = calloc(1, sizeof *info);
+    if (info == NULL) {
+        ds_err("calloc() failed. tizen_appinfo");
+        return NULL;
+    }
+
+    if (pid > 0)
+        info->pid = pid;
+    else if (appid)
+        info->appid = strdup(appid);
+
+    info->appinfo_mgr = appinfo_mgr;
+
+    wl_list_insert(&appinfo_mgr->infos, &info->link);
+
+    return info;
+}
+
+static void
+appinfo_destroy(struct ds_tizen_appinfo *info)
+{
+    wl_list_remove(&info->link);
+    free(info->appid);
+    free(info);
+}
+
+static bool
+appinfo_set_pid(struct ds_tizen_appinfo *info, pid_t pid)
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+    struct ds_tizen_appinfo *info2, *tmp;
+
+    if (!info) return false;
+    if (pid < 0) return false;
+
+    appinfo_mgr = info->appinfo_mgr;
+
+    wl_list_for_each_safe(info2, tmp, &appinfo_mgr->infos, link) {
+        if ((info2->pid == pid) && (info2 != info)) {
+            ds_inf("removed duplicated appinfo");
+
+            if (!info->appid) info->appid = strdup(info2->appid);
+            if (!info->base_output_available && info2->base_output_available) {
+                ds_inf("copy base_output variable into appinfo.");
+                info->base_output_available = true;
+                info->base_output_width = info2->base_output_width;
+                info->base_output_height = info2->base_output_height;
+            }
+            appinfo_destroy(info2);
+        }
+    }
+
+    info->pid = pid;
+    ds_inf("appinfo(%p) set pid(%u)", info, pid);
+
+    wl_signal_emit(&appinfo_mgr->events.set_pid, info);
+
+    return true;
+}
+
+static bool
+appinfo_set_appid(struct ds_tizen_appinfo *info, const char *appid)
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr;
+    struct ds_tizen_appinfo *info2, *tmp;
+
+    if (!info) return false;
+    if (!appid) return false;
+
+    appinfo_mgr = info->appinfo_mgr;
+
+    wl_list_for_each_safe(info2, tmp, &appinfo_mgr->infos, link) {
+        if ((info2->appid && !strcmp(info2->appid, appid)) &&
+            (info2 != info)) {
+            ds_inf("removed duplicated appinfo");
+
+            if (info->pid < 0) info->pid = info2->pid;
+            if (!info->base_output_available && info2->base_output_available)
+            {
+                ds_inf("copy base_output variable into appinfo.");
+                info->base_output_available = true;
+                info->base_output_width = info2->base_output_width;
+                info->base_output_height = info2->base_output_height;
+            }
+            appinfo_destroy(info2);
+        }
+    }
+
+    free(info->appid);
+    info->appid = strdup(appid);
+    ds_inf("appinfo(%p) set appid(%u)", info, appid);
+
+    wl_signal_emit(&appinfo_mgr->events.set_appid, info);
+
+    return true;
+}
+
+static bool
+appinfo_get_base_output_resolution(struct ds_tizen_appinfo *info, int *width, int *height)
+{
+    if (!info) return false;
+    if (!width) return false;
+    if (!height) return false;
+
+    if (!info->base_output_available) {
+        *width = 0;
+        *height = 0;
+        return false;
+    }
+    *width = info->base_output_width;
+    *height = info->base_output_height;
+
+    return true;
+}
+
+static void
+appinfo_set_owner(struct ds_tizen_appinfo *info, enum ds_tizen_appinfo_owner owner)
+{
+    if (!info) return;
+
+    info->owner = owner;
+}
+
+static void
+appinfo_handle_register_pid(struct wl_client *wl_client,
+    struct wl_resource *resource, uint32_t pid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    if (pid <= 0) {
+        ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
+        return;
+    }
+
+    info = appinfo_mgr_get_info(client->appinfo_mgr, pid, NULL);
+    if (info == NULL) {
+        ds_err("appinfo_mgr_get_info() failed. tizen_appinfo");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    appinfo_set_pid(info, pid);
+    appinfo_set_owner(info, DS_TIZEN_APPINFO_OWNER_CLIENT);
+}
+
+
+static void
+appinfo_handle_deregister_pid(struct wl_client *wl_client,
+    struct wl_resource *resource, uint32_t pid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
+        return;
+    }
+
+    appinfo_destroy(info);
+}
+
+static void
+appinfo_handle_set_appid(struct wl_client *wl_client,
+    struct wl_resource *resource, uint32_t pid, const char *appid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    if (pid <= 0) {
+        ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
+        return;
+    }
+
+    info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
+        return;
+    }
+
+    appinfo_set_appid(info, appid);
+
+    /* TODO: base  output resolution */
+}
+
+//for gtest
+WL_EXPORT struct wl_resource *
+ds_tizen_appinfo_mgr_get_appinfo_resource(
+        struct ds_tizen_appinfo_mgr *appinfo_mgr)
+{
+    return appinfo_mgr->resource;
+}
+
+static void
+appinfo_handle_get_base_output_resolution(struct wl_client *wl_client,
+    struct wl_resource *resource, uint32_t pid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+    int width = 0, height = 0;
+
+    client = wl_resource_get_user_data(resource);
+
+    if (pid <= 0) {
+        ds_err("tizen_appinfo: pid is invalid. pid:%u", pid);
+        goto finish;
+    }
+
+    info = appinfo_mgr_find_with_pid(client->appinfo_mgr, pid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by pid(%u)", pid);
+        goto finish;
+    }
+
+    appinfo_get_base_output_resolution(info, &width, &height);
+
+    client->appinfo_mgr->resource = resource;
+
+finish:
+    if (width == 0 && height == 0) {
+        width = 1080; //e_config->configured_output_resolution.w;
+        height = 1920; //e_config->configured_output_resolution.h;
+    }
+
+    ds_inf("send base_output_resolution. size(%d x %d). pid(%u)", width, height, pid);
+    tizen_launch_appinfo_send_base_output_resolution_done(resource, pid, width, height);
+}
+
+static void
+appinfo_handle_register_appid(struct wl_client *wl_client, struct wl_resource *resource,
+    const char *appid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    info = appinfo_mgr_get_info(client->appinfo_mgr, -1, appid);
+    if (info == NULL) {
+        ds_err("appinfo_mgr_get_info() failed. tizen_appinfo");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    appinfo_set_appid(info, appid);
+    appinfo_set_owner(info, DS_TIZEN_APPINFO_OWNER_CLIENT);
+}
+
+static void
+appinfo_handle_deregister_appid(struct wl_client *wl_client,
+    struct wl_resource *resource, const char *appid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
+        return;
+    }
+
+    appinfo_destroy(info);
+}
+
+static void
+appinfo_handle_set_pid(struct wl_client *wl_client,
+    struct wl_resource *resource, const char *appid, uint32_t pid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
+        return;
+    }
+
+    appinfo_set_pid(info, pid);
+}
+
+static void
+appinfo_handle_ready_metadata(struct wl_client *wl_client,
+    struct wl_resource *resource, const char *appid, uint32_t pid)
+{
+    struct ds_tizen_appinfo_client *client;
+    struct ds_tizen_appinfo *info;
+
+    client = wl_resource_get_user_data(resource);
+
+    info = appinfo_mgr_find_with_appid(client->appinfo_mgr, appid);
+    if (info == NULL) {
+        ds_err("tizen_appinfo: no appinfo found by appid(%u)", appid);
+        return;
+    }
+
+    if (info->pid != pid)
+        appinfo_set_pid(info, pid);
+
+    wl_signal_emit(&client->appinfo_mgr->events.metadata_ready, info);
+
+    /* TODO: base  output resolution */
+}
+
+static const struct tizen_launch_appinfo_interface appinfo_impl =
+{
+   appinfo_handle_destroy,
+   appinfo_handle_register_pid,
+   appinfo_handle_deregister_pid,
+   appinfo_handle_set_appid,
+   appinfo_handle_get_base_output_resolution,
+   appinfo_handle_register_appid,
+   appinfo_handle_deregister_appid,
+   appinfo_handle_set_pid,
+   appinfo_handle_ready_metadata,
+};
+
+static void
+_tizen_appinfo_client_handle_destroy(struct wl_resource *resource)
+{
+    struct ds_tizen_appinfo_client *client;
+
+    client = wl_resource_get_user_data(resource);
+
+    ds_inf("_tizen_appinfo_client_handle_destroy (client:%p)", client);
+
+    wl_list_remove(&client->link);
+    free(client);
+}
+
+static void appinfo_mgr_bind(struct wl_client *wl_client, void *data,
+        uint32_t version, uint32_t id)
+{
+    struct ds_tizen_appinfo_mgr *appinfo_mgr = data;
+    struct ds_tizen_appinfo_client *client;
+
+    client = calloc(1, sizeof *client);
+    if (client == NULL) {
+        ds_err("calloc() failed. tizen_appinfo");
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    ds_inf("tizen_appinfo_client_binds. (client:%p)", client);
+
+    client->appinfo_mgr = appinfo_mgr;
+    client->wl_client = wl_client;
+
+    client->resource = wl_resource_create(wl_client,
+            &tizen_launch_appinfo_interface,
+            MIN(version, TIZEN_APPINFO_VERSION), id);
+
+    if (client->resource == NULL) {
+        ds_err("tizen_appinfo : wl_resource_create() failed.");
+        free(client);
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    wl_resource_set_implementation(client->resource, &appinfo_impl, client,
+            _tizen_appinfo_client_handle_destroy);
+
+    wl_list_insert(&appinfo_mgr->clients, &client->link);
+}
diff --git a/src/launch/meson.build b/src/launch/meson.build
new file mode 100644 (file)
index 0000000..b3e2efd
--- /dev/null
@@ -0,0 +1,29 @@
+libds_tizen_launch_files = [
+  'appinfo.c',
+]
+
+libds_tizen_launch_deps = [
+  deps_libds_tizen,
+  dependency('tizen-launch-server', required: true),
+]
+
+lib_libds_tizen_launch = shared_library('ds-tizen-launch', libds_tizen_launch_files,
+  dependencies: libds_tizen_launch_deps,
+  include_directories: [ common_inc, include_directories('.'), include_directories('..') ],
+  version: meson.project_version(),
+  install: true
+)
+
+deps_libds_tizen_launch = declare_dependency(
+  link_with: lib_libds_tizen_launch,
+  dependencies: libds_tizen_launch_deps,
+  include_directories: [ common_inc, include_directories('.') ],
+)
+
+pkgconfig = import('pkgconfig')
+pkgconfig.generate(lib_libds_tizen_launch,
+  version: meson.project_version(),
+  filebase: 'libds-tizen-launch',
+  name: 'libds-tizen-launch',
+  description: 'tizen launch extension of libds-tizen for tizen platform',
+)
index 73c169c..3ea00d7 100644 (file)
@@ -35,3 +35,4 @@ subdir('input_devicemgr')
 subdir('dpms')
 subdir('indicator')
 subdir('clipboard')
+subdir('launch')
index eb8d221..4b4686d 100644 (file)
@@ -65,3 +65,22 @@ executable('libds-tizen-clipboard-tests',
   install_dir: libds_tizen_bindir,
   install : true
 )
+
+## appinfo tests
+tc_launch_appinfo_files = [
+  'tc_main.cpp',
+  'tc_launch_appinfo.cpp',
+]
+
+executable('libds-tizen-launch-appinfo-tests',
+  [
+    tc_mock_files,
+    tc_launch_appinfo_files
+  ],
+  dependencies: [
+    deps_test_common,
+    deps_libds_tizen_launch,
+  ],
+  install_dir: libds_tizen_bindir,
+  install : true
+)
diff --git a/tests/tc_launch_appinfo.cpp b/tests/tc_launch_appinfo.cpp
new file mode 100644 (file)
index 0000000..9e7bab1
--- /dev/null
@@ -0,0 +1,421 @@
+#include "tc_main.h"
+#include "mockclient.h"
+#include "mockcompositor.h"
+#include <libds-tizen/launch/appinfo.h>
+#include <tizen-launch-server-protocol.h>
+#include <tizen-launch-client-protocol.h>
+
+#define TIZEN_APPINFO_VERSION 1
+
+class MockAppinfoCompositor : public MockCompositor
+{
+public:
+    MockAppinfoCompositor()
+        : MockCompositor(&MockAppinfoCompositor::TestSetup, this)
+    {
+        ds_inf("%s : this(%p)", __func__, this);
+
+        // initialize the flags to check
+        bDestroyed = false;
+
+        bSetPid = false;
+        bSetAppid = false;
+        bMetadataReady = false;
+    }
+
+    ~MockAppinfoCompositor()
+    {
+        ds_inf("%s : this(%p)", __func__, this);
+    }
+
+    static void TestSetup(void *data)
+    {
+        MockAppinfoCompositor *mockComp =
+            static_cast<MockAppinfoCompositor *>(data);
+        Compositor *comp = mockComp->compositor;
+
+        ds_inf("%s: mockComp(%p)", __func__, mockComp);
+
+        mockComp->mAppinfoMgr = ds_tizen_appinfo_mgr_create(comp->display);
+
+        // destroy listener
+        mockComp->mDestroyListener.notify =
+            MockAppinfoCompositor::DestroyCallback;
+        mockComp->mDestroyListener.parent = mockComp;
+        ds_tizen_appinfo_mgr_add_destroy_listener(mockComp->mAppinfoMgr,
+            &mockComp->mDestroyListener);
+
+        // set_pid listener
+        mockComp->mSetPidListener.notify =
+            MockAppinfoCompositor::SetPidCallback;
+        mockComp->mSetPidListener.parent = mockComp;
+        ds_tizen_appinfo_mgr_add_set_pid_listener(mockComp->mAppinfoMgr,
+            &mockComp->mSetPidListener);
+
+        // set_appid listener
+        mockComp->mSetAppidListener.notify =
+            MockAppinfoCompositor::SetAppidCallback;
+        mockComp->mSetAppidListener.parent = mockComp;
+        ds_tizen_appinfo_mgr_add_set_appid_listener(mockComp->mAppinfoMgr,
+            &mockComp->mSetAppidListener);
+
+        // metadata_ready listener
+        mockComp->mMetadataReadyListener.notify =
+            MockAppinfoCompositor::MetadataReadyCallback;
+        mockComp->mMetadataReadyListener.parent = mockComp;
+        ds_tizen_appinfo_mgr_add_metadata_ready_listener(
+            mockComp->mAppinfoMgr,
+            &mockComp->mMetadataReadyListener);
+    }
+
+    static void DestroyCallback(struct wl_listener *listener, void *data)
+    {
+        ds_inf("%s", __func__);
+
+        MockAppinfoCompositor *mockComp =
+            reinterpret_cast<DestroyListener *>(listener)->parent;
+
+        mockComp->bDestroyed = true;
+    }
+
+    static void SetPidCallback(struct wl_listener *listener, void *data)
+    {
+        ds_inf("%s", __func__);
+
+        MockAppinfoCompositor *mockComp =
+            reinterpret_cast<SetPidListener *>(listener)->parent;
+        struct ds_tizen_appinfo *info = static_cast<struct ds_tizen_appinfo *>(data);
+
+        ds_inf("%s: mockComp(%p), appinfo(%p)", __func__, mockComp, info);
+
+        mockComp->bSetPid = true;
+    }
+
+    static void SetAppidCallback(struct wl_listener *listener, void *data)
+    {
+        ds_inf("%s", __func__);
+
+        MockAppinfoCompositor *mockComp =
+            reinterpret_cast<SetAppidListener *>(listener)->parent;
+        struct ds_tizen_appinfo *info = static_cast<struct ds_tizen_appinfo *>(data);
+
+        ds_inf("%s: mockComp(%p), appinfo(%p)", __func__, mockComp, info);
+
+        mockComp->bSetAppid = true;
+    }
+
+
+    static void MetadataReadyCallback(struct wl_listener *listener, void *data)
+    {
+        ds_inf("%s", __func__);
+
+        MockAppinfoCompositor *mockComp =
+            reinterpret_cast<MetadataReadyListener *>(listener)->parent;
+        struct ds_tizen_appinfo *info = static_cast<struct ds_tizen_appinfo *>(data);
+
+        ds_inf("%s: mockComp(%p), appinfo(%p)", __func__, mockComp, info);
+
+        mockComp->bMetadataReady = true;
+    }
+
+    void SendBaseOutputResolutionDone(uint32_t pid, uint32_t width, uint32_t height)
+    {
+        ds_inf("%s", __func__);
+
+        wl_resource *res_appinfo = ds_tizen_appinfo_mgr_get_appinfo_resource(mAppinfoMgr);
+
+        tizen_launch_appinfo_send_base_output_resolution_done(res_appinfo, pid, width, height);
+    }
+
+public:
+    bool bDestroyed;
+    bool bSetPid;
+    bool bSetAppid;
+    bool bMetadataReady;
+
+private:
+    struct ds_tizen_appinfo_mgr *mAppinfoMgr;
+    struct DestroyListener: ::wl_listener {
+        MockAppinfoCompositor *parent;
+    };
+    DestroyListener mDestroyListener;
+    struct SetPidListener: ::wl_listener {
+        MockAppinfoCompositor *parent;
+    };
+    SetPidListener mSetPidListener;
+    struct SetAppidListener: ::wl_listener {
+        MockAppinfoCompositor *parent;
+    };
+    SetAppidListener mSetAppidListener;
+    struct MetadataReadyListener: ::wl_listener {
+        MockAppinfoCompositor *parent;
+    };
+    MetadataReadyListener mMetadataReadyListener;
+};
+
+class MockAppinfoClient : public MockClient
+{
+public:
+    MockAppinfoClient()
+        : bBaseOutputResolutionDone(false),
+          mBaseOutputResolutionWidth(0),
+          mBaseOutputResolutionHeight(0),
+          compositor_res(nullptr),
+          tizen_launch_appinfo(nullptr)
+    {}
+    MockAppinfoClient(const struct wl_registry_listener *listener)
+        : MockClient(listener, this)
+    {
+        ds_inf("%s", __func__);
+
+        bBaseOutputResolutionDone = false;
+        mBaseOutputResolutionWidth = 0;
+        mBaseOutputResolutionHeight = 0;
+    }
+    ~MockAppinfoClient()
+    {
+        ds_inf("%s", __func__);
+    }
+
+    void SetWlCompositor(struct wl_compositor *global_res)
+    {
+        ds_inf("%s", __func__);
+
+        compositor_res = global_res;
+    }
+
+    struct wl_compositor *GetWlCompositor()
+    {
+        ds_inf("%s", __func__);
+
+        return compositor_res;
+    }
+
+    void SetTizenAppinfo(struct tizen_launch_appinfo *global_res)
+    {
+        ds_inf("%s", __func__);
+        tizen_launch_appinfo = global_res;
+    }
+
+    struct tizen_launch_appinfo *GetTizenAppinfo()
+    {
+        ds_inf("%s", __func__);
+
+        return tizen_launch_appinfo;
+    }
+
+public:
+    bool bBaseOutputResolutionDone;
+    uint32_t mBaseOutputResolutionWidth;
+    uint32_t mBaseOutputResolutionHeight;
+
+private:
+    struct wl_compositor *compositor_res;
+    struct tizen_launch_appinfo *tizen_launch_appinfo;
+};
+
+static void
+client_tizen_appinfo_cb_base_output_resolution_done(void *data,
+    struct tizen_launch_appinfo *appinfo, uint32_t pid,
+    uint32_t width, uint32_t height)
+{
+    ds_inf("%s", __func__);
+
+    MockAppinfoClient *client = static_cast<MockAppinfoClient *>(data);
+
+    client->bBaseOutputResolutionDone = true;
+    client->mBaseOutputResolutionWidth = width;
+    client->mBaseOutputResolutionHeight = height;
+}
+
+static const struct tizen_launch_appinfo_listener appinfo_cb_listener = {
+    .base_output_resolution_done = client_tizen_appinfo_cb_base_output_resolution_done,
+};
+
+static void
+client_registry_cb_global(void *data, struct wl_registry *registry,
+    uint32_t name, const char *interface, uint32_t version)
+{
+    ds_inf("%s", __func__);
+
+    MockAppinfoClient *client = static_cast<MockAppinfoClient *>(data);
+    struct wl_compositor *compositor_res;
+    struct tizen_launch_appinfo *tizen_launch_appinfo;
+
+    if (!strcmp(interface, "wl_compositor")) {
+        compositor_res = (struct wl_compositor *)wl_registry_bind(registry,
+            name, &wl_compositor_interface, 1);
+        if (compositor_res == nullptr) {
+            ds_err("wl_registry_bind() failed. wl_compositor resource.");
+            return;
+        }
+        client->SetWlCompositor(compositor_res);
+    } else if (!strcmp(interface, "tizen_launch_appinfo")) {
+        tizen_launch_appinfo = (struct tizen_launch_appinfo *)wl_registry_bind(registry,
+            name, &tizen_launch_appinfo_interface, TIZEN_APPINFO_VERSION);
+        if (tizen_launch_appinfo == nullptr) {
+            ds_err("wl_registry_bind() failed. tizen_launch_appinfo resource.");
+            return;
+        }
+        client->SetTizenAppinfo(tizen_launch_appinfo);
+
+        tizen_launch_appinfo_add_listener(tizen_launch_appinfo, &appinfo_cb_listener,
+            client);
+    }
+}
+
+static void
+client_registry_cb_global_remove(void *data, struct wl_registry *registry,
+    uint32_t name)
+{
+    ds_inf("%s", __func__);
+
+    MockAppinfoClient *client = static_cast<MockAppinfoClient *>(data);
+    struct wl_compositor *compositor_res = client->GetWlCompositor();
+    struct tizen_launch_appinfo *appinfo_res = client->GetTizenAppinfo();
+
+    tizen_launch_appinfo_destroy(appinfo_res);
+    wl_compositor_destroy(compositor_res);
+}
+
+static const struct wl_registry_listener registry_listener = {
+    .global = client_registry_cb_global,
+    .global_remove = client_registry_cb_global_remove
+};
+
+class AppinfoTest : public ::testing::Test
+{
+public:
+    void SetUp(void) override;
+    void TearDown(void) override;
+
+    MockAppinfoCompositor *comp;
+    MockAppinfoClient *client;
+    struct wl_compositor *compositor_res;
+    struct tizen_launch_appinfo *appinfo_res;
+};
+
+void
+AppinfoTest::SetUp(void)
+{
+    ds_inf("%s", __func__);
+
+    comp = new MockAppinfoCompositor();
+    client = new MockAppinfoClient(&registry_listener);
+    compositor_res = client->GetWlCompositor();
+    appinfo_res = client->GetTizenAppinfo();
+
+    client->RoundTrip();
+}
+
+void
+AppinfoTest::TearDown(void)
+{
+    ds_inf("%s", __func__);
+
+    client->RoundTrip();
+
+    delete client;
+    delete comp;
+}
+
+TEST_F(AppinfoTest, Create_P)
+{
+    EXPECT_TRUE(true);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoRegisterPid)
+{
+    uint32_t pid = 1234;
+
+    tizen_launch_appinfo_register_pid(appinfo_res, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetPid);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoSetAppid)
+{
+    uint32_t pid = 1234;
+    const char *appid = "org.tizen.libds-tizen-appinfo-test";
+
+    tizen_launch_appinfo_register_pid(appinfo_res, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetPid);
+
+    tizen_launch_appinfo_set_appid(appinfo_res, pid, appid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetAppid);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoRegisterAppid)
+{
+    const char *appid = "org.tizen.libds-tizen-appinfo-test";
+
+    tizen_launch_appinfo_register_appid(appinfo_res, appid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetAppid);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoSetPid)
+{
+    uint32_t pid = 1234;
+    const char *appid = "org.tizen.libds-tizen-appinfo-test";
+
+    tizen_launch_appinfo_register_appid(appinfo_res, appid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetAppid);
+
+    tizen_launch_appinfo_set_pid(appinfo_res, appid, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetPid);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoMetadataReady)
+{
+    const char *appid = "org.tizen.libds-tizen-appinfo-test";
+    uint32_t pid = 1234;
+
+    tizen_launch_appinfo_register_appid(appinfo_res, appid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetAppid);
+
+    tizen_launch_appinfo_ready_metadata(appinfo_res, appid, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bMetadataReady);
+}
+
+TEST_F(AppinfoTest, Req_TizenAppinfoGetBaseOutputResolution)
+{
+    uint32_t pid = 1234;
+
+    tizen_launch_appinfo_register_pid(appinfo_res, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetPid);
+
+    tizen_launch_appinfo_get_base_output_resolution(appinfo_res, pid);
+    client->RoundTrip();
+
+    EXPECT_TRUE(client->bBaseOutputResolutionDone);
+    EXPECT_TRUE(client->mBaseOutputResolutionWidth == 1080); //default value
+    EXPECT_TRUE(client->mBaseOutputResolutionHeight == 1920); // default value
+}
+
+TEST_F(AppinfoTest, Ev_TizenAppinfoBaseOutputResolutionDone)
+{
+    uint32_t pid = 1234, width = 1920, height = 1080;
+
+    tizen_launch_appinfo_register_pid(appinfo_res, pid);
+    client->RoundTrip();
+    EXPECT_TRUE(comp->bSetPid);
+
+    tizen_launch_appinfo_get_base_output_resolution(appinfo_res, pid);
+    client->RoundTrip();
+
+    comp->SendBaseOutputResolutionDone(pid, width, height);
+    comp->Process();
+
+    client->RoundTrip();
+    EXPECT_TRUE(client->bBaseOutputResolutionDone);
+    EXPECT_TRUE(client->mBaseOutputResolutionWidth == 1920);
+    EXPECT_TRUE(client->mBaseOutputResolutionHeight == 1080);
+}