diff options
3 files changed, 103 insertions, 6 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index d56dc1e07f52..bde8f3978222 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -16,6 +16,8 @@ package android.app; +import android.annotation.NonNull; + /** * Activity manager local system service interface. * @@ -27,4 +29,23 @@ public abstract class ActivityManagerInternal { public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs, String processName, String abiOverride, int uid, Runnable crashHandler); + + /** + * Acquires a sleep token with the specified tag. + * + * @param tag A string identifying the purpose of the token (eg. "Dream"). + */ + public abstract SleepToken acquireSleepToken(@NonNull String tag); + + /** + * Sleep tokens cause the activity manager to put the top activity to sleep. + * They are used by components such as dreams that may hide and block interaction + * with underlying activities. + */ + public static abstract class SleepToken { + /** + * Releases the sleep token. + */ + public abstract void release(); + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b65893274c13..15d675672ba5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -114,6 +114,7 @@ import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerInternal; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.ActivityThread; @@ -1013,6 +1014,13 @@ public final class ActivityManagerService extends ActivityManagerNative */ private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; + /** + * A list of tokens that cause the top activity to be put to sleep. + * They are used by components that may hide and block interaction with underlying + * activities. + */ + final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>(); + static final int LOCK_SCREEN_HIDDEN = 0; static final int LOCK_SCREEN_LEAVING = 1; static final int LOCK_SCREEN_SHOWN = 2; @@ -9813,15 +9821,14 @@ public final class ActivityManagerService extends ActivityManagerNative return false; } + // TODO: Transform the lock screen state into a sleep token instead. switch (mWakefulness) { case PowerManagerInternal.WAKEFULNESS_AWAKE: case PowerManagerInternal.WAKEFULNESS_DREAMING: - // If we're interactive but applications are already paused then defer - // resuming them until the lock screen is hidden. - return mSleeping && mLockScreenShown != LOCK_SCREEN_HIDDEN; case PowerManagerInternal.WAKEFULNESS_DOZING: - // If we're dozing then pause applications whenever the lock screen is shown. - return mLockScreenShown != LOCK_SCREEN_HIDDEN; + // Pause applications whenever the lock screen is shown or any sleep + // tokens have been acquired. + return (mLockScreenShown != LOCK_SCREEN_HIDDEN || !mSleepTokens.isEmpty()); case PowerManagerInternal.WAKEFULNESS_ASLEEP: default: // If we're asleep then pause applications unconditionally. @@ -12950,6 +12957,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (dumpPackage == null) { pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness)); + pw.println(" mSleepTokens=" + mSleepTokens); pw.println(" mSleeping=" + mSleeping + " mLockScreenShown=" + lockScreenShownToString()); pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode); @@ -19723,6 +19731,42 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManagerService.this.startIsolatedProcess(entryPoint, entryPointArgs, processName, abiOverride, uid, crashHandler); } + + @Override + public SleepToken acquireSleepToken(String tag) { + Preconditions.checkNotNull(tag); + + synchronized (ActivityManagerService.this) { + SleepTokenImpl token = new SleepTokenImpl(tag); + mSleepTokens.add(token); + updateSleepIfNeededLocked(); + return token; + } + } + } + + private final class SleepTokenImpl extends SleepToken { + private final String mTag; + private final long mAcquireTime; + + public SleepTokenImpl(String tag) { + mTag = tag; + mAcquireTime = SystemClock.uptimeMillis(); + } + + @Override + public void release() { + synchronized (ActivityManagerService.this) { + if (mSleepTokens.remove(this)) { + updateSleepIfNeededLocked(); + } + } + } + + @Override + public String toString() { + return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; + } } /** diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ad85b5997301..25857c5d5062 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -17,6 +17,8 @@ package com.android.server.policy; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.IUiModeManager; @@ -252,6 +254,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerFuncs mWindowManagerFuncs; WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; + ActivityManagerInternal mActivityManagerInternal; DreamManagerInternal mDreamManagerInternal; IStatusBarService mStatusBarService; boolean mPreloadedRecentApps; @@ -493,6 +496,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mShowingLockscreen; boolean mShowingDream; boolean mDreamingLockscreen; + boolean mDreamingSleepTokenNeeded; + SleepToken mDreamingSleepToken; boolean mKeyguardSecure; boolean mKeyguardSecureIncludingHidden; volatile boolean mKeyguardOccluded; @@ -599,6 +604,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; private static final int MSG_POWER_DELAYED_PRESS = 13; private static final int MSG_POWER_LONG_PRESS = 14; + private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15; private class PolicyHandler extends Handler { @Override @@ -647,6 +653,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_POWER_LONG_PRESS: powerLongPress(); break; + case MSG_UPDATE_DREAMING_SLEEP_TOKEN: + updateDreamingSleepToken(msg.arg1 != 0); + break; } } } @@ -1220,6 +1229,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManager = windowManager; mWindowManagerFuncs = windowManagerFuncs; mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); // Init display burn-in protection @@ -4239,6 +4249,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { // while the dream is showing. if (!mShowingDream) { mDreamingLockscreen = mShowingLockscreen; + if (mDreamingSleepTokenNeeded) { + mDreamingSleepTokenNeeded = false; + mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); + } + } else { + if (!mDreamingSleepTokenNeeded) { + mDreamingSleepTokenNeeded = true; + mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); + } } if (mStatusBar != null) { @@ -5851,6 +5870,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void updateDreamingSleepToken(boolean acquire) { + if (acquire) { + if (mDreamingSleepToken == null) { + mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); + } + } else { + if (mDreamingSleepToken != null) { + mDreamingSleepToken.release(); + } + } + } + /** {@inheritDoc} */ @Override public void enableScreenAfterBoot() { @@ -6487,7 +6518,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); pw.print(" mShowingDream="); pw.print(mShowingDream); - pw.print(" mDreamingLockscreen="); pw.println(mDreamingLockscreen); + pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); + pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); if (mLastInputMethodWindow != null) { pw.print(prefix); pw.print("mLastInputMethodWindow="); pw.println(mLastInputMethodWindow); |