Modify manual render 16/209216/8
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 3 Jul 2019 10:47:14 +0000 (19:47 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 5 Jul 2019 02:29:08 +0000 (11:29 +0900)
When the consumer gets the launch request from another application,
the consumer should start the rendering manually to solve a problem
that the hands of the clock do not move.
After calling the elm_win_norender_push() function, the watch-control
sends a resume request to the provider. When getting the updated image
in the screen-connector callback function, the manual render is stopped.

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/209214/

Change-Id: I929690a89103397cf65a400f62c9314497188c76
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
watch-control/CMakeLists.txt
watch-control/src/control.c [changed mode: 0755->0644]
watch-control/src/watch_control_private.h [new file with mode: 0644]
watch-control/src/watch_control_signal.c [new file with mode: 0644]
watch-control/src/watch_control_signal.h [new file with mode: 0644]

index 83bbe71..542b3da 100644 (file)
@@ -19,9 +19,7 @@ pkg_check_modules(watch-control REQUIRED
        screen_connector_watcher_evas
 )
 
-SET(BUILD_SOURCE
-       src/control.c
-)
+AUX_SOURCE_DIRECTORY(src BUILD_SOURCE)
 
 FOREACH(flag ${watch-control_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
old mode 100755 (executable)
new mode 100644 (file)
index 183c283..8d541a4
 #include <aul_screen_connector.h>
 #include <Ecore_Wl2.h>
 #include <gio/gio.h>
+#include <aul_watch_control.h>
 
-#define API __attribute__((visibility("default")))
-
-#undef LOG_TAG
-#define LOG_TAG "WATCH_CONTROL"
-
-#ifndef _E
-#define _E LOGE
-#endif
-
-#ifndef _D
-#define _D LOGD
-#endif
-
-#ifndef _W
-#define _W LOGW
-#endif
+#include "watch_control_signal.h"
+#include "watch_control_private.h"
 
 #define KEY_SCREEN_SHAPE_CIRCLE "http://tizen.org/feature/screen.shape.circle"
-#define DEVICED_PATH_DISPLAY           "/Org/Tizen/System/DeviceD/Display"
-#define DEVICED_INTERFACE_DISPLAY      "org.tizen.system.deviced.display"
 
 static int __watch_viewer_initialized = 0;
 static int __watch_size_policy = WATCH_POLICY_HINT_EXPAND;
@@ -69,11 +54,8 @@ static char *viewer_appid;
 static int __is_dead_signal_connected;
 static aul_app_com_connection_h __conn_dead_signal;
 static unsigned int __watch_rid;
-static bool __manual_render;
-static guint __manual_render_timer;
-static bool __is_bound = false;
+static bool __is_bound;
 static int __viewer_visibility = AUL_SCREEN_STATUS_PAUSE;
-static Ecore_Event_Handler *__pre_visibility;
 
 struct toolkit_info_s {
        char *appid;
@@ -87,16 +69,250 @@ struct dead_cb_s {
        void *data;
 };
 
+struct manual_render_s {
+       aul_watch_control_h control_handle;
+       lcd_signal_h signal_handle;
+       Ecore_Event_Handler *pre_visibility;
+       Ecore_Event_Handler *visibility;
+       guint timer;
+       bool enabled;
+       bool started;
+       bool lcd_on;
+};
+
 static bool __is_pended;
 static int __change_viewer_visibility(int visibility, bool update_cur_state);
 static int __change_visibility(int visibility);
 static aul_app_com_connection_h __conn_launch_signal;
+static struct manual_render_s __manual_render;
 
 static int __listen_launch_signal(void);
 static void __ignore_launch_signal(void);
 static void __set_viewer_appid(void);
 static void __manual_render_start(void);
-static void __manual_render_finish(void);
+static void __manual_render_stop(void);
+
+static bool __watch_is_visible(void)
+{
+       Evas_Object *image;
+       bool is_visible = false;
+
+       image = evas_object_data_get(__win, "tbm,watch");
+       if (!image)
+               return false;
+
+       screen_connector_toolkit_evas_is_visible(image, &is_visible);
+
+       return is_visible;
+}
+
+static gboolean __manual_render_timeout_cb(gpointer data)
+{
+       _W("Manual render timeout expired");
+       watch_manager_pause();
+       watch_manager_notify_paused_status_of_viewer();
+       __manual_render.timer = 0;
+       __manual_render_stop();
+
+       return G_SOURCE_REMOVE;
+}
+
+static void __manual_render_set_timer(void)
+{
+       if (__manual_render.timer)
+               return;
+
+       __manual_render.timer = g_timeout_add(200, __manual_render_timeout_cb,
+                       NULL);
+}
+
+static void __manual_render_unset_timer(void)
+{
+       if (!__manual_render.timer)
+               return;
+
+       g_source_remove(__manual_render.timer);
+       __manual_render.timer = 0;
+}
+
+static void __manual_render_start(void)
+{
+       if (!__watch_is_visible()) {
+               _W("Watch is not visible. Skip manual render");
+               return;
+       }
+
+       __manual_render.enabled = true;
+
+       if (__is_bound) {
+               _W("Watch is bound cannot manual render just call tick");
+               __change_viewer_visibility(AUL_SCREEN_STATUS_PRE_RESUME, false);
+               watch_manager_resume();
+               return;
+       }
+
+       if (__manual_render.started) {
+               _W("Manual render is already started");
+               return;
+       }
+
+       elm_win_norender_push(__win);
+       watch_manager_notify_resumed_status_of_viewer();
+       watch_manager_resume();
+       __manual_render_set_timer();
+       __manual_render.started = true;
+}
+
+static void __manual_render_stop(void)
+{
+       if (!__manual_render.started)
+               return;
+
+       elm_win_norender_pop(__win);
+       _I("Set manual false");
+
+       __manual_render.started = false;
+       __manual_render_unset_timer();
+}
+
+static void __aul_watch_control_cb(bundle *b, void *user_data)
+{
+       if (!__watch_is_visible() || !__manual_render.lcd_on) {
+               __manual_render.enabled = false;
+               return;
+       }
+
+       __manual_render_start();
+}
+
+static void __obj_move_cb(void *data, Evas *e, Evas_Object *obj,
+               void *event_info)
+{
+       if (!__manual_render.enabled)
+               return;
+
+       if (!__watch_is_visible() || !__manual_render.lcd_on)
+               return;
+
+       __manual_render_start();
+}
+
+static void __lcd_signal_cb(bool lcd_on, void *user_data)
+{
+       _D("LCD status is changed to %s", lcd_on ? "on" : "off");
+       __manual_render.lcd_on = lcd_on;
+}
+
+static Eina_Bool __window_on_pre_visibility(void *data, int type, void *event)
+{
+        Ecore_Wl2_Event_Window_Pre_Visibility_Change *ev = event;
+       Ecore_Evas *ee;
+       Ecore_Wl2_Window *wl_win;
+       int win_id;
+
+        if (!ev)
+                return ECORE_CALLBACK_RENEW;
+
+       ee = ecore_evas_ecore_evas_get(evas_object_evas_get(__win));
+       if (!ee)
+               return ECORE_CALLBACK_RENEW;
+
+       wl_win = ecore_evas_wayland2_window_get(ee);
+       if (!wl_win)
+               return ECORE_CALLBACK_RENEW;
+
+       win_id = ecore_wl2_window_id_get(wl_win);
+       if (ev->win != win_id)
+               return ECORE_CALLBACK_RENEW;
+
+        if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
+                __manual_render_start();
+                LOGD("[__WINDOW_PRE_VISIBILITY_CHANGE__] win_id(%d)", ev->win);
+        }
+
+        return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool __window_on_visibility(void *data, int type, void *event)
+{
+        Ecore_Wl2_Event_Window_Visibility_Change *ev = event;
+       Ecore_Evas *ee;
+       Ecore_Wl2_Window *wl_win;
+       int win_id;
+
+        if (!ev)
+               return ECORE_CALLBACK_RENEW;
+
+       ee = ecore_evas_ecore_evas_get(evas_object_evas_get(__win));
+       if (!ee)
+               return ECORE_CALLBACK_RENEW;
+
+       wl_win = ecore_evas_wayland2_window_get(ee);
+       if (!wl_win)
+               return ECORE_CALLBACK_RENEW;
+
+       win_id = ecore_wl2_window_id_get(wl_win);
+       if (ev->win != win_id)
+               return ECORE_CALLBACK_RENEW;
+
+        if (!ev->fully_obscured) {
+                LOGD("[__WINDOW_VISIBILITY_CHANGE__] win_id(%d)", ev->win);
+                __manual_render_unset_timer();
+        }
+
+        return ECORE_CALLBACK_RENEW;
+}
+
+static int __manual_render_init(void)
+{
+       int ret;
+
+       ret = aul_watch_control_add_handler(__aul_watch_control_cb, NULL,
+                       &__manual_render.control_handle);
+       if (ret < 0) {
+               _E("Failed to add aul watch control handler");
+               return -1;
+       }
+
+       ret = watch_control_signal_add_lcd_signal_handler(__lcd_signal_cb,
+                       NULL, &__manual_render.signal_handle);
+       if (ret < 0) {
+               _E("Failed to add lcd signal handler");
+               return -1;
+       }
+
+       __manual_render.pre_visibility = ecore_event_handler_add(
+                       ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
+                       __window_on_pre_visibility, NULL);
+       if (!__manual_render.pre_visibility)
+               _W("Failed to add pre visibility change handler");
+
+       __manual_render.visibility = ecore_event_handler_add(
+                       ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE,
+                       __window_on_visibility, NULL);
+       if (!__manual_render.visibility)
+               _W("Failed to add visibility change handler");
+
+       return 0;
+}
+
+static void __manual_render_fini(void)
+{
+       __manual_render_stop();
+
+       ecore_event_handler_del(__manual_render.visibility);
+       __manual_render.visibility = NULL;
+
+       ecore_event_handler_del(__manual_render.pre_visibility);
+       __manual_render.pre_visibility = NULL;
+
+       watch_control_signal_remove_lcd_signal_handler(
+                       __manual_render.signal_handle);
+       __manual_render.signal_handle = NULL;
+
+       aul_watch_control_remove_handler(__manual_render.control_handle);
+       __manual_render.control_handle = NULL;
+}
 
 static void __destroy_toolkit_info(gpointer data)
 {
@@ -207,104 +423,6 @@ static void __win_resized(void *data, Evas *e, Evas_Object *obj, void *event_inf
        __default_height = h;
 }
 
-static gboolean __manual_render_timeout(gpointer user_data)
-{
-       LOGW("manual render timeout expired");
-       __manual_render_finish();
-       __manual_render_timer = 0;
-       return G_SOURCE_REMOVE;
-}
-
-static void __manual_render_start(void)
-{
-       Evas_Object *cur_image;
-       bool is_visible = false;
-
-       if (__win == NULL) {
-               _E("Window is NULL");
-               return;
-       }
-
-       cur_image = evas_object_data_get(__win, "tbm,watch");
-       screen_connector_toolkit_evas_is_visible(cur_image, &is_visible);
-       if (!is_visible) {
-               LOGW("watch is not visible skip manual render");
-               return;
-       }
-
-       if (__is_bound) {
-               LOGW("watch is bound cannot manual render just call tick");
-               __change_viewer_visibility(AUL_SCREEN_STATUS_PRE_RESUME, false);
-               if (cur_image)
-                       screen_connector_toolkit_evas_send_visibility(cur_image,
-                                       VISIBILITY_TYPE_UNOBSCURED);
-
-               return;
-       }
-
-       if (__manual_render) {
-               LOGW("manual render is already started");
-               return;
-       }
-
-       elm_win_norender_push(__win);
-       __change_viewer_visibility(AUL_SCREEN_STATUS_PRE_RESUME, false);
-       if (cur_image)
-               screen_connector_toolkit_evas_send_visibility(cur_image,
-                               VISIBILITY_TYPE_UNOBSCURED);
-       __manual_render = true;
-
-       __manual_render_timer = g_timeout_add(100, __manual_render_timeout, NULL);
-       LOGI("Manual render start");
-}
-
-static void __manual_render_finish(void)
-{
-       if (__win == NULL) {
-               _E("Window is NULL");
-               return;
-       }
-       elm_win_norender_pop(__win);
-       LOGI("set manual false");
-
-       __manual_render = false;
-       if (__manual_render_timer > 0) {
-               g_source_remove(__manual_render_timer);
-               __manual_render_timer = 0;
-       }
-}
-
-static Eina_Bool __window_on_pre_visibility(void *data, int type, void *event)
-{
-       Ecore_Wl2_Event_Window_Pre_Visibility_Change *ev = event;
-       Ecore_Evas *ee;
-       Ecore_Wl2_Window *wl_win;
-       unsigned int win_id;
-
-       if (!ev)
-               return ECORE_CALLBACK_RENEW;
-
-       ee = ecore_evas_ecore_evas_get(evas_object_evas_get(__win));
-       if (!ee)
-               return ECORE_CALLBACK_RENEW;
-
-       wl_win = ecore_evas_wayland2_window_get(ee);
-       if (!wl_win)
-               return ECORE_CALLBACK_RENEW;
-
-       win_id = ecore_wl2_window_id_get(wl_win);
-       if (ev->win != win_id)
-               return ECORE_CALLBACK_RENEW;
-
-       if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
-               __manual_render_start();
-               LOGD("[__WINDOW_PRE_VISIBILITY_CHANGE__] win_id(%u)",
-                               (unsigned int)ev->win);
-       }
-
-       return ECORE_CALLBACK_RENEW;
-}
-
 static int __watch_viewer_init(Evas_Object *win)
 {
        if (__watch_viewer_initialized)
@@ -322,13 +440,8 @@ static int __watch_viewer_init(Evas_Object *win)
        __win_resized(NULL, NULL, win, NULL); /* init */
        evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, __win_resized, NULL);
 
-       __pre_visibility = ecore_event_handler_add(
-                       ECORE_WL2_EVENT_WINDOW_PRE_VISIBILITY_CHANGE,
-                       __window_on_pre_visibility, NULL);
-       if (!__pre_visibility)
-               _E("Failed to add pre visibility change handler");
+       __manual_render_init();
 
-       __manual_render = false;
        __watch_viewer_initialized = 1;
 
        return 0;
@@ -336,10 +449,7 @@ static int __watch_viewer_init(Evas_Object *win)
 
 static void __watch_viewer_fini()
 {
-       if (__pre_visibility) {
-               ecore_event_handler_del(__pre_visibility);
-               __pre_visibility = NULL;
-       }
+       __manual_render_fini();
 
        if (__win) {
                evas_object_event_callback_del(__win, EVAS_CALLBACK_RESIZE, __win_resized);
@@ -387,6 +497,8 @@ static void __screen_connector_toolkit_evas_added_cb(const char *appid, const ch
        _D("w: %d, h: %d, x: %d y: %d", w, h, x, y);
        evas_object_smart_callback_call(__win, WATCH_SMART_SIGNAL_ADDED, image);
        evas_object_data_set(__win, "tbm,watch", image);
+       evas_object_event_callback_add(image, EVAS_CALLBACK_MOVE,
+                       __obj_move_cb, image);
        screen_connector_toolkit_evas_get_rid(image, (int *)&__watch_rid);
        __flush_pending_queue(__watch_rid);
        __change_viewer_visibility(__viewer_visibility, false);
@@ -408,6 +520,8 @@ static void __screen_connector_toolkit_evas_removed_cb(const char *appid, const
 
        _D("obj(%p) removed", image);
        evas_object_smart_callback_call(__win, WATCH_SMART_SIGNAL_REMOVED, image);
+       evas_object_event_callback_del_full(image, EVAS_CALLBACK_MOVE,
+                       __obj_move_cb, image);
        cur_image = evas_object_data_get(__win, "tbm,watch");
        if (cur_image == image) {
                evas_object_data_set(__win, "tbm,watch", NULL);
@@ -446,8 +560,8 @@ static void __screen_connector_toolkit_evas_updated_cb(
 {
        evas_object_smart_callback_call(
                        __win, WATCH_SMART_SIGNAL_UPDATED, image);
-       if (__manual_render)
-               __manual_render_finish();
+       if (__manual_render.started)
+               __manual_render_stop();
        else
                LOGI("updated");
 }
diff --git a/watch-control/src/watch_control_private.h b/watch-control/src/watch_control_private.h
new file mode 100644 (file)
index 0000000..5618432
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WATCH_CONTROL_PRIVATE_H__
+#define __WATCH_CONTROL_PRIVATE_H__
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "WATCH_CONTROL"
+
+#ifndef _E
+#define _E LOGE
+#endif
+
+#ifndef _W
+#define _W LOGW
+#endif
+
+#ifndef _I
+#define _I LOGI
+#endif
+
+#ifndef _D
+#define _D LOGD
+#endif
+
+#ifndef API
+#define API __attribute__((visibility("default")))
+#endif
+
+#endif /* __WATCH_CONTROL_PRIVATE_H__ */
diff --git a/watch-control/src/watch_control_signal.c b/watch-control/src/watch_control_signal.c
new file mode 100644 (file)
index 0000000..8c671aa
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "watch_control_signal.h"
+#include "watch_control_private.h"
+
+#define DEVICED_PATH_DISPLAY            "/Org/Tizen/System/DeviceD/Display"
+#define DEVICED_INTERFACE_DISPLAY       "org.tizen.system.deviced.display"
+#define SIGNAL_LCD_ON                   "LCDOn"
+#define SIGNAL_LCD_OFF                  "LCDOff"
+
+struct lcd_signal_s {
+       GDBusConnection *conn;
+       guint source;
+       lcd_signal_cb callback;
+       void *user_data;
+};
+
+static void __on_lcd_signal_handler(GDBusConnection *connection,
+               const gchar *sender_name, const gchar *object_name,
+               const gchar *interface_name, const gchar *signal_name,
+               GVariant *parameters, gpointer user_data)
+{
+       struct lcd_signal_s *h = (struct lcd_signal_s *)user_data;
+       bool lcd_on;
+
+       if (signal_name && !strcmp(signal_name, SIGNAL_LCD_ON))
+               lcd_on = true;
+       else
+               lcd_on = false;
+
+       h->callback(lcd_on, h->user_data);
+}
+
+static void __destroy_lcd_signal(struct lcd_signal_s *handle)
+{
+       if (handle->source) {
+               g_dbus_connection_signal_unsubscribe(handle->conn,
+                               handle->source);
+       }
+
+       if (handle->conn)
+               g_object_unref(handle->conn);
+
+       free(handle);
+}
+
+static struct lcd_signal_s *__create_lcd_signal(lcd_signal_cb callback,
+               void *user_data)
+{
+       struct lcd_signal_s *handle;
+       GError *err = NULL;
+
+       handle = calloc(1, sizeof(struct lcd_signal_s));
+       if (!handle) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       handle->conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if (!handle->conn) {
+               _E("g_bus_get_sync() is failed. error(%s)", err->message);
+               g_error_free(err);
+               __destroy_lcd_signal(handle);
+               return NULL;
+       }
+
+       handle->source = g_dbus_connection_signal_subscribe(handle->conn,
+                       NULL,
+                       DEVICED_INTERFACE_DISPLAY,
+                       NULL,
+                       DEVICED_PATH_DISPLAY,
+                       NULL,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __on_lcd_signal_handler,
+                       handle,
+                       NULL);
+       if (!handle->source) {
+               _E("g_dbus_connection_signal_subscribe() is failed");
+               __destroy_lcd_signal(handle);
+               return NULL;
+       }
+
+       handle->callback = callback;
+       handle->user_data = user_data;
+
+       return handle;
+}
+
+int watch_control_signal_add_lcd_signal_handler(lcd_signal_cb callback,
+               void *user_data, lcd_signal_h *handle)
+{
+       struct lcd_signal_s *h;
+
+       if (!callback || !handle) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       h = __create_lcd_signal(callback, user_data);
+       if (!h)
+               return -1;
+
+       *handle = h;
+
+       return 0;
+}
+
+int watch_control_signal_remove_lcd_signal_handler(lcd_signal_h handle)
+{
+       struct lcd_signal_s *h = (struct lcd_signal_s *)handle;
+
+       if (!h) {
+               _E("Invalid parameter");
+               return -1;
+       }
+
+       __destroy_lcd_signal(h);
+
+       return 0;
+}
diff --git a/watch-control/src/watch_control_signal.h b/watch-control/src/watch_control_signal.h
new file mode 100644 (file)
index 0000000..850fc7d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WATCH_CONTROL_SIGNAL_H__
+#define __WATCH_CONTROL_SIGNAL_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *lcd_signal_h;
+
+typedef void (*lcd_signal_cb)(bool lcd_on, void *user_data);
+
+int watch_control_signal_add_lcd_signal_handler(lcd_signal_cb callback,
+               void *user_data, lcd_signal_h *handle);
+
+int watch_control_signal_remove_lcd_signal_handler(lcd_signal_h handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WATCH_CONTROL_SIGNAL_H__ */