Merge "Fixed Task#getVisibility to take into account task hierarchy" into rvc-dev am: 872afaeaeb am: def5442913 am: 697fc09040

Change-Id: Ifd3c34bc67b5b2bccaf348d1d679b13745434234
This commit is contained in:
TreeHugger Robot
2020-04-18 03:22:58 +00:00
committed by Automerger Merge Worker
11 changed files with 278 additions and 226 deletions

View File

@@ -2791,7 +2791,9 @@ public class ActivityManager {
@UnsupportedAppUsage
public boolean visible;
// Index of the stack in the display's stack list, can be used for comparison of stack order
// TODO: Can be removed since no one is using it.
@UnsupportedAppUsage
@Deprecated
public int position;
public WindowContainerToken stackToken;
/**

View File

@@ -2183,7 +2183,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean isInStackLocked() {
final ActivityStack stack = getRootTask();
return stack != null && stack.isInStackLocked(this) != null;
return stack != null && stack.isInTask(this) != null;
}
boolean isPersistable() {
@@ -5588,7 +5588,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
static ActivityRecord isInStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
return (r != null) ? r.getRootTask().isInStackLocked(r) : null;
return (r != null) ? r.getRootTask().isInTask(r) : null;
}
static ActivityStack getStackLocked(IBinder token) {

View File

@@ -259,11 +259,9 @@ class ActivityStack extends Task {
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
/** For Pinned stack controlling. */
private Rect mTmpToBounds = new Rect();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
// TODO: This is no longer set. Okay to remove or was the set removed by accident?
private boolean mDeferRemoval;
// If this is true, we are in the bounds animating mode. The task will be down or upscaled to
@@ -281,7 +279,6 @@ class ActivityStack extends Task {
/**
* For {@link #prepareSurfaces}.
*/
private final Rect mTmpDimBoundsRect = new Rect();
private final Point mLastSurfaceSize = new Point();
private final AnimatingActivityRegistry mAnimatingActivityRegistry =
@@ -290,9 +287,6 @@ class ActivityStack extends Task {
/** Stores the override windowing-mode from before a transient mode change (eg. split) */
private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
/** List for processing through a set of activities */
private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -605,9 +599,6 @@ class ActivityStack extends Task {
final int prevWindowingMode = getWindowingMode();
final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
final int prevRotation = getWindowConfiguration().getRotation();
final int prevDensity = getConfiguration().densityDpi;
final int prevScreenW = getConfiguration().screenWidthDp;
final int prevScreenH = getConfiguration().screenHeightDp;
final Rect newBounds = mTmpRect;
// Initialize the new bounds by previous bounds as the input and output for calculating
// override bounds in pinned (pip) or split-screen mode.
@@ -920,70 +911,6 @@ class ActivityStack extends Task {
return false;
}
ActivityRecord topRunningActivity() {
return topRunningActivity(false /* focusableOnly */);
}
ActivityRecord topRunningActivity(boolean focusableOnly) {
// Split into 2 to avoid object creation due to variable capture.
if (focusableOnly) {
return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
} else {
return getActivity(ActivityRecord::canBeTopRunning);
}
}
private ActivityRecord topRunningNonOverlayTaskActivity() {
return getActivity((r) -> (r.canBeTopRunning() && !r.isTaskOverlay()));
}
ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isTopRunningNonDelayed
, PooledLambda.__(ActivityRecord.class), notTop);
final ActivityRecord r = getActivity(p);
p.recycle();
return r;
}
private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
return !r.delayedResume && r != notTop && r.canBeTopRunning();
}
/**
* This is a simplified version of topRunningActivity that provides a number of
* optional skip-over modes. It is intended for use with the ActivityController hook only.
*
* @param token If non-null, any history records matching this token will be skipped.
* @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
*
* @return Returns the HistoryRecord of the next activity on the stack.
*/
ActivityRecord topRunningActivity(IBinder token, int taskId) {
final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isTopRunning,
PooledLambda.__(ActivityRecord.class), taskId, token);
final ActivityRecord r = getActivity(p);
p.recycle();
return r;
}
private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
}
ActivityRecord isInStackLocked(ActivityRecord r) {
if (r == null) {
return null;
}
final Task task = r.getRootTask();
if (task != null && r.isDescendantOf(task)) {
if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
+ "stack=" + this + " task=" + task + " r=" + r
+ " callers=" + Debug.getCallers(15, "\n"));
return r;
}
return null;
}
/** @return true if the stack can only contain one task */
boolean isSingleTaskInstance() {
final DisplayContent display = getDisplay();
@@ -1106,12 +1033,6 @@ class ActivityStack extends Task {
return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
}
@Override
public boolean isAttached() {
final TaskDisplayArea taskDisplayArea = getDisplayArea();
return taskDisplayArea != null && !taskDisplayArea.isRemoved();
}
// TODO: Should each user have there own stacks?
@Override
void switchUser(int userId) {
@@ -1462,140 +1383,6 @@ class ActivityStack extends Task {
return display != null && this == display.getFocusedStack();
}
/**
* Returns true if the stack should be visible.
*
* @param starting The currently starting activity or null if there is none.
*/
@Override
boolean shouldBeVisible(ActivityRecord starting) {
return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
}
/**
* Returns true if the stack should be visible.
*
* @param starting The currently starting activity or null if there is none.
*/
@StackVisibility
int getVisibility(ActivityRecord starting) {
if (!isAttached() || isForceHidden()) {
return STACK_VISIBILITY_INVISIBLE;
}
final TaskDisplayArea taskDisplayArea = getDisplayArea();
boolean gotSplitScreenStack = false;
boolean gotOpaqueSplitScreenPrimary = false;
boolean gotOpaqueSplitScreenSecondary = false;
boolean gotTranslucentFullscreen = false;
boolean gotTranslucentSplitScreenPrimary = false;
boolean gotTranslucentSplitScreenSecondary = false;
boolean shouldBeVisible = true;
final int windowingMode = getWindowingMode();
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = taskDisplayArea.getStackCount() - 1; i >= 0; --i) {
final ActivityStack other = taskDisplayArea.getStackAt(i);
final boolean hasRunningActivities = other.topRunningActivity() != null;
if (other == this) {
// Should be visible if there is no other stack occluding it, unless it doesn't
// have any running activities, not starting one and not home stack.
shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null
|| isActivityTypeHome();
break;
}
if (!hasRunningActivities) {
continue;
}
final int otherWindowingMode = other.getWindowingMode();
if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
// In this case the home stack isn't resizeable even though we are in split-screen
// mode. We still want the primary splitscreen stack to be visible as there will be
// a slight hint of it in the status bar area above the non-resizeable home
// activity. In addition, if the fullscreen assistant is over primary splitscreen
// stack, the stack should still be visible in the background as long as the recents
// animation is running.
final int activityType = other.getActivityType();
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (activityType == ACTIVITY_TYPE_HOME
|| (activityType == ACTIVITY_TYPE_ASSISTANT
&& mWmService.getRecentsAnimationController() != null)) {
break;
}
}
if (other.isTranslucent(starting)) {
// Can be visible behind a translucent fullscreen stack.
gotTranslucentFullscreen = true;
continue;
}
return STACK_VISIBILITY_INVISIBLE;
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotSplitScreenStack = true;
gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& gotOpaqueSplitScreenPrimary) {
// Can not be visible behind another opaque stack in split-screen-primary mode.
return STACK_VISIBILITY_INVISIBLE;
}
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& !gotOpaqueSplitScreenSecondary) {
gotSplitScreenStack = true;
gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& gotOpaqueSplitScreenSecondary) {
// Can not be visible behind another opaque stack in split-screen-secondary mode.
return STACK_VISIBILITY_INVISIBLE;
}
}
if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
// Can not be visible if we are in split-screen windowing mode and both halves of
// the screen are opaque.
return STACK_VISIBILITY_INVISIBLE;
}
if (isAssistantType && gotSplitScreenStack) {
// Assistant stack can't be visible behind split-screen. In addition to this not
// making sense, it also works around an issue here we boost the z-order of the
// assistant window surfaces in window manager whenever it is visible.
return STACK_VISIBILITY_INVISIBLE;
}
}
if (!shouldBeVisible) {
return STACK_VISIBILITY_INVISIBLE;
}
// Handle cases when there can be a translucent split-screen stack on top.
switch (windowingMode) {
case WINDOWING_MODE_FULLSCREEN:
if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
// At least one of the split-screen stacks that covers this one is translucent.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
if (gotTranslucentSplitScreenPrimary) {
// Covered by translucent primary split-screen on top.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
if (gotTranslucentSplitScreenSecondary) {
// Covered by translucent secondary split-screen on top.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
}
// Lastly - check if there is a translucent fullscreen stack on top.
return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
: STACK_VISIBILITY_VISIBLE;
}
/**
* Make sure that all activities that need to be visible in the stack (that is, they
* currently can be seen by the user) actually are and update their configuration.

View File

@@ -4065,7 +4065,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return r != null
&& r.getRootTask() != null
&& r.inPinnedWindowingMode()
&& r.getRootTask().isInStackLocked(r) != null;
&& r.getRootTask().isInTask(r) != null;
}
@Override

View File

@@ -1398,10 +1398,9 @@ class RecentTasks {
return false;
}
// Trim tasks that are in stacks that are behind the home stack
// Trim tasks that are behind the home task.
final TaskDisplayArea taskDisplayArea = stack.getDisplayArea();
return taskDisplayArea.getIndexOf(stack) < taskDisplayArea.getIndexOf(
taskDisplayArea.getRootHomeTask());
return task.compareTo(taskDisplayArea.getRootHomeTask()) < 0;
}
/** Remove the tasks that user may not be able to return. */

View File

@@ -302,7 +302,7 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// Prefer to use the original target activity instead of top activity because
// we may have moved another task to top (starting 3p launcher).
final ActivityRecord targetActivity = targetStack != null
? targetStack.isInStackLocked(mLaunchedTargetActivity)
? targetStack.isInTask(mLaunchedTargetActivity)
: null;
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
"onAnimationFinished(): targetStack=%s targetActivity=%s "

View File

@@ -2425,6 +2425,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
// TODO: Can be removed since no one is using it.
info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(stack) : 0;
info.configuration.setTo(stack.getConfiguration());

View File

@@ -65,6 +65,9 @@ import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -2346,7 +2349,9 @@ class Task extends WindowContainer<WindowContainer> {
int windowingMode =
getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = inSplitScreenWindowingMode() ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
windowingMode = parentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
: WINDOWING_MODE_FULLSCREEN;
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
}
@@ -3138,6 +3143,52 @@ class Task extends WindowContainer<WindowContainer> {
return activity != null ? activity.findMainWindow() : null;
}
ActivityRecord topRunningActivity() {
return topRunningActivity(false /* focusableOnly */);
}
ActivityRecord topRunningActivity(boolean focusableOnly) {
// Split into 2 to avoid object creation due to variable capture.
if (focusableOnly) {
return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
} else {
return getActivity(ActivityRecord::canBeTopRunning);
}
}
ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed
, PooledLambda.__(ActivityRecord.class), notTop);
final ActivityRecord r = getActivity(p);
p.recycle();
return r;
}
private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
return !r.delayedResume && r != notTop && r.canBeTopRunning();
}
/**
* This is a simplified version of topRunningActivity that provides a number of
* optional skip-over modes. It is intended for use with the ActivityController hook only.
*
* @param token If non-null, any history records matching this token will be skipped.
* @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
*
* @return Returns the HistoryRecord of the next activity on the stack.
*/
ActivityRecord topRunningActivity(IBinder token, int taskId) {
final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning,
PooledLambda.__(ActivityRecord.class), taskId, token);
final ActivityRecord r = getActivity(p);
p.recycle();
return r;
}
private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
}
ActivityRecord getTopFullscreenActivity() {
return getActivity((r) -> {
final WindowState win = r.findMainWindow();
@@ -3440,9 +3491,169 @@ class Task extends WindowContainer<WindowContainer> {
return this;
}
// TODO(task-merge): Figure-out how this should work with hierarchy tasks.
/**
* Returns true if the task should be visible.
*
* @param starting The currently starting activity or null if there is none.
*/
boolean shouldBeVisible(ActivityRecord starting) {
return true;
return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
}
/**
* Returns true if the task should be visible.
*
* @param starting The currently starting activity or null if there is none.
*/
@ActivityStack.StackVisibility
int getVisibility(ActivityRecord starting) {
if (!isAttached() || isForceHidden()) {
return STACK_VISIBILITY_INVISIBLE;
}
boolean gotSplitScreenStack = false;
boolean gotOpaqueSplitScreenPrimary = false;
boolean gotOpaqueSplitScreenSecondary = false;
boolean gotTranslucentFullscreen = false;
boolean gotTranslucentSplitScreenPrimary = false;
boolean gotTranslucentSplitScreenSecondary = false;
boolean shouldBeVisible = true;
// This stack is only considered visible if all its parent stacks are considered visible,
// so check the visibility of all ancestor stacks first.
final WindowContainer parent = getParent();
if (parent.asTask() != null) {
final int parentVisibility = parent.asTask().getVisibility(starting);
if (parentVisibility == STACK_VISIBILITY_INVISIBLE) {
// Can't be visible if parent isn't visible
return STACK_VISIBILITY_INVISIBLE;
} else if (parentVisibility == STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
// Parent is behind a translucent container so the highest visibility this container
// can get is that.
gotTranslucentFullscreen = true;
}
}
final int windowingMode = getWindowingMode();
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = parent.getChildCount() - 1; i >= 0; --i) {
final WindowContainer wc = parent.getChildAt(i);
final Task other = wc.asTask();
if (other == null) continue;
final boolean hasRunningActivities = other.topRunningActivity() != null;
if (other == this) {
// Should be visible if there is no other stack occluding it, unless it doesn't
// have any running activities, not starting one and not home stack.
shouldBeVisible = hasRunningActivities || isInTask(starting) != null
|| isActivityTypeHome();
break;
}
if (!hasRunningActivities) {
continue;
}
final int otherWindowingMode = other.getWindowingMode();
if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
// In this case the home stack isn't resizeable even though we are in split-screen
// mode. We still want the primary splitscreen stack to be visible as there will be
// a slight hint of it in the status bar area above the non-resizeable home
// activity. In addition, if the fullscreen assistant is over primary splitscreen
// stack, the stack should still be visible in the background as long as the recents
// animation is running.
final int activityType = other.getActivityType();
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (activityType == ACTIVITY_TYPE_HOME
|| (activityType == ACTIVITY_TYPE_ASSISTANT
&& mWmService.getRecentsAnimationController() != null)) {
break;
}
}
if (other.isTranslucent(starting)) {
// Can be visible behind a translucent fullscreen stack.
gotTranslucentFullscreen = true;
continue;
}
return STACK_VISIBILITY_INVISIBLE;
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotSplitScreenStack = true;
gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& gotOpaqueSplitScreenPrimary) {
// Can not be visible behind another opaque stack in split-screen-primary mode.
return STACK_VISIBILITY_INVISIBLE;
}
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& !gotOpaqueSplitScreenSecondary) {
gotSplitScreenStack = true;
gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& gotOpaqueSplitScreenSecondary) {
// Can not be visible behind another opaque stack in split-screen-secondary mode.
return STACK_VISIBILITY_INVISIBLE;
}
}
if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
// Can not be visible if we are in split-screen windowing mode and both halves of
// the screen are opaque.
return STACK_VISIBILITY_INVISIBLE;
}
if (isAssistantType && gotSplitScreenStack) {
// Assistant stack can't be visible behind split-screen. In addition to this not
// making sense, it also works around an issue here we boost the z-order of the
// assistant window surfaces in window manager whenever it is visible.
return STACK_VISIBILITY_INVISIBLE;
}
}
if (!shouldBeVisible) {
return STACK_VISIBILITY_INVISIBLE;
}
// Handle cases when there can be a translucent split-screen stack on top.
switch (windowingMode) {
case WINDOWING_MODE_FULLSCREEN:
if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
// At least one of the split-screen stacks that covers this one is translucent.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
if (gotTranslucentSplitScreenPrimary) {
// Covered by translucent primary split-screen on top.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
if (gotTranslucentSplitScreenSecondary) {
// Covered by translucent secondary split-screen on top.
return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
}
break;
}
// Lastly - check if there is a translucent fullscreen stack on top.
return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
: STACK_VISIBILITY_VISIBLE;
}
ActivityRecord isInTask(ActivityRecord r) {
if (r == null) {
return null;
}
final Task task = r.getRootTask();
if (task != null && r.isDescendantOf(task)) {
if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
+ "stack=" + this + " task=" + task + " r=" + r
+ " callers=" + Debug.getCallers(15, "\n"));
return r;
}
return null;
}
void dump(PrintWriter pw, String prefix) {

View File

@@ -184,6 +184,7 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
return count > 0 ? getChildAt(count - 1) : null;
}
// TODO: Figure-out a way to remove since it might be a source of confusion.
int getIndexOf(ActivityStack stack) {
return mChildren.indexOf(stack);
}
@@ -690,7 +691,7 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
// the position internally, also update the logic here
final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
? getFocusedStack() : null;
final boolean wasContained = getIndexOf(stack) >= 0;
final boolean wasContained = mChildren.contains(stack);
if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
throw new IllegalStateException(
"positionStackAt: Can only have one task on display=" + this);

