From 8c8a08f2a79bbd614f47da139fcd2e31637248e2 Mon Sep 17 00:00:00 2001 From: "duna.oh" Date: Fri, 22 Jul 2022 02:41:29 +0900 Subject: [PATCH] launch: implement appinfo interface Change-Id: I6afd36726e16ed967bffc6f9b24c772c1740bab8 --- include/libds-tizen/launch/appinfo.h | 42 +++ packaging/libds-tizen.spec | 32 ++ src/launch/appinfo.c | 579 +++++++++++++++++++++++++++++++++++ src/launch/meson.build | 29 ++ src/meson.build | 1 + tests/meson.build | 19 ++ tests/tc_launch_appinfo.cpp | 421 +++++++++++++++++++++++++ 7 files changed, 1123 insertions(+) create mode 100644 include/libds-tizen/launch/appinfo.h create mode 100644 src/launch/appinfo.c create mode 100644 src/launch/meson.build create mode 100644 tests/tc_launch_appinfo.cpp diff --git a/include/libds-tizen/launch/appinfo.h b/include/libds-tizen/launch/appinfo.h new file mode 100644 index 0000000..bd62e9b --- /dev/null +++ b/include/libds-tizen/launch/appinfo.h @@ -0,0 +1,42 @@ +#ifndef LIBDS_TIZEN_APPINFO_H +#define LIBDS_TIZEN_APPINFO_H + +#include +#include + +#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 diff --git a/packaging/libds-tizen.spec b/packaging/libds-tizen.spec index 16e6ce7..27af91c 100644 --- a/packaging/libds-tizen.spec +++ b/packaging/libds-tizen.spec @@ -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 index 0000000..0b6c8c2 --- /dev/null +++ b/src/launch/appinfo.c @@ -0,0 +1,579 @@ +#include +#include +#include +#include + +#include "util.h" +#include + +#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 index 0000000..b3e2efd --- /dev/null +++ b/src/launch/meson.build @@ -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', +) diff --git a/src/meson.build b/src/meson.build index 73c169c..3ea00d7 100644 --- a/src/meson.build +++ b/src/meson.build @@ -35,3 +35,4 @@ subdir('input_devicemgr') subdir('dpms') subdir('indicator') subdir('clipboard') +subdir('launch') diff --git a/tests/meson.build b/tests/meson.build index eb8d221..4b4686d 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -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 index 0000000..9e7bab1 --- /dev/null +++ b/tests/tc_launch_appinfo.cpp @@ -0,0 +1,421 @@ +#include "tc_main.h" +#include "mockclient.h" +#include "mockcompositor.h" +#include +#include +#include + +#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(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(listener)->parent; + + mockComp->bDestroyed = true; + } + + static void SetPidCallback(struct wl_listener *listener, void *data) + { + ds_inf("%s", __func__); + + MockAppinfoCompositor *mockComp = + reinterpret_cast(listener)->parent; + struct ds_tizen_appinfo *info = static_cast(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(listener)->parent; + struct ds_tizen_appinfo *info = static_cast(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(listener)->parent; + struct ds_tizen_appinfo *info = static_cast(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(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(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(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(®istry_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); +} -- 2.7.4