diff options
5 files changed, 49 insertions, 125 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c687bbf107b2..a87fe615e4df 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4605,8 +4605,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } - final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity( - this, null /* handleBehindFullscreenActivity */); + final boolean behindFullscreenActivity = !stack.shouldBeVisible(null /* starting */) + || stack.getOccludingActivityAbove(this) != null; return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */); } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 601d64b24439..ea9aab71bcb0 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -328,81 +328,6 @@ class ActivityStack extends Task { } } - private final CheckBehindFullscreenActivityHelper mCheckBehindFullscreenActivityHelper = - new CheckBehindFullscreenActivityHelper(); - private class CheckBehindFullscreenActivityHelper { - private boolean mAboveTop; - private boolean mBehindFullscreenActivity; - private ActivityRecord mToCheck; - private Consumer<ActivityRecord> mHandleBehindFullscreenActivity; - private boolean mHandlingOccluded; - - private void reset(ActivityRecord toCheck, - Consumer<ActivityRecord> handleBehindFullscreenActivity) { - mToCheck = toCheck; - mHandleBehindFullscreenActivity = handleBehindFullscreenActivity; - mAboveTop = true; - mBehindFullscreenActivity = false; - - if (!shouldBeVisible(null)) { - // The stack is not visible, so no activity in it should be displaying a starting - // window. Mark all activities below top and behind fullscreen. - mAboveTop = false; - mBehindFullscreenActivity = true; - } - - mHandlingOccluded = mToCheck == null && mHandleBehindFullscreenActivity != null; - } - - boolean process(ActivityRecord toCheck, - Consumer<ActivityRecord> handleBehindFullscreenActivity) { - reset(toCheck, handleBehindFullscreenActivity); - - if (!mHandlingOccluded && mBehindFullscreenActivity) { - return true; - } - - final ActivityRecord topActivity = topRunningActivity(); - final PooledFunction f = PooledLambda.obtainFunction( - CheckBehindFullscreenActivityHelper::processActivity, this, - PooledLambda.__(ActivityRecord.class), topActivity); - forAllActivities(f); - f.recycle(); - - return mBehindFullscreenActivity; - } - - /** Returns {@code true} to stop the outer loop and indicate the result is computed. */ - private boolean processActivity(ActivityRecord r, ActivityRecord topActivity) { - if (mAboveTop) { - if (r == topActivity) { - if (r == mToCheck) { - // It is the top activity in a visible stack. - mBehindFullscreenActivity = false; - return true; - } - mAboveTop = false; - } - mBehindFullscreenActivity |= r.occludesParent(); - return false; - } - - if (mHandlingOccluded) { - // Iterating through all occluded activities. - if (mBehindFullscreenActivity) { - mHandleBehindFullscreenActivity.accept(r); - } - } else if (r == mToCheck) { - return true; - } else if (mBehindFullscreenActivity) { - // It is occluded before {@param toCheck} is found. - return true; - } - mBehindFullscreenActivity |= r.occludesParent(); - return false; - } - } - // TODO: Can we just loop through WindowProcessController#mActivities instead of doing this? private final RemoveHistoryRecordsForApp mRemoveHistoryRecordsForApp = new RemoveHistoryRecordsForApp(); @@ -1434,25 +1359,6 @@ class ActivityStack extends Task { } } - /** @see ActivityRecord#cancelInitializing() */ - void cancelInitializingActivities() { - // We don't want to clear starting window for activities that aren't behind fullscreen - // activities as we need to display their starting window until they are done initializing. - checkBehindFullscreenActivity(null /* toCheck */, ActivityRecord::cancelInitializing); - } - - /** - * If an activity {@param toCheck} is given, this method returns {@code true} if the activity - * is occluded by any fullscreen activity. If there is no {@param toCheck} and the handling - * function {@param handleBehindFullscreenActivity} is given, this method will pass all occluded - * activities to the function. - */ - boolean checkBehindFullscreenActivity(ActivityRecord toCheck, - Consumer<ActivityRecord> handleBehindFullscreenActivity) { - return mCheckBehindFullscreenActivityHelper.process( - toCheck, handleBehindFullscreenActivity); - } - /** * Ensure that the top activity in the stack is resumed. * @@ -2660,16 +2566,6 @@ class ActivityStack extends Task { task.setBounds(task.isResizeable() ? bounds : null); } - /** - * Returns the top-most activity that occludes the given one, or @{code null} if none. - */ - @Nullable - private ActivityRecord getOccludingActivityAbove(ActivityRecord activity) { - ActivityRecord top = getActivity((ar) -> ar.occludesParent(), - true /* traverseTopToBottom */, activity); - return top != activity ? top : null; - } - boolean willActivityBeVisible(IBinder token) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r == null) { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 8bc98ce2d2d3..40f8fab510ba 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3353,7 +3353,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> void cancelInitializingActivities() { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { - taskDisplayArea.getStackAt(sNdx).cancelInitializingActivities(); + // We don't want to clear starting window for activities that aren't occluded + // as we need to display their starting window until they are done initializing. + taskDisplayArea.getStackAt(sNdx).forAllOccludedActivities( + ActivityRecord::cancelInitializing); } }); } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index bcd71c9ba74e..970520aff81f 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3175,6 +3175,33 @@ class Task extends WindowContainer<WindowContainer> { return false; } + /** Returns the top-most activity that occludes the given one, or {@code null} if none. */ + @Nullable + ActivityRecord getOccludingActivityAbove(ActivityRecord activity) { + final ActivityRecord top = getActivity(ActivityRecord::occludesParent, + true /* traverseTopToBottom */, activity); + return top != activity ? top : null; + } + + /** Iterates through all occluded activities. */ + void forAllOccludedActivities(Consumer<ActivityRecord> handleOccludedActivity) { + if (!shouldBeVisible(null /* starting */)) { + // The stack is invisible so all activities are occluded. + forAllActivities(handleOccludedActivity); + return; + } + final ActivityRecord topOccluding = getOccludingActivityAbove(null); + if (topOccluding == null) { + // No activities are occluded. + return; + } + // Invoke the callback on the activities behind the top occluding activity. + forAllActivities(r -> { + handleOccludedActivity.accept(r); + return false; + }, topOccluding, false /* includeBoundary */, true /* traverseTopToBottom */); + } + @Override public SurfaceControl.Builder makeAnimationLeash() { return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 1b42a0466cf7..373eed921580 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -1331,42 +1331,40 @@ public class ActivityStackTests extends ActivityTestsBase { } @Test - public void testCheckBehindFullscreenActivity() { + public void testIterateOccludedActivity() { final ArrayList<ActivityRecord> occludedActivities = new ArrayList<>(); - final Consumer<ActivityRecord> handleBehindFullscreenActivity = occludedActivities::add; + final Consumer<ActivityRecord> handleOccludedActivity = occludedActivities::add; final ActivityRecord bottomActivity = new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build(); final ActivityRecord topActivity = new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build(); + // Top activity occludes bottom activity. doReturn(true).when(mStack).shouldBeVisible(any()); - assertTrue(mStack.checkBehindFullscreenActivity(bottomActivity, - null /* handleBehindFullscreenActivity */)); - assertFalse(mStack.checkBehindFullscreenActivity(topActivity, - null /* handleBehindFullscreenActivity */)); + assertTrue(topActivity.shouldBeVisible()); + assertFalse(bottomActivity.shouldBeVisible()); - // Top activity occludes bottom activity. - mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity); + mStack.forAllOccludedActivities(handleOccludedActivity); assertThat(occludedActivities).containsExactly(bottomActivity); + // Top activity doesn't occlude parent, so the bottom activity is not occluded. doReturn(false).when(topActivity).occludesParent(); - assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity, - null /* handleBehindFullscreenActivity */)); - assertFalse(mStack.checkBehindFullscreenActivity(topActivity, - null /* handleBehindFullscreenActivity */)); + assertTrue(bottomActivity.shouldBeVisible()); occludedActivities.clear(); - // Top activity doesn't occlude parent, so the bottom activity is not occluded. - mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity); + mStack.forAllOccludedActivities(handleOccludedActivity); assertThat(occludedActivities).isEmpty(); + // A finishing activity should not occlude other activities behind. final ActivityRecord finishingActivity = new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build(); finishingActivity.finishing = true; doCallRealMethod().when(finishingActivity).occludesParent(); - assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity, - null /* handleBehindFullscreenActivity */)); - assertFalse(mStack.checkBehindFullscreenActivity(topActivity, - null /* handleBehindFullscreenActivity */)); + assertTrue(topActivity.shouldBeVisible()); + assertTrue(bottomActivity.shouldBeVisible()); + + occludedActivities.clear(); + mStack.forAllOccludedActivities(handleOccludedActivity); + assertThat(occludedActivities).isEmpty(); } @Test |