diff options
| author | 2017-08-16 23:15:05 +0000 | |
|---|---|---|
| committer | 2017-08-16 23:15:05 +0000 | |
| commit | 341cd735cb7ba5d3b2c6f9b17eceef7059e4dc67 (patch) | |
| tree | 1de74e01fa3c7d0f170116fb5fc546521eadc602 | |
| parent | 70aa7bbc81e6ae6352b5f391eef3a62d85c163c5 (diff) | |
| parent | f62360cafa21aef36f2176512d4a5241ae38aa8c (diff) | |
Merge "DO NOT MERGE Let external activities run when the primary display is off" into oc-mr1-dev
17 files changed, 408 insertions, 209 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index e5fe2402dae1..68fb7bc20575 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -30,8 +30,6 @@ import android.util.SparseIntArray; import com.android.internal.app.IVoiceInteractor; -import java.io.PrintWriter; -import java.util.ArrayList; import java.util.List; /** @@ -90,11 +88,12 @@ public abstract class ActivityManagerInternal { String processName, String abiOverride, int uid, Runnable crashHandler); /** - * Acquires a sleep token with the specified tag. + * Acquires a sleep token for the specified display with the specified tag. * * @param tag A string identifying the purpose of the token (eg. "Dream"). + * @param displayId The display to apply the sleep token to. */ - public abstract SleepToken acquireSleepToken(@NonNull String tag); + public abstract SleepToken acquireSleepToken(@NonNull String tag, int displayId); /** * Sleep tokens cause the activity manager to put the top activity to sleep. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1d860d601601..325ffb4c3581 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1346,7 +1346,7 @@ public class ActivityManagerService extends IActivityManager.Stub * Set while we are running a voice interaction. This overrides * sleeping while it is active. */ - private IVoiceInteractionSession mRunningVoice; + IVoiceInteractionSession mRunningVoice; /** * For some direct access we need to power manager. @@ -1366,13 +1366,6 @@ public class ActivityManagerService extends IActivityManager.Stub 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>(); - - /** * Set if we are shutting down the system, similar to sleeping. */ boolean mShuttingDown = false; @@ -12390,7 +12383,19 @@ public class ActivityManagerService extends IActivityManager.Stub void onWakefulnessChanged(int wakefulness) { synchronized(this) { mWakefulness = wakefulness; - updateSleepIfNeededLocked(); + + // Also update state in a special way for running foreground services UI. + switch (mWakefulness) { + case PowerManagerInternal.WAKEFULNESS_ASLEEP: + case PowerManagerInternal.WAKEFULNESS_DREAMING: + case PowerManagerInternal.WAKEFULNESS_DOZING: + mServices.updateScreenStateLocked(false /* screenOn */); + break; + case PowerManagerInternal.WAKEFULNESS_AWAKE: + default: + mServices.updateScreenStateLocked(true /* screenOn */); + break; + } } } @@ -12410,14 +12415,24 @@ public class ActivityManagerService extends IActivityManager.Stub } void updateSleepIfNeededLocked() { - final boolean shouldSleep = shouldSleepLocked(); - if (mSleeping && !shouldSleep) { - mSleeping = false; - startTimeTrackingFocusedActivityLocked(); - mTopProcessState = ActivityManager.PROCESS_STATE_TOP; - mStackSupervisor.comeOutOfSleepIfNeededLocked(); - sendNotifyVrManagerOfSleepState(false); - updateOomAdjLocked(); + final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay(); + final boolean wasSleeping = mSleeping; + + if (!shouldSleep) { + // If wasSleeping is true, we need to wake up activity manager state from when + // we started sleeping. In either case, we need to apply the sleep tokens, which + // will wake up stacks or put them to sleep as appropriate. + if (wasSleeping) { + mSleeping = false; + startTimeTrackingFocusedActivityLocked(); + mTopProcessState = ActivityManager.PROCESS_STATE_TOP; + mStackSupervisor.comeOutOfSleepIfNeededLocked(); + } + mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */); + if (wasSleeping) { + sendNotifyVrManagerOfSleepState(false); + updateOomAdjLocked(); + } } else if (!mSleeping && shouldSleep) { mSleeping = true; if (mCurAppTimeTracker != null) { @@ -12428,40 +12443,6 @@ public class ActivityManagerService extends IActivityManager.Stub sendNotifyVrManagerOfSleepState(true); updateOomAdjLocked(); } - - // Also update state in a special way for running foreground services UI. - switch (mWakefulness) { - case PowerManagerInternal.WAKEFULNESS_ASLEEP: - case PowerManagerInternal.WAKEFULNESS_DREAMING: - case PowerManagerInternal.WAKEFULNESS_DOZING: - mServices.updateScreenStateLocked(false); - break; - case PowerManagerInternal.WAKEFULNESS_AWAKE: - default: - mServices.updateScreenStateLocked(true); - break; - } - } - - private boolean shouldSleepLocked() { - // Resume applications while running a voice interactor. - if (mRunningVoice != null) { - return false; - } - - // TODO: Transform the lock screen state into a sleep token instead. - switch (mWakefulness) { - case PowerManagerInternal.WAKEFULNESS_AWAKE: - case PowerManagerInternal.WAKEFULNESS_DREAMING: - // Pause applications whenever the lock screen is shown or any sleep - // tokens have been acquired. - return mKeyguardController.isKeyguardShowing() || !mSleepTokens.isEmpty(); - case PowerManagerInternal.WAKEFULNESS_DOZING: - case PowerManagerInternal.WAKEFULNESS_ASLEEP: - default: - // If we're asleep then pause applications unconditionally. - return true; - } } /** Pokes the task persister. */ @@ -12502,6 +12483,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized(this) { mShuttingDown = true; + mStackSupervisor.prepareForShutdownLocked(); updateEventDispatchingLocked(); timedout = mStackSupervisor.shutdownLocked(timeout); } @@ -14916,6 +14898,14 @@ public class ActivityManagerService extends IActivityManager.Stub this, in, out, err, args, callback, resultReceiver); } + SleepToken acquireSleepToken(String tag, int displayId) { + synchronized (this) { + final SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId); + updateSleepIfNeededLocked(); + return token; + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; @@ -15812,7 +15802,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (dumpPackage == null) { pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness)); - pw.println(" mSleepTokens=" + mSleepTokens); + pw.println(" mSleepTokens=" + mStackSupervisor.mSleepTokens); pw.println(" mSleeping=" + mSleeping); pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode); if (mRunningVoice != null) { @@ -23772,15 +23762,9 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public SleepToken acquireSleepToken(String tag) { + public SleepToken acquireSleepToken(String tag, int displayId) { Preconditions.checkNotNull(tag); - - synchronized (ActivityManagerService.this) { - SleepTokenImpl token = new SleepTokenImpl(tag); - mSleepTokens.add(token); - updateSleepIfNeededLocked(); - return token; - } + return ActivityManagerService.this.acquireSleepToken(tag, displayId); } @Override @@ -24217,30 +24201,6 @@ public class ActivityManagerService extends IActivityManager.Stub } } - 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) + "}"; - } - } - /** * An implementation of IAppTask, that allows an app to manage its own tasks via * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 8cab918c394f..6b1f7585dde6 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1341,7 +1341,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo intent, getUriPermissionsLocked(), userId); final ReferrerIntent rintent = new ReferrerIntent(intent, referrer); boolean unsent = true; - final boolean isTopActivityWhileSleeping = service.isSleepingLocked() && isTopRunningActivity(); + final ActivityStack stack = getStack(); + final boolean isTopActivityWhileSleeping = isTopRunningActivity() + && (stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked()); // We want to immediately deliver the intent to the activity if: // - It is currently resumed or paused. i.e. it is currently visible to the user and we want @@ -1731,7 +1733,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // If the screen is going to turn on because the caller explicitly requested it and // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will // pause and then resume again later, which will result in a double life-cycle event. - mStackSupervisor.checkReadyForSleepLocked(); + stack.checkReadyForSleep(); } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 896f846feec0..84fd0de4f0ab 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1170,10 +1170,25 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + void checkReadyForSleep() { + if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) { + mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */); + } + } + /** + * Tries to put the activities in the stack to sleep. + * + * If the stack is not in a state where its activities can be put to sleep, this function will + * start any necessary actions to move the stack into such a state. It is expected that this + * function get called again when those actions complete. + * + * @param shuttingDown true when the called because the device is shutting down. * @return true if something must be done before going to sleep. */ - boolean checkReadyForSleepLocked() { + boolean goToSleepIfPossible(boolean shuttingDown) { + boolean shouldSleep = true; + if (mResumedActivity != null) { // Still have something resumed; can't sleep until it is paused. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity); @@ -1183,26 +1198,47 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If we are in the middle of resuming the top activity in // {@link #resumeTopActivityUncheckedLocked}, mResumedActivity will be set but not // resumed yet. We must not proceed pausing the activity here. This method will be - // called again if necessary as part of + // called again if necessary as part of {@link #checkReadyForSleep} or // {@link ActivityStackSupervisor#checkReadyForSleepLocked}. if (mStackSupervisor.inResumeTopActivity) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "In the middle of resuming top activity " + mResumedActivity); - return true; + } else { + startPausingLocked(false, true, null, false); } - - startPausingLocked(false, true, null, false); - return true; - } - if (mPausingActivity != null) { + shouldSleep = false ; + } else if (mPausingActivity != null) { // Still waiting for something to pause; can't sleep yet. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity); - return true; + shouldSleep = false; } - return false; + + if (!shuttingDown) { + if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) { + // Still need to tell some activities to stop; can't sleep yet. + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " + + mStackSupervisor.mStoppingActivities.size() + " activities"); + + mStackSupervisor.scheduleIdleLocked(); + shouldSleep = false; + } + + if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) { + // Still need to tell some activities to sleep; can't sleep yet. + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " + + mStackSupervisor.mGoingToSleepActivities.size() + " activities"); + shouldSleep = false; + } + } + + if (shouldSleep) { + goToSleep(); + } + + return !shouldSleep; } - void goToSleep() { + private void goToSleep() { ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Make sure any paused or stopped but visible activities are now sleeping. @@ -1219,6 +1255,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + private boolean containsActivityFromStack(List<ActivityRecord> rs) { + for (ActivityRecord r : rs) { + if (r.getStack() == this) { + return true; + } + } + return false; + } + /** * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because * this directly impacts the responsiveness seen by the user. @@ -1251,7 +1296,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (mPausingActivity != null) { Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity + " state=" + mPausingActivity.state); - if (!mService.isSleepingLocked()) { + if (!shouldSleepActivities()) { // Avoid recursion among check for sleep and complete pause during sleeping. // Because activity will be paused immediately after resume, just let pause // be completed by the order of activity paused from clients. @@ -1411,7 +1456,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // We can't clobber it, because the stop confirmation will not be handled. // We don't need to schedule another stop, we only need to let it happen. prev.state = STOPPING; - } else if (!prev.visible || mService.isSleepingOrShuttingDownLocked()) { + } else if (!prev.visible || shouldSleepOrShutDownActivities()) { // Clear out any deferred client hide we might currently have. prev.setDeferHidingClient(false); // If we were visible then resumeTopActivities will release resources before @@ -1433,10 +1478,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (resumeNext) { final ActivityStack topStack = mStackSupervisor.getFocusedStack(); - if (!mService.isSleepingOrShuttingDownLocked()) { + if (!topStack.shouldSleepOrShutDownActivities()) { mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); } else { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); ActivityRecord top = topStack.topRunningActivityLocked(); if (top == null || (prev != null && top != prev)) { // If there are no more activities available to run, do resume anyway to start @@ -1502,7 +1547,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.scheduleIdleTimeoutLocked(r); } } else { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); } } @@ -2211,7 +2256,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // is skipped. final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { - mStackSupervisor.checkReadyForSleepLocked(); + checkReadyForSleep(); } return result; @@ -2296,7 +2341,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If we are sleeping, and there is no resumed activity, and the top // activity is paused, well that is the state we want. - if (mService.isSleepingOrShuttingDownLocked() + if (shouldSleepOrShutDownActivities() && mLastPausedActivity == next && mStackSupervisor.allPausedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there @@ -2388,7 +2433,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If the most recent activity was noHistory but was only stopped rather // than stopped+finished because the device went to sleep, we need to make // sure to finish it as we're making a new activity topmost. - if (mService.isSleepingLocked() && mLastNoHistoryActivity != null && + if (shouldSleepActivities() && mLastNoHistoryActivity != null && !mLastNoHistoryActivity.finishing) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + mLastNoHistoryActivity + " on new resume"); @@ -3400,7 +3445,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { - if (!mService.isSleepingLocked()) { + if (!shouldSleepActivities()) { if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "stop-no-history", false)) { @@ -3432,7 +3477,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai EventLogTags.writeAmStopActivity( r.userId, System.identityHashCode(r), r.shortComponentName); r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); - if (mService.isSleepingOrShuttingDownLocked()) { + if (shouldSleepOrShutDownActivities()) { r.setSleeping(true); } Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); @@ -5278,4 +5323,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mNoAnimActivities.clear(); ActivityOptions.abort(options); } + + boolean shouldSleepActivities() { + final ActivityStackSupervisor.ActivityDisplay display = getDisplay(); + return display != null ? display.isSleeping() : mService.isSleepingLocked(); + } + + boolean shouldSleepOrShutDownActivities() { + return shouldSleepActivities() || mService.isShuttingDownLocked(); + } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index e8bc68f21981..1c1895449466 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -105,6 +105,7 @@ import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackId; import android.app.ActivityManager.StackInfo; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityOptions; import android.app.AppOpsManager; import android.app.ProfilerInfo; @@ -156,6 +157,7 @@ import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import android.util.TimeUtils; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; @@ -177,6 +179,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -375,9 +378,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * is being brought in front of us. */ boolean mUserLeaving = false; - /** Set when we have taken too long waiting to go to sleep. */ - boolean mSleepTimeout = false; - /** * We don't want to allow the device to go to sleep while in the process * of launching an activity. This is primarily to allow alarm intent @@ -393,6 +393,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D */ PowerManager.WakeLock mGoingToSleep; + /** + * 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>(); + /** Stack id of the front stack when user switched, indexed by userId. */ SparseIntArray mUserStackInFront = new SparseIntArray(2); @@ -3126,6 +3133,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return null; } + boolean hasAwakeDisplay() { + for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + if (!display.shouldSleep()) { + return true; + } + } + return false; + } + void goingToSleepLocked() { scheduleSleepTimeout(); if (!mGoingToSleep.isHeld()) { @@ -3138,7 +3155,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); } } - checkReadyForSleepLocked(); + + applySleepTokensLocked(false /* applyToStacks */); + + checkReadyForSleepLocked(true /* allowDelay */); + } + + void prepareForShutdownLocked() { + for (int i = 0; i < mActivityDisplays.size(); i++) { + createSleepTokenLocked("shutdown", mActivityDisplays.keyAt(i)); + } } boolean shutdownLocked(int timeout) { @@ -3151,7 +3177,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked(); + cantShutdown |= + stacks.get(stackNdx).goToSleepIfPossible(true /* shuttingDown */); } } if (cantShutdown) { @@ -3172,8 +3199,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } // Force checkReadyForSleep to complete. - mSleepTimeout = true; - checkReadyForSleepLocked(); + checkReadyForSleepLocked(false /* allowDelay */); return timedout; } @@ -3183,54 +3209,75 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (mGoingToSleep.isHeld()) { mGoingToSleep.release(); } + } + + void applySleepTokensLocked(boolean applyToStacks) { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + // Set the sleeping state of the display. + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + final boolean displayShouldSleep = display.shouldSleep(); + if (displayShouldSleep == display.isSleeping()) { + continue; + } + display.setIsSleeping(displayShouldSleep); + + if (!applyToStacks) { + continue; + } + + // Set the sleeping state of the stacks on the display. + final ArrayList<ActivityStack> stacks = display.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - stack.awakeFromSleepingLocked(); - if (isFocusedStack(stack)) { - resumeFocusedStackTopActivityLocked(); + if (displayShouldSleep) { + stack.goToSleepIfPossible(false /* shuttingDown */); + } else { + stack.awakeFromSleepingLocked(); + if (isFocusedStack(stack)) { + resumeFocusedStackTopActivityLocked(); + } + } + } + + if (displayShouldSleep || mGoingToSleepActivities.isEmpty()) { + continue; + } + // The display is awake now, so clean up the going to sleep list. + for (Iterator<ActivityRecord> it = mGoingToSleepActivities.iterator(); it.hasNext(); ) { + final ActivityRecord r = it.next(); + if (r.getDisplayId() == display.mDisplayId) { + it.remove(); } } } - mGoingToSleepActivities.clear(); } void activitySleptLocked(ActivityRecord r) { mGoingToSleepActivities.remove(r); - checkReadyForSleepLocked(); + final ActivityStack s = r.getStack(); + if (s != null) { + s.checkReadyForSleep(); + } else { + checkReadyForSleepLocked(true); + } } - void checkReadyForSleepLocked() { + void checkReadyForSleepLocked(boolean allowDelay) { if (!mService.isSleepingOrShuttingDownLocked()) { // Do not care. return; } - if (!mSleepTimeout) { + if (allowDelay) { boolean dontSleep = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; + final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx); + final ArrayList<ActivityStack> stacks = display.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked(); + dontSleep |= stacks.get(stackNdx).goToSleepIfPossible(false /* shuttingDown */); } } - if (mStoppingActivities.size() > 0) { - // Still need to tell some activities to stop; can't sleep yet. - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " - + mStoppingActivities.size() + " activities"); - scheduleIdleLocked(); - dontSleep = true; - } - - if (mGoingToSleepActivities.size() > 0) { - // Still need to tell some activities to sleep; can't sleep yet. - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " - + mGoingToSleepActivities.size() + " activities"); - dontSleep = true; - } - if (dontSleep) { return; } @@ -3239,13 +3286,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Send launch end powerhint before going sleep mService.mActivityStarter.sendPowerHintForLaunchEndIfNeeded(); - for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { - final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; - for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { - stacks.get(stackNdx).goToSleep(); - } - } - removeSleepTimeouts(); if (mGoingToSleep.isHeld()) { @@ -3516,21 +3556,27 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D s.setVisibility(false); } } - if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) { - if (!processPausingActivities && s.state == PAUSING) { - // Defer processing pausing activities in this iteration and reschedule - // a delayed idle to reprocess it again - removeTimeoutsForActivityLocked(idleActivity); - scheduleIdleTimeoutLocked(idleActivity); - continue; - } + if (remove) { + final ActivityStack stack = s.getStack(); + final boolean shouldSleepOrShutDown = stack != null + ? stack.shouldSleepOrShutDownActivities() + : mService.isSleepingOrShuttingDownLocked(); + if (!waitingVisible || shouldSleepOrShutDown) { + if (!processPausingActivities && s.state == PAUSING) { + // Defer processing pausing activities in this iteration and reschedule + // a delayed idle to reprocess it again + removeTimeoutsForActivityLocked(idleActivity); + scheduleIdleTimeoutLocked(idleActivity); + continue; + } - if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); - if (stops == null) { - stops = new ArrayList<>(); + if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s); + if (stops == null) { + stops = new ArrayList<>(); + } + stops.add(s); + mStoppingActivities.remove(activityNdx); } - stops.add(s); - mStoppingActivities.remove(activityNdx); } } @@ -3583,7 +3629,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D public void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack); pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack); - pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout); pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); @@ -3680,6 +3725,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D stackHeader.append("\n"); stackHeader.append(" mFullscreen=" + stack.mFullscreen); stackHeader.append("\n"); + stackHeader.append(" isSleeping=" + stack.shouldSleepActivities()); + stackHeader.append("\n"); stackHeader.append(" mBounds=" + stack.mBounds); final boolean printedStackHeader = stack.dumpActivitiesLocked(fd, pw, dumpAll, @@ -3731,8 +3778,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D " Activities waiting for another to become visible:", null); printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, false, dumpPackage, true, " Activities waiting to sleep:", null); - printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll, - false, dumpPackage, true, " Activities waiting to sleep:", null); return printed; } @@ -3843,7 +3888,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } void removeSleepTimeouts() { - mSleepTimeout = false; mHandler.removeMessages(SLEEP_TIMEOUT_MSG); } @@ -3945,6 +3989,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D moveTasksToFullscreenStackLocked(stack.getStackId(), true /* onTop */); } } + + releaseSleepTokens(activityDisplay); + mActivityDisplays.remove(displayId); mWindowManager.onDisplayRemoved(displayId); } @@ -3955,12 +4002,60 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay != null) { + // The window policy is responsible for stopping activities on the default display + if (displayId != Display.DEFAULT_DISPLAY) { + int displayState = activityDisplay.mDisplay.getState(); + if (displayState == Display.STATE_OFF && activityDisplay.mOffToken == null) { + activityDisplay.mOffToken = + mService.acquireSleepToken("Display-off", displayId); + } else if (displayState == Display.STATE_ON + && activityDisplay.mOffToken != null) { + activityDisplay.mOffToken.release(); + activityDisplay.mOffToken = null; + } + } // TODO: Update the bounds. } mWindowManager.onDisplayChanged(displayId); } } + SleepToken createSleepTokenLocked(String tag, int displayId) { + ActivityDisplay display = mActivityDisplays.get(displayId); + if (display == null) { + throw new IllegalArgumentException("Invalid display: " + displayId); + } + + final SleepTokenImpl token = new SleepTokenImpl(tag, displayId); + mSleepTokens.add(token); + display.mAllSleepTokens.add(token); + return token; + } + + private void removeSleepTokenLocked(SleepTokenImpl token) { + mSleepTokens.remove(token); + + ActivityDisplay display = mActivityDisplays.get(token.mDisplayId); + if (display != null) { + display.mAllSleepTokens.remove(token); + if (display.mAllSleepTokens.isEmpty()) { + mService.updateSleepIfNeededLocked(); + } + } + } + + private void releaseSleepTokens(ActivityDisplay display) { + if (display.mAllSleepTokens.isEmpty()) { + return; + } + for (SleepTokenImpl token : display.mAllSleepTokens) { + mSleepTokens.remove(token); + } + display.mAllSleepTokens.clear(); + + mService.updateSleepIfNeededLocked(); + } + private StackInfo getStackInfoLocked(ActivityStack stack) { final int displayId = stack.mDisplayId; final ActivityDisplay display = mActivityDisplays.get(displayId); @@ -4266,9 +4361,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D void activityRelaunchedLocked(IBinder token) { mWindowManager.notifyAppRelaunchingFinished(token); - if (mService.isSleepingOrShuttingDownLocked()) { - final ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r != null) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r != null) { + if (r.getStack().shouldSleepOrShutDownActivities()) { r.setSleeping(true, true); } } @@ -4420,8 +4515,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { if (mService.isSleepingOrShuttingDownLocked()) { Slog.w(TAG, "Sleep timeout! Sleeping now."); - mSleepTimeout = true; - checkReadyForSleepLocked(); + checkReadyForSleepLocked(false /* allowDelay */); } } } break; @@ -4546,6 +4640,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Array of all UIDs that are present on the display. */ private IntArray mDisplayAccessUIDs = new IntArray(); + /** All tokens used to put activities on this stack to sleep (including mOffToken) */ + final ArrayList<SleepTokenImpl> mAllSleepTokens = new ArrayList<>(); + /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */ + SleepToken mOffToken; + + private boolean mSleeping; + @VisibleForTesting ActivityDisplay() { mActivityDisplays.put(mDisplayId, this); @@ -4570,12 +4671,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (DEBUG_STACK) Slog.v(TAG_STACK, "attachStack: attaching " + stack + " to displayId=" + mDisplayId + " position=" + position); mStacks.add(position, stack); + mService.updateSleepIfNeededLocked(); } void detachStack(ActivityStack stack) { if (DEBUG_STACK) Slog.v(TAG_STACK, "detachStack: detaching " + stack + " from displayId=" + mDisplayId); mStacks.remove(stack); + mService.updateSleepIfNeededLocked(); } @Override @@ -4623,6 +4726,19 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean shouldDestroyContentOnRemove() { return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; } + + boolean shouldSleep() { + return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty()) + && (mService.mRunningVoice == null); + } + + boolean isSleeping() { + return mSleeping; + } + + void setIsSleeping(boolean asleep) { + mSleeping = asleep; + } } ActivityStack findStackBehind(ActivityStack stack) { @@ -4804,4 +4920,30 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mResult.dump(pw, prefix); } } + + private final class SleepTokenImpl extends SleepToken { + private final String mTag; + private final long mAcquireTime; + private final int mDisplayId; + + public SleepTokenImpl(String tag, int displayId) { + mTag = tag; + mDisplayId = displayId; + mAcquireTime = SystemClock.uptimeMillis(); + } + + @Override + public void release() { + synchronized (mService) { + removeSleepTokenLocked(this); + } + } + + @Override + public String toString() { + return "{\"" + mTag + "\", display " + mDisplayId + + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; + } + } + } diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 58e71df3ba57..cea80c8d0e9d 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; @@ -32,6 +33,7 @@ import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_OCCLUDE; import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE; import static com.android.server.wm.AppTransition.TRANSIT_UNSET; +import android.app.ActivityManagerInternal.SleepToken; import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; @@ -63,6 +65,7 @@ class KeyguardController { private ActivityRecord mDismissingKeyguardActivity; private int mBeforeUnoccludeTransit; private int mVisibilityTransactionDepth; + private SleepToken mSleepToken; KeyguardController(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) { @@ -102,7 +105,7 @@ class KeyguardController { mDismissalRequested = false; } mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); } /** @@ -122,7 +125,7 @@ class KeyguardController { mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */, convertTransitFlags(flags), false /* forceOverride */); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); // Some stack visibility might change (e.g. docked stack) mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); @@ -263,7 +266,7 @@ class KeyguardController { try { mWindowManager.prepareAppTransition(resolveOccludeTransit(), false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */); - mService.updateSleepIfNeededLocked(); + updateKeyguardSleepToken(); mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); } finally { @@ -333,6 +336,15 @@ class KeyguardController { } } + private void updateKeyguardSleepToken() { + if (mSleepToken == null && isKeyguardShowing()) { + mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY); + } else if (mSleepToken != null && !isKeyguardShowing()) { + mSleepToken.release(); + mSleepToken = null; + } + } + void dump(PrintWriter pw, String prefix) { pw.println(prefix + "KeyguardController:"); pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ae78d7c551c1..3c11a539dff6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -7466,10 +7466,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. private void updateDreamingSleepToken(boolean acquire) { if (acquire) { if (mDreamingSleepToken == null) { - mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); + mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken( + "Dream", Display.DEFAULT_DISPLAY); } } else { if (mDreamingSleepToken != null) { @@ -7479,10 +7481,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. private void updateScreenOffSleepToken(boolean acquire) { if (acquire) { if (mScreenOffSleepToken == null) { - mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); + mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken( + "ScreenOff", Display.DEFAULT_DISPLAY); } } else { if (mScreenOffSleepToken != null) { diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 2b3901b1febb..c2edc04db2e1 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -16,8 +16,8 @@ package com.android.server.wm; +import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; - import static com.android.server.wm.AppTransition.TRANSIT_UNSET; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; @@ -358,7 +358,7 @@ public class AppWindowAnimator { // This must be called while inside a transaction. boolean stepAnimationLocked(long currentTime) { - if (mService.okToAnimate()) { + if (mAppToken.okToAnimate()) { // We will run animations as long as the display isn't frozen. if (animation == sDummyAnimation) { @@ -423,8 +423,8 @@ public class AppWindowAnimator { if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + mAppToken + ": reportedVisible=" + mAppToken.reportedVisible - + " okToDisplay=" + mService.okToDisplay() - + " okToAnimate=" + mService.okToAnimate() + + " okToDisplay=" + mAppToken.okToDisplay() + + " okToAnimate=" + mAppToken.okToAnimate() + " startingDisplayed=" + mAppToken.startingDisplayed); transformation.clear(); diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index e9696d2ab46f..1ca98ac77e1c 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS; @@ -401,7 +402,7 @@ public class AppWindowContainerController // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. - if (mService.okToAnimate() && mService.mAppTransition.isTransitionSet()) { + if (wtoken.okToAnimate() && mService.mAppTransition.isTransitionSet()) { // A dummy animation is a placeholder animation which informs others that an // animation is going on (in this case an application transition). If the animation // was transferred from another application/animator, no dummy animator should be @@ -478,7 +479,7 @@ public class AppWindowContainerController // If the display is frozen, we won't do anything until the actual window is // displayed so there is no reason to put in the starting window. - if (!mService.okToDisplay()) { + if (!mContainer.okToDisplay()) { return false; } @@ -699,16 +700,17 @@ public class AppWindowContainerController public void startFreezingScreen(int configChanges) { synchronized(mWindowMap) { - if (configChanges == 0 && mService.okToDisplay()) { - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken); - return; - } - if (mContainer == null) { Slog.w(TAG_WM, "Attempted to freeze screen with non-existing app token: " + mContainer); return; } + + if (configChanges == 0 && mContainer.okToDisplay()) { + if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken); + return; + } + mContainer.startFreezingScreen(); } } diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java index 741492815bd7..6f9e45a66909 100644 --- a/services/core/java/com/android/server/wm/DimLayerController.java +++ b/services/core/java/com/android/server/wm/DimLayerController.java @@ -290,7 +290,7 @@ class DimLayerController { state.dimLayer.setLayer(dimLayer); } if (state.dimLayer.isAnimating()) { - if (!mDisplayContent.mService.okToAnimate()) { + if (!mDisplayContent.okToAnimate()) { // Jump to the end of the animation. state.dimLayer.show(); } else { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5bc4a6b23392..f0a375bf29f4 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3204,6 +3204,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mService.requestTraversal(); } + boolean okToDisplay() { + if (mDisplayId == DEFAULT_DISPLAY) { + return !mService.mDisplayFrozen + && mService.mDisplayEnabled && mService.mPolicy.isScreenOn(); + } + return mDisplayInfo.state == Display.STATE_ON; + } + + boolean okToAnimate() { + return okToDisplay() && + (mDisplayId != DEFAULT_DISPLAY || mService.mPolicy.okToAnimate()); + } + static final class TaskForResizePointSearchResult { boolean searchDone; Task taskForResize; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 5c664c2d16ce..e7f3de0b433f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2347,7 +2347,7 @@ public class WindowManagerService extends IWindowManager.Stub // artifacts when we unfreeze the display if some different animation // is running. Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked"); - if (okToAnimate()) { + if (atoken.okToAnimate()) { final DisplayContent displayContent = atoken.getTask().getDisplayContent(); final DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int width = displayInfo.appWidth; @@ -2425,14 +2425,6 @@ public class WindowManagerService extends IWindowManager.Stub return false; } - boolean okToDisplay() { - return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn(); - } - - boolean okToAnimate() { - return okToDisplay() && mPolicy.okToAnimate(); - } - @Override public void addWindowToken(IBinder binder, int type, int displayId) { if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) { @@ -2699,7 +2691,9 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent, flags, forceOverride); - if (prepared && okToAnimate()) { + // TODO (multidisplay): associate app transitions with displays + final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY); + if (prepared && dc != null && dc.okToAnimate()) { mSkipAppTransitionAnimation = false; } } @@ -5817,7 +5811,10 @@ public class WindowManagerService extends IWindowManager.Stub // If the screen is currently frozen or off, then keep // it frozen/off until this window draws at its new // orientation. - if (!okToDisplay() && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { + // TODO (multidisplay): Support screen freezing on secondary displays. + final DisplayContent dc = mRoot.getDisplayContent(DEFAULT_DISPLAY); + if ((dc == null || !dc.okToDisplay()) + && mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) { if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Changing surface while display frozen: " + w); w.setOrientationChanging(true); w.mLastFreezeDuration = 0; @@ -6033,7 +6030,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (!displayContent.isReady() || !mPolicy.isScreenOn() || !okToAnimate()) { + if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) { // No need to freeze the screen before the display is ready, if the screen is off, // or we can't currently animate. return; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 2b258c9d0fcc..da739ac93b14 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1711,7 +1711,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final boolean adjustedForMinimizedDockOrIme = task != null && (task.mStack.isAdjustedForMinimizedDockedStack() || task.mStack.isAdjustedForIme()); - if (mService.okToAnimate() + if (mToken.okToAnimate() && (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0 && !isDragResizing() && !adjustedForMinimizedDockOrIme && (task == null || getTask().mStack.hasMovementAnimations()) @@ -1880,7 +1880,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // First, see if we need to run an animation. If we do, we have to hold off on removing the // window until the animation is done. If the display is frozen, just remove immediately, // since the animation wouldn't be seen. - if (mHasSurface && mService.okToAnimate()) { + if (mHasSurface && mToken.okToAnimate()) { if (mWillReplaceWindow) { // This window is going to be replaced. We need to keep it around until the new one // gets added, then we will get rid of this one. @@ -2315,7 +2315,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mLayoutNeeded = true; } - if (isDrawnLw() && mService.okToAnimate()) { + if (isDrawnLw() && mToken.okToAnimate()) { mWinAnimator.applyEnterAnimationLocked(); } } @@ -2471,7 +2471,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (doAnimation) { if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility=" + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation); - if (!mService.okToAnimate()) { + if (!mToken.okToAnimate()) { doAnimation = false; } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) { // Check for the case where we are currently visible and @@ -2501,7 +2501,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP boolean hideLw(boolean doAnimation, boolean requestAnim) { if (doAnimation) { - if (!mService.okToAnimate()) { + if (!mToken.okToAnimate()) { doAnimation = false; } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 86265c297b1b..053ee970f9ae 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -369,7 +369,7 @@ class WindowStateAnimator { // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet(). mWasAnimating = mAnimating; final DisplayContent displayContent = mWin.getDisplayContent(); - if (displayContent != null && mService.okToAnimate()) { + if (mWin.mToken.okToAnimate()) { // We will run animations as long as the display isn't frozen. if (mWin.isDrawnLw() && mAnimation != null) { @@ -1812,7 +1812,7 @@ class WindowStateAnimator { // artifacts when we unfreeze the display if some different animation // is running. Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked"); - if (mService.okToAnimate()) { + if (mWin.mToken.okToAnimate()) { int anim = mPolicy.selectAnimationLw(mWin, transit); int attr = -1; Animation a = null; diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index e3033c9c01a8..48d1618c1c91 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -288,4 +288,12 @@ class WindowToken extends WindowContainer<WindowState> { String getName() { return toString(); } + + boolean okToDisplay() { + return mDisplayContent != null && mDisplayContent.okToDisplay(); + } + + boolean okToAnimate() { + return mDisplayContent != null && mDisplayContent.okToAnimate(); + } } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java index 48464e5e0248..ba221591fc92 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java @@ -78,7 +78,7 @@ public class ActivityStackTests extends ActivityTestsBase { service.mStackSupervisor.inResumeTopActivity = true; testStack.mResumedActivity = activityRecord; - final boolean waiting = testStack.checkReadyForSleepLocked(); + final boolean waiting = testStack.goToSleepIfPossible(false); // Ensure we report not being ready for sleep. assertTrue(waiting); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 04b5bdebdca1..4ad92c7ec14e 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -218,6 +218,12 @@ public class ActivityTestsBase { return createTestStack(stackId, createOnTop); } + + // Always keep things awake + @Override + boolean hasAwakeDisplay() { + return true; + } } private static WindowManagerService prepareMockWindowManager() { |