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:
@@ -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;
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user