summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Stevens <stevensd@google.com> 2017-08-16 23:15:05 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-08-16 23:15:05 +0000
commit341cd735cb7ba5d3b2c6f9b17eceef7059e4dc67 (patch)
tree1de74e01fa3c7d0f170116fb5fc546521eadc602
parent70aa7bbc81e6ae6352b5f391eef3a62d85c163c5 (diff)
parentf62360cafa21aef36f2176512d4a5241ae38aa8c (diff)
Merge "DO NOT MERGE Let external activities run when the primary display is off" into oc-mr1-dev
-rw-r--r--core/java/android/app/ActivityManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java128
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java96
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java264
-rw-r--r--services/core/java/com/android/server/am/KeyguardController.java18
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java8
-rw-r--r--services/core/java/com/android/server/wm/AppWindowAnimator.java8
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerController.java16
-rw-r--r--services/core/java/com/android/server/wm/DimLayerController.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java6
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() {