power: add padding timer to power lock 58/59358/4 accepted/tizen/common/20160804.174407 accepted/tizen/ivi/20160804.081139 accepted/tizen/mobile/20160804.081210 accepted/tizen/tv/20160804.081102 accepted/tizen/wearable/20160804.081123 submit/tizen/20160803.081834
authorTaeyoung Kim <ty317.kim@samsung.com>
Mon, 15 Feb 2016 04:29:07 +0000 (13:29 +0900)
committertaeyoung <ty317.kim@samsung.com>
Wed, 3 Aug 2016 07:47:48 +0000 (16:47 +0900)
- If Power Lock timeout (10 minutes) is expired during apps do
  something with reference count 0 for very short time,
  Power Lock will be released. Thus Suspend mode can be entered.

 (Problem example)
==============================================================
Time  |  Music player  |  device-power       | libtracker
==============================================================
00:00    power lock       power lock
                          add timer
         play start                             ref count:1
--------------------------------------------------------------
09:50    play stop                              ref count:0
         search music
--------------------------------------------------------------
10:00                     timer expired
                          check ref count (== 0)
                            -> power unlock
--------------------------------------------------------------
10:10    search done
         play start                             ref count:1
--------------------------------------------------------------
 After
  few                < Power Suspend Mode >
minutes
==============================================================

- To fix the issue, power lock api uses the padding timeout
  whose callback is called after 20 seconds of power lock timeout.
  Apps can do something without increasing reference count.
  If the ref count is still 0 after 20 seconds, the Power Lock
  will be released.

- If the ref count is changed during 20 seconds but the value is
  still 0, Power Lock should not be released. Thus libtracker
  supports the total reference count which means the accumulated
  ref count. Thus The accumulated ref count is checked if the
  ref count is still 0.

Change-Id: I307fbda4313d14fec2a4a31640096020c3c21485
Signed-off-by: Taeyoung Kim <ty317.kim@samsung.com>
Signed-off-by: taeyoung <ty317.kim@samsung.com>
src/power.c

index a25e98bbdaa22776200857f7cd9be59202b9c031..647c9a28543fe9d8692b20df2c5670037ab1f677 100644 (file)
 #define STR_LCD_DIM   "lcddim"
 #define STR_LCD_ON    "lcdon"
 
-#define LOCK_CPU_TIMEOUT_MAX       600000 /* milliseconds */
+#define LOCK_CPU_TIMEOUT_MAX       (60*60*1000) /* milliseconds */
+#define LOCK_CPU_PADDING_TIMEOUT   (20*1000) /* milliseconds */
 
 static guint off_lock_timeout;
+static guint padding_timeout;
+static int prev_count;
 
 static char *get_state_str(display_state_e state)
 {
@@ -82,18 +85,30 @@ static char *get_state_str(display_state_e state)
 
 static void remove_off_lock_timeout(void)
 {
-       _I("Power lock timeout handler removed");
        if (off_lock_timeout) {
+               _I("Power lock timeout handler removed");
                g_source_remove(off_lock_timeout);
                off_lock_timeout = 0;
        }
 }
 
-static gboolean off_lock_timeout_expired(gpointer data)
+static void remove_padding_timeout(void)
+{
+       if (padding_timeout) {
+               _I("Padding timeout handler removed");
+               g_source_remove(padding_timeout);
+               padding_timeout = 0;
+       }
+}
+
+static gboolean padding_timeout_expired(gpointer data)
 {
        int ret, ref;
+       int count;
 
-       _I("Power lock timeout expired");
+       _I("Padding timeout expired");
+
+       remove_padding_timeout();
 
        ret = tracker_get_power_lock_ref(&ref);
        if (ret != TRACKER_ERROR_NONE) {
@@ -102,10 +117,25 @@ static gboolean off_lock_timeout_expired(gpointer data)
        }
 
        _I("reference count of power lock is (%d)", ref);
-       if (ref > 0)
-               return G_SOURCE_CONTINUE;
+       if (ref > 0) {
+               _I("Power Lock continue (Reference count > 0 !!)");
+               return G_SOURCE_REMOVE;
+       }
+
+       ret = tracker_get_power_lock_total(&count);
+       if (ret != TRACKER_ERROR_NONE) {
+               _E("Failed to get total count of power lock(%d)", ret);
+               goto out;
+       }
+
+       if (count != prev_count) {
+               _I("Power Lock continue (Total reference count increased !!)");
+               return G_SOURCE_REMOVE;
+       }
 
 out:
+       remove_off_lock_timeout();
+
        ret = device_power_release_lock(POWER_LOCK_CPU);
        if (ret != DEVICE_ERROR_NONE)
                _E("Failed to lock power(CPU) again(%d)", ret);
@@ -113,16 +143,64 @@ out:
        return G_SOURCE_REMOVE;
 }
 
+static void add_padding_timeout(void)
+{
+       guint id;
+
+       remove_padding_timeout();
+
+       _I("Padding timeout handler added");
+
+       id = g_timeout_add(LOCK_CPU_PADDING_TIMEOUT,
+                       padding_timeout_expired, NULL);
+       if (id)
+               padding_timeout = id;
+       else
+               _E("Failed to add timeout for padding time");
+}
+
+static gboolean off_lock_timeout_expired(gpointer data)
+{
+       int ret, ref;
+
+       _I("Power lock timeout expired");
+
+       ret = tracker_get_power_lock_ref(&ref);
+       if (ret != TRACKER_ERROR_NONE) {
+               _E("Failed to get reference count of power lock(%d)", ret);
+               remove_off_lock_timeout();
+               return G_SOURCE_REMOVE;
+       }
+
+       _I("reference count of power lock is (%d)", ref);
+       if (ref > 0)
+               goto out;
+
+       add_padding_timeout();
+
+       ret = tracker_get_power_lock_total(&prev_count);
+       if (ret != TRACKER_ERROR_NONE)
+               _E("Failed to get total count of power lock(%d)", ret);
+
+out:
+       return G_SOURCE_CONTINUE;
+}
+
 static void add_off_lock_timeout(void)
 {
        guint id;
 
        remove_off_lock_timeout();
+       remove_padding_timeout();
+
+       _I("Power lock timeout handler added");
 
        id = g_timeout_add(LOCK_CPU_TIMEOUT_MAX,
                        off_lock_timeout_expired, NULL);
        if (id)
                off_lock_timeout = id;
+       else
+               _E("Failed to add Power Lock timeout handler");
 }
 
 static void lock_cb(void *data, GVariant *result, GError *err)
@@ -251,8 +329,10 @@ int device_power_release_lock(power_lock_e type)
 
        if (type == POWER_LOCK_CPU) {
                ret = unlock_state(DISPLAY_STATE_SCREEN_OFF, PM_SLEEP_MARGIN);
-               if (ret == 0 && off_lock_timeout > 0)
+               if (ret == 0 && off_lock_timeout > 0) {
                        remove_off_lock_timeout();
+                       remove_padding_timeout();
+               }
        } else if (type == POWER_LOCK_DISPLAY)
                ret = unlock_state(DISPLAY_STATE_NORMAL, PM_KEEP_TIMER);
        else if (type == POWER_LOCK_DISPLAY_DIM)