diff options
author | Jeff Brown <jeffbrown@google.com> | 2014-07-17 22:44:20 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2014-07-18 21:56:08 -0700 |
commit | f6d466895b74d620d646abbec1c8911f3a0ce0bb (patch) | |
tree | 1411bc110ac23d4baa62f44d73fa94681b8c258b /services | |
parent | 5dc219142a756d57355b511c8f8ab913c01710da (diff) | |
download | frameworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.zip frameworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.tar.gz frameworks_base-f6d466895b74d620d646abbec1c8911f3a0ce0bb.tar.bz2 |
Allow dreams to wake up gently.
This change adds a new DreamService.wakeUp() method to allow a
dream to wake itself up gently and perform a transition before
finally finishing. The power manager will ask a dream to wake
up gently in most cases but may force it to happen immediately
when necessary.
If the dream takes too long to finish itself then the dream
controller will douse it with water summarily after 5 seconds.
Change-Id: Ib0564c5650cd5a454e1acc5aa91fe46995eecfa7
Diffstat (limited to 'services')
3 files changed, 76 insertions, 33 deletions
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index 649b5c9..334f0ac 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -47,6 +47,9 @@ final class DreamController { // How long we wait for a newly bound dream to create the service connection private static final int DREAM_CONNECTION_TIMEOUT = 5 * 1000; + // Time to allow the dream to perform an exit transition when waking up. + private static final int DREAM_FINISH_TIMEOUT = 5 * 1000; + private final Context mContext; private final Handler mHandler; private final Listener mListener; @@ -66,11 +69,19 @@ final class DreamController { public void run() { if (mCurrentDream != null && mCurrentDream.mBound && !mCurrentDream.mConnected) { Slog.w(TAG, "Bound dream did not connect in the time allotted"); - stopDream(); + stopDream(true /*immediate*/); } } }; + private final Runnable mStopStubbornDreamRunnable = new Runnable() { + @Override + public void run() { + Slog.w(TAG, "Stubborn dream did not finish itself in the time allotted"); + stopDream(true /*immediate*/); + } + }; + public DreamController(Context context, Handler handler, Listener listener) { mContext = context; mHandler = handler; @@ -90,6 +101,7 @@ final class DreamController { pw.println(" mBound=" + mCurrentDream.mBound); pw.println(" mService=" + mCurrentDream.mService); pw.println(" mSentStartBroadcast=" + mCurrentDream.mSentStartBroadcast); + pw.println(" mWakingGently=" + mCurrentDream.mWakingGently); } else { pw.println(" mCurrentDream: null"); } @@ -97,7 +109,7 @@ final class DreamController { public void startDream(Binder token, ComponentName name, boolean isTest, boolean canDoze, int userId) { - stopDream(); + stopDream(true /*immediate*/); // Close the notification shade. Don't need to send to all, but better to be explicit. mContext.sendBroadcastAsUser(mCloseNotificationShadeIntent, UserHandle.ALL); @@ -112,7 +124,7 @@ final class DreamController { mIWindowManager.addWindowToken(token, WindowManager.LayoutParams.TYPE_DREAM); } catch (RemoteException ex) { Slog.e(TAG, "Unable to add window token for dream.", ex); - stopDream(); + stopDream(true /*immediate*/); return; } @@ -123,12 +135,12 @@ final class DreamController { if (!mContext.bindServiceAsUser(intent, mCurrentDream, Context.BIND_AUTO_CREATE, new UserHandle(userId))) { Slog.e(TAG, "Unable to bind dream service: " + intent); - stopDream(); + stopDream(true /*immediate*/); return; } } catch (SecurityException ex) { Slog.e(TAG, "Unable to bind dream service: " + intent, ex); - stopDream(); + stopDream(true /*immediate*/); return; } @@ -136,11 +148,29 @@ final class DreamController { mHandler.postDelayed(mStopUnconnectedDreamRunnable, DREAM_CONNECTION_TIMEOUT); } - public void stopDream() { + public void stopDream(boolean immediate) { if (mCurrentDream == null) { return; } + if (!immediate) { + if (mCurrentDream.mWakingGently) { + return; // already waking gently + } + + if (mCurrentDream.mService != null) { + // Give the dream a moment to wake up and finish itself gently. + mCurrentDream.mWakingGently = true; + try { + mCurrentDream.mService.wakeUp(); + mHandler.postDelayed(mStopStubbornDreamRunnable, DREAM_FINISH_TIMEOUT); + return; + } catch (RemoteException ex) { + // oh well, we tried, finish immediately instead + } + } + } + final DreamRecord oldDream = mCurrentDream; mCurrentDream = null; Slog.i(TAG, "Stopping dream: name=" + oldDream.mName @@ -148,6 +178,7 @@ final class DreamController { + ", userId=" + oldDream.mUserId); mHandler.removeCallbacks(mStopUnconnectedDreamRunnable); + mHandler.removeCallbacks(mStopStubbornDreamRunnable); if (oldDream.mSentStartBroadcast) { mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL); @@ -195,7 +226,7 @@ final class DreamController { service.attach(mCurrentDream.mToken, mCurrentDream.mCanDoze); } catch (RemoteException ex) { Slog.e(TAG, "The dream service died unexpectedly.", ex); - stopDream(); + stopDream(true /*immediate*/); return; } @@ -226,6 +257,8 @@ final class DreamController { public IDreamService mService; public boolean mSentStartBroadcast; + public boolean mWakingGently; + public DreamRecord(Binder token, ComponentName name, boolean isTest, boolean canDoze, int userId) { mToken = token; @@ -243,7 +276,7 @@ final class DreamController { public void run() { mService = null; if (mCurrentDream == DreamRecord.this) { - stopDream(); + stopDream(true /*immediate*/); } } }); @@ -271,7 +304,7 @@ final class DreamController { public void run() { mService = null; if (mCurrentDream == DreamRecord.this) { - stopDream(); + stopDream(true /*immediate*/); } } }); diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index a35e2ba..4ccf73b 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -80,6 +80,7 @@ public final class DreamManagerService extends SystemService { private boolean mCurrentDreamIsTest; private boolean mCurrentDreamCanDoze; private boolean mCurrentDreamIsDozing; + private boolean mCurrentDreamIsWaking; private DozeHardwareWrapper mCurrentDreamDozeHardware; public DreamManagerService(Context context) { @@ -113,7 +114,7 @@ public final class DreamManagerService extends SystemService { @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { - stopDreamLocked(); + stopDreamLocked(false /*immediate*/); } } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); @@ -132,6 +133,7 @@ public final class DreamManagerService extends SystemService { pw.println("mCurrentDreamIsTest=" + mCurrentDreamIsTest); pw.println("mCurrentDreamCanDoze=" + mCurrentDreamCanDoze); pw.println("mCurrentDreamIsDozing=" + mCurrentDreamIsDozing); + pw.println("mCurrentDreamIsWaking=" + mCurrentDreamIsWaking); pw.println("mCurrentDreamDozeHardware=" + mCurrentDreamDozeHardware); pw.println("getDozeComponent()=" + getDozeComponent()); pw.println(); @@ -146,7 +148,8 @@ public final class DreamManagerService extends SystemService { private boolean isDreamingInternal() { synchronized (mLock) { - return mCurrentDreamToken != null && !mCurrentDreamIsTest; + return mCurrentDreamToken != null && !mCurrentDreamIsTest + && !mCurrentDreamIsWaking; } } @@ -166,12 +169,12 @@ public final class DreamManagerService extends SystemService { // for example when being undocked. long time = SystemClock.uptimeMillis(); mPowerManager.userActivity(time, false /*noChangeLights*/); - stopDreamInternal(); + stopDreamInternal(false /*immediate*/); } - private void finishSelfInternal(IBinder token) { + private void finishSelfInternal(IBinder token, boolean immediate) { if (DEBUG) { - Slog.d(TAG, "Dream finished: " + token); + Slog.d(TAG, "Dream finished: " + token + ", immediate=" + immediate); } // Note that a dream finishing and self-terminating is not @@ -183,7 +186,7 @@ public final class DreamManagerService extends SystemService { // device may simply go to sleep. synchronized (mLock) { if (mCurrentDreamToken == token) { - stopDreamLocked(); + stopDreamLocked(immediate); } } } @@ -204,9 +207,9 @@ public final class DreamManagerService extends SystemService { } } - private void stopDreamInternal() { + private void stopDreamInternal(boolean immediate) { synchronized (mLock) { - stopDreamLocked(); + stopDreamLocked(immediate); } } @@ -345,9 +348,9 @@ public final class DreamManagerService extends SystemService { return; } - stopDreamLocked(); + stopDreamLocked(true /*immediate*/); - if (DEBUG) Slog.i(TAG, "Entering dreamland."); + Slog.i(TAG, "Entering dreamland."); final Binder newToken = new Binder(); mCurrentDreamToken = newToken; @@ -364,16 +367,22 @@ public final class DreamManagerService extends SystemService { }); } - private void stopDreamLocked() { + private void stopDreamLocked(final boolean immediate) { if (mCurrentDreamToken != null) { - if (DEBUG) Slog.i(TAG, "Leaving dreamland."); - - cleanupDreamLocked(); + if (immediate) { + Slog.i(TAG, "Leaving dreamland."); + cleanupDreamLocked(); + } else if (mCurrentDreamIsWaking) { + return; // already waking + } else { + Slog.i(TAG, "Gently waking up from dream."); + mCurrentDreamIsWaking = true; + } mHandler.post(new Runnable() { @Override public void run() { - mController.stopDream(); + mController.stopDream(immediate); } }); } @@ -385,6 +394,7 @@ public final class DreamManagerService extends SystemService { mCurrentDreamIsTest = false; mCurrentDreamCanDoze = false; mCurrentDreamUserId = 0; + mCurrentDreamIsWaking = false; if (mCurrentDreamIsDozing) { mCurrentDreamIsDozing = false; mDozeWakeLock.release(); @@ -568,7 +578,7 @@ public final class DreamManagerService extends SystemService { } @Override // Binder call - public void finishSelf(IBinder token) { + public void finishSelf(IBinder token, boolean immediate) { // Requires no permission, called by Dream from an arbitrary process. if (token == null) { throw new IllegalArgumentException("token must not be null"); @@ -576,7 +586,7 @@ public final class DreamManagerService extends SystemService { final long ident = Binder.clearCallingIdentity(); try { - finishSelfInternal(token); + finishSelfInternal(token, immediate); } finally { Binder.restoreCallingIdentity(ident); } @@ -635,8 +645,8 @@ public final class DreamManagerService extends SystemService { } @Override - public void stopDream() { - stopDreamInternal(); + public void stopDream(boolean immediate) { + stopDreamInternal(immediate); } @Override @@ -683,11 +693,11 @@ public final class DreamManagerService extends SystemService { @Override public void run() { if (DEBUG) Slog.d(TAG, "System properties changed"); - synchronized(mLock) { + synchronized (mLock) { if (mCurrentDreamName != null && mCurrentDreamCanDoze && !mCurrentDreamName.equals(getDozeComponent())) { - // may have updated the doze component, wake up - stopDreamLocked(); + // May have updated the doze component, wake up + mPowerManager.wakeUp(SystemClock.uptimeMillis()); } } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index cb4d339..4b1e8eb 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -1551,7 +1551,7 @@ public final class PowerManagerService extends com.android.server.SystemService if (mDreamManager != null) { // Restart the dream whenever the sandman is summoned. if (startDreaming) { - mDreamManager.stopDream(); + mDreamManager.stopDream(false /*immediate*/); mDreamManager.startDream(wakefulness == WAKEFULNESS_DOZING); } isDreaming = mDreamManager.isDreaming(); @@ -1619,7 +1619,7 @@ public final class PowerManagerService extends com.android.server.SystemService // Stop dream. if (isDreaming) { - mDreamManager.stopDream(); + mDreamManager.stopDream(false /*immediate*/); } } |