#include "e.h"
#include "e_policy_appinfo.h"
-Eina_List *appinfo_list;
+static Eina_List *appinfo_list;
+
+static int _appinfo_hooks_walking = 0;
+static int _appinfo_hooks_delete = 0;
+
+static Eina_Inlist *_appinfo_hooks[] =
+{
+ [E_POLICY_APPINFO_HOOK_APPID_SET] = NULL,
+ [E_POLICY_APPINFO_HOOK_PID_SET] = NULL,
+ [E_POLICY_APPINFO_HOOK_METADATA_READY] = NULL,
+};
struct _E_Policy_Appinfo
{
int base_output_height;
};
+static void
+_e_policy_appinfo_hooks_clean(void)
+{
+ Eina_Inlist *l;
+ E_Policy_Appinfo_Hook *hook;
+ unsigned int x;
+
+ for (x = 0; x < E_POLICY_APPINFO_HOOK_LAST; x++)
+ EINA_INLIST_FOREACH_SAFE(_appinfo_hooks[x], l, hook)
+ {
+ if (!hook->delete_me) continue;
+ _appinfo_hooks[x] = eina_inlist_remove(_appinfo_hooks[x], EINA_INLIST_GET(hook));
+ free(hook);
+ }
+}
+
+static void
+_e_policy_appinfo_hook_call(E_Policy_Appinfo_Hook_Point hookpoint, const char* appid, pid_t pid)
+{
+ E_Policy_Appinfo_Hook *hook;
+
+ _appinfo_hooks_walking++;
+ EINA_INLIST_FOREACH(_appinfo_hooks[hookpoint], hook)
+ {
+ if (hook->delete_me) continue;
+ hook->func(appid, pid, hook->data);
+ }
+ _appinfo_hooks_walking--;
+ if ((_appinfo_hooks_walking == 0) && (_appinfo_hooks_delete) > 0)
+ _e_policy_appinfo_hooks_clean();
+}
+
+
EINTERN E_Policy_Appinfo *
e_policy_appinfo_new(void)
{
epai = E_NEW(E_Policy_Appinfo, 1);
EINA_SAFETY_ON_NULL_RETURN_VAL(epai, NULL);
+ epai->pid = -1;
+ epai->appid = NULL;
+
appinfo_list = eina_list_append(appinfo_list, epai);
ELOGF("POL_APPINFO", "appinfo(%p) create", NULL, epai);
ELOGF("POL_APPINFO", "appinfo(%p) set pid(%u)", NULL, epai, pid);
+ _e_policy_appinfo_hook_call(E_POLICY_APPINFO_HOOK_PID_SET, epai->appid, pid);
+
return EINA_TRUE;
}
ELOGF("POL_APPINFO", "appinfo(%p) set appid(%s)", NULL, epai, appid);
+ _e_policy_appinfo_hook_call(E_POLICY_APPINFO_HOOK_PID_SET, epai->appid, epai->pid);
+
return EINA_TRUE;
}
+EINTERN void
+e_policy_appinfo_ready_metadata(E_Policy_Appinfo *epai, pid_t pid)
+{
+ EINA_SAFETY_ON_NULL_RETURN(epai);
+ EINA_SAFETY_ON_TRUE_RETURN(pid < 0);
+
+ if (epai->pid != pid)
+ e_policy_appinfo_pid_set(epai, pid);
+
+ _e_policy_appinfo_hook_call(E_POLICY_APPINFO_HOOK_METADATA_READY, epai->appid, epai->pid);
+}
+
EINTERN Eina_Bool
e_policy_appinfo_base_output_resolution_get(E_Policy_Appinfo *epai, int *width, int *height)
{
E_Policy_Appinfo *epai = NULL;
Eina_List *l = NULL;
- EINA_SAFETY_ON_TRUE_RETURN_VAL(pid <= 0, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(pid <= 0, NULL);
EINA_LIST_FOREACH(appinfo_list, l, epai)
{
return NULL;
}
+E_API E_Policy_Appinfo *
+e_policy_appinfo_find_with_appid(const char *appid)
+{
+ E_Policy_Appinfo *epai = NULL;
+ Eina_List *l = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(appid, NULL);
+
+ EINA_LIST_FOREACH(appinfo_list, l, epai)
+ {
+ if (!e_util_strcmp(epai->appid, appid))
+ return epai;
+ }
+
+ return NULL;
+}
+
E_API Eina_Bool
e_policy_appinfo_base_output_resolution_set(E_Policy_Appinfo *epai, int width, int height)
{
return EINA_TRUE;
}
+
+E_API E_Policy_Appinfo_Hook *
+e_policy_appinfo_hook_add(E_Policy_Appinfo_Hook_Point hookpoint, E_Policy_Appinfo_Hook_Cb cb, const void *data)
+{
+ E_Policy_Appinfo_Hook *hook;
+
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint < 0, NULL);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_POLICY_APPINFO_HOOK_LAST, NULL);
+
+ hook = E_NEW(E_Policy_Appinfo_Hook, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(hook, NULL);
+
+ hook->hookpoint = hookpoint;
+ hook->func = cb;
+ hook->data = (void*)data;
+
+ _appinfo_hooks[hookpoint] = eina_inlist_append(_appinfo_hooks[hookpoint], EINA_INLIST_GET(hook));
+
+ return hook;
+}
+
+E_API void
+e_policy_appinfo_hook_del(E_Policy_Appinfo_Hook *hook)
+{
+ EINA_SAFETY_ON_NULL_RETURN(hook);
+
+ hook->delete_me = 1;
+ if (_appinfo_hooks_walking == 0)
+ {
+ _appinfo_hooks[hook->hookpoint] = eina_inlist_remove(_appinfo_hooks[hook->hookpoint], EINA_INLIST_GET(hook));
+ free(hook);
+ }
+ else
+ _appinfo_hooks_delete++;
+}
+#ifdef E_TYPEDEFS
typedef struct _E_Policy_Appinfo E_Policy_Appinfo;
+#else
+# ifndef E_POLICY_APPINFO_H
+# define E_POLICY_APPINFO_H
+typedef struct _E_Policy_Appinfo_Hook E_Policy_Appinfo_Hook;
-EINTERN E_Policy_Appinfo *e_policy_appinfo_new(void);
-EINTERN void e_policy_appinfo_del(E_Policy_Appinfo *epai);
-EINTERN Eina_Bool e_policy_appinfo_pid_set(E_Policy_Appinfo *epai, pid_t pid);
-EINTERN Eina_Bool e_policy_appinfo_appid_set(E_Policy_Appinfo *epai, const char *appid);
-EINTERN Eina_Bool e_policy_appinfo_base_output_resolution_get(E_Policy_Appinfo *epai, int *width, int *height);
+typedef enum _E_Policy_Appinfo_Hook_Point
+{
+ E_POLICY_APPINFO_HOOK_APPID_SET,
+ E_POLICY_APPINFO_HOOK_PID_SET,
+ E_POLICY_APPINFO_HOOK_METADATA_READY,
+ E_POLICY_APPINFO_HOOK_LAST,
+} E_Policy_Appinfo_Hook_Point;
-E_API E_Policy_Appinfo *e_policy_appinfo_find_with_pid(pid_t pid);
-E_API Eina_Bool e_policy_appinfo_base_output_resolution_set(E_Policy_Appinfo *epai, int width, int height);
+typedef void (*E_Policy_Appinfo_Hook_Cb)(const char *appid, pid_t pid, void *data);
+struct _E_Policy_Appinfo_Hook
+{
+ EINA_INLIST;
+ E_Policy_Appinfo_Hook_Point hookpoint;
+ E_Policy_Appinfo_Hook_Cb func;
+ void *data;
+ unsigned char delete_me : 1;
+};
+EINTERN E_Policy_Appinfo *e_policy_appinfo_new(void);
+EINTERN void e_policy_appinfo_del(E_Policy_Appinfo *epai);
+EINTERN Eina_Bool e_policy_appinfo_pid_set(E_Policy_Appinfo *epai, pid_t pid);
+EINTERN Eina_Bool e_policy_appinfo_appid_set(E_Policy_Appinfo *epai, const char *appid);
+EINTERN void e_policy_appinfo_ready_metadata(E_Policy_Appinfo *epai, pid_t pid);
+EINTERN Eina_Bool e_policy_appinfo_base_output_resolution_get(E_Policy_Appinfo *epai, int *width, int *height);
+
+E_API E_Policy_Appinfo *e_policy_appinfo_find_with_pid(pid_t pid);
+E_API E_Policy_Appinfo *e_policy_appinfo_find_with_appid(const char *appid);
+E_API Eina_Bool e_policy_appinfo_base_output_resolution_set(E_Policy_Appinfo *epai, int width, int height);
+
+E_API E_Policy_Appinfo_Hook *e_policy_appinfo_hook_add(E_Policy_Appinfo_Hook_Point point, E_Policy_Appinfo_Hook_Cb cb, const void *data);
+E_API void e_policy_appinfo_hook_del(E_Policy_Appinfo_Hook *hook);
+# endif
+#endif
return;
}
+static void
+_tzlaunch_appinfo_iface_cb_register_appid(struct wl_client *client, struct wl_resource *res_tzlaunch_appinfo,
+ const char *appid)
+{
+ E_Policy_Wl_Tzlaunch_Appinfo *appinfo = NULL;
+ E_Policy_Appinfo *epai = NULL;
+
+ appinfo = wl_resource_get_user_data(res_tzlaunch_appinfo);
+ if (!appinfo)
+ {
+ wl_resource_post_error(res_tzlaunch_appinfo,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid tzlaunch_appinfo's user data");
+ return;
+ }
+
+ if ((epai = e_policy_appinfo_find_with_appid(appid)))
+ {
+ ELOGF("TZ_APPINFO", "appid:%s is already registered!", NULL, appid);
+ return;
+ }
+
+ epai = e_policy_appinfo_new();
+ EINA_SAFETY_ON_NULL_RETURN(epai);
+
+ if (!e_policy_appinfo_appid_set(epai, appid))
+ {
+ ELOGF("TZ_APPINFO", "Failed to register appid:%s", NULL, appid);
+ e_policy_appinfo_del(epai);
+ return;
+ }
+}
+
+static void
+_tzlaunch_appinfo_iface_cb_deregister_appid(struct wl_client *client, struct wl_resource *res_tzlaunch_appinfo,
+ const char *appid)
+{
+ E_Policy_Wl_Tzlaunch_Appinfo *appinfo = NULL;
+ E_Policy_Appinfo *epai = NULL;
+
+ appinfo = wl_resource_get_user_data(res_tzlaunch_appinfo);
+ if (!appinfo)
+ {
+ wl_resource_post_error(res_tzlaunch_appinfo,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid tzlaunch_appinfo's user data");
+ return;
+ }
+
+ epai = e_policy_appinfo_find_with_appid(appid);
+ EINA_SAFETY_ON_NULL_RETURN(epai);
+
+ e_policy_appinfo_del(epai);
+}
+
+static void
+_tzlaunch_appinfo_iface_cb_set_pid(struct wl_client *client, struct wl_resource *res_tzlaunch_appinfo,
+ const char *appid, uint32_t pid)
+{
+ E_Policy_Wl_Tzlaunch_Appinfo *appinfo = NULL;
+ E_Policy_Appinfo *epai = NULL;
+
+ appinfo = wl_resource_get_user_data(res_tzlaunch_appinfo);
+ if (!appinfo)
+ {
+ wl_resource_post_error(res_tzlaunch_appinfo,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid tzlaunch_appinfo's user data");
+ return;
+ }
+
+ epai = e_policy_appinfo_find_with_appid(appid);
+ EINA_SAFETY_ON_NULL_RETURN(epai);
+
+ if (!e_policy_appinfo_pid_set(epai, pid))
+ {
+ ELOGF("TZ_APPINFO", "Failed to set pid:%u for appid:%s", NULL, pid, appid);
+ return;
+ }
+}
+
+static void
+_tzlaunch_appinfo_iface_cb_ready_metadata(struct wl_client *client, struct wl_resource *res_tzlaunch_appinfo,
+ const char *appid, uint32_t pid)
+{
+ E_Policy_Wl_Tzlaunch_Appinfo *appinfo = NULL;
+ E_Policy_Appinfo *epai = NULL;
+ int width = 0, height = 0;
+
+ appinfo = wl_resource_get_user_data(res_tzlaunch_appinfo);
+ if (!appinfo)
+ {
+ wl_resource_post_error(res_tzlaunch_appinfo,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "Invalid tzlaunch_appinfo's user data");
+ return;
+ }
+
+ epai = e_policy_appinfo_find_with_appid(appid);
+ EINA_SAFETY_ON_NULL_RETURN(epai);
+
+ e_policy_appinfo_ready_metadata(epai, pid);
+
+ /* about base output resolution */
+
+ // 1. send HOOK with pid
+ _e_policy_wl_hook_call(E_POLICY_WL_HOOK_BASE_OUTPUT_RESOLUTION_GET, pid);
+ // 2. module must set the base_output_resolution.
+ if (!e_policy_appinfo_base_output_resolution_get(epai, &width, &height))
+ {
+ ELOGF("TZ_APPINFO", "failed to set base_output_resolution in module, pid:%u, appid:%s", NULL, pid, appid);
+ return;
+ }
+ // 3. server has to get the base_screern_resolution via e_policy_appinfo_base_output_resolution_get.
+ // 3-1. if success, use the base_rescreen_resolution
+ // 3-2. if fail, get the base_output_resolution from the E_Comp_Wl_Output.
+
+ // 4. send output.
+ if (!e_comp_wl_pid_output_configured_resolution_send(pid, width, height))
+ {
+ ELOGF("TZ_APPINFO", "failed to send output_configured_resolution, pid:%u, appid:%s", NULL, pid, appid);
+ return;
+ }
+}
+
static const struct tizen_launch_appinfo_interface _tzlaunch_appinfo_iface =
{
_tzlaunch_appinfo_iface_cb_destroy,
_tzlaunch_appinfo_iface_cb_deregister_pid,
_tzlaunch_appinfo_iface_cb_set_appid,
_tzlaunch_appinfo_iface_cb_get_base_output_resolution,
+ _tzlaunch_appinfo_iface_cb_register_appid,
+ _tzlaunch_appinfo_iface_cb_deregister_appid,
+ _tzlaunch_appinfo_iface_cb_set_pid,
+ _tzlaunch_appinfo_iface_cb_ready_metadata,
};
static void