From de2c5f135841e8f09e2a1056090801e10a58827d Mon Sep 17 00:00:00 2001 From: Jeff Chang Date: Fri, 10 Apr 2020 17:23:43 +0800 Subject: [PATCH] Compute visibilities when finishing activity with a translucent resume activity When there is a translucent activity in foreground and finishing a next intermediate activity. Since the visibility of next below activity was not updated. The black background shown below the translucent resume activity. The CL update the visibilities with above condition and add test case to verify. Bug: 153927250 Test: atest WmTests:ActivityRecordTests Change-Id: Ie5fc13872becb48b8bdcd572d710111534424a72 --- .../com/android/server/wm/ActivityRecord.java | 33 ++++++++++----- .../server/wm/ActivityRecordTests.java | 40 +++++++++++++++++++ 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 130da2dfe9c52..dcdbfdedb0c86 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2669,15 +2669,28 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return this; } - // Ensure activity visibilities and update lockscreen occluded/dismiss state when - // finishing the top activity that occluded keyguard. So that, the - // ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below won't - // be resumed. - if (isState(PAUSED) - && mStackSupervisor.getKeyguardController().isKeyguardLocked() - && getStack().topActivityOccludesKeyguard()) { - getDisplay().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, - false /* preserveWindows */, false /* notifyClients */); + final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED); + if (isCurrentVisible) { + final ActivityStack stack = getStack(); + final ActivityRecord activity = stack.mResumedActivity; + boolean ensureVisibility = false; + if (activity != null && !activity.occludesParent()) { + // If the resume activity is not opaque, we need to make sure the visibilities of + // activities be updated, they may be seen by users. + ensureVisibility = true; + } else if (mStackSupervisor.getKeyguardController().isKeyguardLocked() + && stack.topActivityOccludesKeyguard()) { + // Ensure activity visibilities and update lockscreen occluded/dismiss state when + // finishing the top activity that occluded keyguard. So that, the + // ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below + // won't be resumed. + ensureVisibility = true; + } + + if (ensureVisibility) { + getDisplay().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + false /* preserveWindows */, true /* notifyClients */); + } } boolean activityRemoved = false; @@ -2698,7 +2711,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // than destroy immediately. final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.mVisibleRequested); - if ((mVisibleRequested || isState(PAUSED)) && isNextNotYetVisible) { + if (isCurrentVisible && isNextNotYetVisible) { // Add this activity to the list of stopping activities. It will be processed and // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 6a28918eab005..364845c0ff4ae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1082,6 +1082,46 @@ public class ActivityRecordTests extends ActivityTestsBase { assertFalse(mStack.topActivityOccludesKeyguard()); } + /** + * Verify that complete finish request for an activity which the resume activity is translucent + * must ensure the visibilities of activities being updated. + */ + @Test + public void testCompleteFinishing_ensureActivitiesVisible() { + final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build(); + firstActivity.mVisibleRequested = false; + firstActivity.nowVisible = false; + firstActivity.setState(STOPPED, "true"); + + final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build(); + secondActivity.mVisibleRequested = true; + secondActivity.nowVisible = true; + secondActivity.setState(PAUSED, "true"); + + final ActivityRecord translucentActivity = + new ActivityBuilder(mService).setTask(mTask).build(); + translucentActivity.mVisibleRequested = true; + translucentActivity.nowVisible = true; + translucentActivity.setState(RESUMED, "true"); + + doReturn(false).when(translucentActivity).occludesParent(); + + // Finish the second activity + secondActivity.finishing = true; + secondActivity.completeFinishing("test"); + verify(secondActivity.getDisplay()).ensureActivitiesVisible(null /* starting */, + 0 /* configChanges */ , false /* preserveWindows */, + true /* notifyClients */); + + // Finish the first activity + firstActivity.finishing = true; + firstActivity.mVisibleRequested = true; + firstActivity.completeFinishing("test"); + verify(firstActivity.getDisplay(), times(2)).ensureActivitiesVisible(null /* starting */, + 0 /* configChanges */ , false /* preserveWindows */, + true /* notifyClients */); + } + /** * Verify destroy activity request completes successfully. */