summaryrefslogtreecommitdiffstats
path: root/services/core
diff options
context:
space:
mode:
authorScott Mertz <scott@cyngn.com>2016-05-09 16:53:04 -0700
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-05-12 11:54:15 -0700
commit32b90fc34417250a625a3c273a3bb3af0563e258 (patch)
tree847132bc5f98ce00f0f6ef3aed5f19f2064c9b9f /services/core
parentc8bbaca3d2b6c051eed3b389ff255e6ce6c05753 (diff)
downloadframeworks_base-32b90fc34417250a625a3c273a3bb3af0563e258.zip
frameworks_base-32b90fc34417250a625a3c273a3bb3af0563e258.tar.gz
frameworks_base-32b90fc34417250a625a3c273a3bb3af0563e258.tar.bz2
Acquire wakelock until dream service acknowledges dream state change
Fixes a bug where the system can enter suspend before the dream service can handle the state change. This manifests in the DozeService failing to enable the sensors used to determine if it should pulse the screen by the time the system goes into full suspend. This doesn't completely address the asynchronous nature of the DreamManagerService startDream method. There's still 2 more asynchronous calls before the ACTION_DREAMING_STARTED is sent out, but testing shows this is 'good enough'. OPO-681 Change-Id: Id6ddc33bc367c1a0182df95374817577006a5b98
Diffstat (limited to 'services/core')
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java60
1 files changed, 55 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 21fa44d..036c0ff 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -112,6 +112,8 @@ public final class PowerManagerService extends SystemService
private static final int MSG_SANDMAN = 2;
// Message: Sent when the screen brightness boost expires.
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
+ // Message: Sent when the sandman fails to acknowledge the dream state change.
+ private static final int MSG_SANDMAN_TIMEOUT = 4;
private static final int MSG_WAKE_UP = 5;
@@ -139,6 +141,8 @@ public final class PowerManagerService extends SystemService
private static final int DIRTY_DOCK_STATE = 1 << 10;
// Dirty bit: brightness boost changed
private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
+ // Dirty bit: sandman state changed
+ private static final int DIRTY_SANDMAN_STATE = 1 << 12;
// Summarizes the state of all active wakelocks.
private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -183,6 +187,9 @@ public final class PowerManagerService extends SystemService
// Max time (microseconds) to allow a CPU boost for
private static final int MAX_CPU_BOOST_TIME = 5000000;
+ // Max time (milliseconds) to wait for the sandman to acknowledge dream state changes
+ private static final int SANDMAN_RESPONSE_TIMEOUT = 2 * 1000;
+
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
@@ -282,6 +289,13 @@ public final class PowerManagerService extends SystemService
// True if the display suspend blocker has been acquired.
private boolean mHoldingDisplaySuspendBlocker;
+ // The suspend blocker used to keep the CPU alive when dreams are requesting to be
+ // started.
+ private final SuspendBlocker mDreamSuspendBlocker;
+
+ // True if the dream suspend blocker has been acquired.
+ private boolean mHoldingDreamSuspendBlocker;
+
// True if systemReady() has been called.
private boolean mSystemReady;
@@ -543,6 +557,7 @@ public final class PowerManagerService extends SystemService
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
+ mDreamSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Dreams");
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
@@ -1927,15 +1942,16 @@ public final class PowerManagerService extends SystemService
| DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
if (mDisplayReady) {
- scheduleSandmanLocked();
+ scheduleSandmanLocked(false);
}
}
}
- private void scheduleSandmanLocked() {
+ private void scheduleSandmanLocked(boolean fromDreamService) {
if (!mSandmanScheduled) {
mSandmanScheduled = true;
Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+ msg.arg1 = fromDreamService ? 1 : 0;
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
@@ -1948,7 +1964,7 @@ public final class PowerManagerService extends SystemService
* the dream and we don't want to hold our lock while doing so. There is a risk that
* the device will wake or go to sleep in the meantime so we have to handle that case.
*/
- private void handleSandman() { // runs on handler thread
+ private void handleSandman(boolean fromDreamService) { // runs on handler thread
// Handle preconditions.
final boolean startDreaming;
final int wakefulness;
@@ -1961,6 +1977,30 @@ public final class PowerManagerService extends SystemService
} else {
startDreaming = false;
}
+ // We hold the display suspend blocker as long as mSandmanSummoned is true
+ // That guarantees this code to be run before the system enters suspend. However,
+ // once we exit this lock, we are no longer guaranteed to stay awake. Hold a wake
+ // lock that is released once the dream service has acknowledged the request
+ // to start.
+ if (mDreamManager != null) {
+ if (startDreaming) {
+ if (!mHoldingDreamSuspendBlocker) {
+ mDreamSuspendBlocker.acquire();
+ mHoldingDreamSuspendBlocker = true;
+ Message msg = mHandler.obtainMessage(MSG_SANDMAN_TIMEOUT);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, SANDMAN_RESPONSE_TIMEOUT);
+ mDirty |= DIRTY_SANDMAN_STATE;
+ updatePowerStateLocked();
+ }
+ } else if (fromDreamService) {
+ mHandler.removeMessages(MSG_SANDMAN_TIMEOUT);
+ if (mHoldingDreamSuspendBlocker) {
+ mDreamSuspendBlocker.release();
+ mHoldingDreamSuspendBlocker = false;
+ }
+ }
+ }
}
// Start dreaming if needed.
@@ -2390,6 +2430,11 @@ public final class PowerManagerService extends SystemService
if (mScreenBrightnessBoostInProgress) {
return true;
}
+
+ if (mSandmanSummoned) {
+ return true;
+ }
+
// Let the system suspend if the screen is off or dozing.
return false;
}
@@ -2985,7 +3030,7 @@ public final class PowerManagerService extends SystemService
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
- scheduleSandmanLocked();
+ scheduleSandmanLocked(true);
}
}
}
@@ -3042,7 +3087,8 @@ public final class PowerManagerService extends SystemService
handleUserActivityTimeout();
break;
case MSG_SANDMAN:
- handleSandman();
+ boolean fromDreamService = msg.arg1 == 1;
+ handleSandman(fromDreamService);
break;
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
handleScreenBrightnessBoostTimeout();
@@ -3051,6 +3097,10 @@ public final class PowerManagerService extends SystemService
cleanupProximity();
((Runnable) msg.obj).run();
break;
+ case MSG_SANDMAN_TIMEOUT:
+ Slog.w(TAG, "Sandman unresponsive, releasing suspend blocker");
+ handleSandman(true);
+ break;
}
}
}