Show recents at correct time when starting activity in docked stack
Previous logic relied on the returnTo type of the task of the activity
we are launching which can get the wrong signal at times because the
original task might have been started from home, but since we are
already in docked mode it shouldn't cause recents activity to be
launched.
We now decide if recents ability should be shown based on if the home
stack is currently visible at the time we started the new activity.
Also, renamed ActivityStack.getStackVisibilityLocked() to
ActivityStack.shouldBeVisible() since it is used to determine if the
stack should be visible and also so it isn't confused with the new
method ActivityStack.isVisible() which returns true if the stack is
currently visible.
Test: manual
Change-Id: I051e72ce93c886d25526af2afef851c95812ab3e
Fixes: 37005549
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 5edfb06..2881787 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -102,7 +102,7 @@
mLastLogTimeSecs = now;
ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
- if (stack != null && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
+ if (stack != null && stack.shouldBeVisible(null) != STACK_INVISIBLE) {
mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
return;
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index f13b11e..d4b36ff 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -116,7 +116,6 @@
import android.util.SparseArray;
import android.view.Display;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
@@ -1560,12 +1559,18 @@
return true;
}
+ /** Returns true if the stack is currently considered visible. */
+ boolean isVisible() {
+ return mWindowContainerController != null && mWindowContainerController.isVisible();
+ }
+
/**
- * Returns stack's visibility: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE} or
- * {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
+ * Returns what the stack visibility should be: {@link #STACK_INVISIBLE}, {@link #STACK_VISIBLE}
+ * or {@link #STACK_VISIBLE_ACTIVITY_BEHIND}.
+ *
* @param starting The currently starting activity or null if there is none.
*/
- int getStackVisibilityLocked(ActivityRecord starting) {
+ int shouldBeVisible(ActivityRecord starting) {
if (!isAttached()) {
return STACK_INVISIBLE;
}
@@ -1715,7 +1720,7 @@
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = top != null;
- final int stackVisibility = getStackVisibilityLocked(starting);
+ final int stackVisibility = shouldBeVisible(starting);
final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
boolean behindFullscreenActivity = stackInvisible;
@@ -2097,7 +2102,7 @@
// activities as we need to display their starting window until they are done initializing.
boolean behindFullscreenActivity = false;
- if (getStackVisibilityLocked(null) == STACK_INVISIBLE) {
+ if (shouldBeVisible(null) == STACK_INVISIBLE) {
// The stack is not visible, so no activity in it should be displaying a starting
// window. Mark all activities below top and behind fullscreen.
aboveTop = false;
@@ -4184,7 +4189,7 @@
if (hasVisibleBehindActivity() &&
!mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
if (r == topRunningActivityLocked()
- && getStackVisibilityLocked(null) == STACK_VISIBLE) {
+ && shouldBeVisible(null) == STACK_VISIBLE) {
// Don't release the top activity if it has requested to run behind the next
// activity and the stack is currently visible.
return;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 3e3fee5..ecf5647 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -164,7 +164,6 @@
import android.view.InputEvent;
import android.view.Surface;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -174,7 +173,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.wm.StackWindowController;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -2184,7 +2182,7 @@
for (int j = stacks.size() - 1; j >= 0; --j) {
final ActivityStack stack = stacks.get(j);
if (stack != currentFocus && stack.isFocusable()
- && stack.getStackVisibilityLocked(null) != STACK_INVISIBLE) {
+ && stack.shouldBeVisible(null) != STACK_INVISIBLE) {
return stack;
}
}
@@ -2345,7 +2343,7 @@
}
ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
final boolean isFullscreenStackVisible = fullscreenStack != null &&
- fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
+ fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE;
// If we are moving from the pinned stack, then the animation takes care of updating
// the picture-in-picture mode.
final boolean schedulePictureInPictureModeChange = (fromStackId != PINNED_STACK_ID);
@@ -2520,7 +2518,7 @@
final ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID);
if (fullscreenStack != null) {
final boolean isFullscreenStackVisible =
- fullscreenStack.getStackVisibilityLocked(null) == STACK_VISIBLE;
+ fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE;
for (int i = 0; i < tasks.size(); i++) {
// Insert the task either at the top of the fullscreen stack if it is hidden,
// or to the bottom if it is currently visible
@@ -3545,7 +3543,7 @@
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
ActivityStack stack = stacks.get(stackNdx);
if (!dumpVisibleStacksOnly ||
- stack.getStackVisibilityLocked(null) == STACK_VISIBLE) {
+ stack.shouldBeVisible(null) == STACK_VISIBLE) {
activities.addAll(stack.getDumpActivitiesLocked(name));
}
}
@@ -3852,7 +3850,7 @@
info.displayId = DEFAULT_DISPLAY;
info.stackId = stack.mStackId;
info.userId = stack.mCurrentUser;
- info.visible = stack.getStackVisibilityLocked(null) == STACK_VISIBLE;
+ info.visible = stack.shouldBeVisible(null) == STACK_VISIBLE;
info.position = display != null
? display.mStacks.indexOf(stack)
: 0;
@@ -4971,7 +4969,7 @@
for (int j = display.mStacks.size() - 1; j >= 0; j--) {
final ActivityStack stack = display.mStacks.get(j);
// Get top activity from a visible stack and add it to the list.
- if (stack.getStackVisibilityLocked(null /* starting */)
+ if (stack.shouldBeVisible(null /* starting */)
== ActivityStack.STACK_VISIBLE) {
final ActivityRecord top = stack.topActivity();
if (top != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index b408569..eab92df 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -74,7 +74,6 @@
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
@@ -118,14 +117,11 @@
import android.service.voice.IVoiceInteractionSession;
import android.util.EventLog;
import android.util.Slog;
-import android.view.Display;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
-import com.android.server.LocalServices;
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.pm.InstantAppResolver;
-import com.android.server.vr.VrManagerInternal;
import com.android.server.wm.WindowManagerService;
import java.util.ArrayList;
@@ -562,31 +558,17 @@
startedActivityStackId = targetStack.mStackId;
}
- // If we launched the activity from a no display activity that was launched from the home
- // screen, we also need to start recents to un-minimize the docked stack, since the
- // noDisplay activity will be finished shortly after.
- // Note that some apps have trampoline activities without noDisplay being set. In that case,
- // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
- // that tries to detect that case.
- // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
- // visibility instead of using this flag.
- final boolean noDisplayActivityOverHome = sourceRecord != null
- && sourceRecord.noDisplay
- && sourceRecord.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
- if (startedActivityStackId == DOCKED_STACK_ID
- && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
+ if (startedActivityStackId == DOCKED_STACK_ID) {
final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
- final ActivityRecord topActivityHomeStack = homeStack != null
- ? homeStack.topRunningActivityLocked() : null;
- if (topActivityHomeStack == null
- || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
+ final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
+ if (homeStackVisible) {
// We launch an activity while being in home stack, which means either launcher or
// recents into docked stack. We don't want the launched activity to be alone in a
// docked stack, so we want to immediately launch recents too.
if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
mWindowManager.showRecentApps(true /* fromHome */);
- return;
}
+ return;
}
if (startedActivityStackId == PINNED_STACK_ID
@@ -2150,7 +2132,7 @@
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
if (dockedStack != null
- && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
+ && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
} else {
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 635527e..5d0384e 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -94,6 +94,12 @@
}
}
+ public boolean isVisible() {
+ synchronized (mWindowMap) {
+ return mContainer != null && mContainer.isVisible();
+ }
+ }
+
public void reparent(int displayId, Rect outStackBounds) {
synchronized (mWindowMap) {
if (mContainer == null) {
@@ -363,7 +369,7 @@
}
/** Calls directly into activity manager so window manager lock shouldn't held. */
- public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+ void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
if (mListener != null) {
mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
}