View File

@@ -3532,7 +3532,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mClient.insetsControlChanged(getInsetsState(),
stateController.getControlsForDispatch(this));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to deliver inset state change", e);
Slog.w(TAG, "Failed to deliver inset state change to w=" + this, e);
}
}

View File

@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -44,6 +45,7 @@ import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
import static com.android.server.wm.Task.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.TaskDisplayArea.getStackAbove;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -488,6 +490,55 @@ public class ActivityStackTests extends ActivityTestsBase {
splitScreenSecondary2.getVisibility(null /* starting */));
}
@Test
public void testGetVisibility_MultiLevel() {
final ActivityStack homeStack = createStackForShouldBeVisibleTest(
mDefaultTaskDisplayArea, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME,
true /* onTop */);
final ActivityStack splitPrimary = createStackForShouldBeVisibleTest(
mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
ACTIVITY_TYPE_UNDEFINED, true /* onTop */);
final ActivityStack splitSecondary = createStackForShouldBeVisibleTest(
mDefaultTaskDisplayArea, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
ACTIVITY_TYPE_UNDEFINED, true /* onTop */);
doReturn(false).when(homeStack).isTranslucent(any());
doReturn(false).when(splitPrimary).isTranslucent(any());
doReturn(false).when(splitSecondary).isTranslucent(any());
// Re-parent home to split secondary.
homeStack.reparent(splitSecondary, POSITION_TOP);
// Current tasks should be visible.
assertEquals(STACK_VISIBILITY_VISIBLE, splitPrimary.getVisibility(null /* starting */));
assertEquals(STACK_VISIBILITY_VISIBLE, splitSecondary.getVisibility(null /* starting */));
// Home task should still be visible even though it is a child of another visible task.
assertEquals(STACK_VISIBILITY_VISIBLE, homeStack.getVisibility(null /* starting */));
// Add fullscreen translucent task that partially occludes split tasks
final ActivityStack translucentStack = createStandardStackForVisibilityTest(
WINDOWING_MODE_FULLSCREEN, true /* translucent */);
// Fullscreen translucent task should be visible
assertEquals(STACK_VISIBILITY_VISIBLE, translucentStack.getVisibility(null /* starting */));
// Split tasks should be visible behind translucent
assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
splitPrimary.getVisibility(null /* starting */));
assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
splitSecondary.getVisibility(null /* starting */));
// Home task should be visible behind translucent since its parent is visible behind
// translucent.
assertEquals(STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
homeStack.getVisibility(null /* starting */));
// Hide split-secondary
splitSecondary.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, true /* set */);
// Home split secondary and home task should be invisible.
assertEquals(STACK_VISIBILITY_INVISIBLE, splitSecondary.getVisibility(null /* starting */));
assertEquals(STACK_VISIBILITY_INVISIBLE, homeStack.getVisibility(null /* starting */));
}
@Test
public void testGetVisibility_FullscreenBehindTranslucent() {
final ActivityStack bottomStack =