diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index a01113b26a1e019aecbc86194c88edfa8963fc49..9fa5ed2cfde97a45bc2716c810739b94d03df752 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4030,6 +4030,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mAppStopped) { abortAndClearOptionsAnimation(); } + if (mDisplayContent != null) { + mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this); + } } boolean isFinishing() { @@ -5388,12 +5391,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLastDeferHidingClient = deferHidingClient; if (!visible) { - // If this activity is about to finish/stopped and now becomes invisible, remove it - // from the unknownApp list in case the activity does not want to draw anything, which - // keep the user waiting for the next transition to start. - if (finishing || isState(STOPPED)) { - displayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this); - } // Because starting window was transferred, this activity may be a trampoline which has // been occluded by next activity. If it has added windows, set client visibility // immediately to avoid the client getting RELAYOUT_RES_FIRST_TIME from relayout and @@ -5837,6 +5834,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A break; case STOPPED: mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED); + if (mDisplayContent != null) { + mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this); + } break; case DESTROYED: if (app != null && (mVisible || mVisibleRequested)) { @@ -6517,7 +6517,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Reset the last saved PiP snap fraction on app stop. mDisplayContent.mPinnedTaskController.onActivityHidden(mActivityComponent); - mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this); if (isClientVisible()) { // Though this is usually unlikely to happen, still make sure the client is invisible. setClientVisible(false); diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java index 444470952c5dcbdf7ab98fe6db3fba7aa16b8820..c79a8b6b13a167bad426e6aa88399acd5359cda3 100644 --- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java +++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java @@ -378,8 +378,23 @@ class BLASTSyncEngine { if (!wc.isSyncFinished(this)) { allFinished = false; Slog.i(TAG, "Unfinished container: " + wc); + wc.forAllActivities(a -> { + if (a.isVisibleRequested()) { + if (a.isRelaunching()) { + Slog.i(TAG, " " + a + " is relaunching"); + } + a.forAllWindows(w -> { + Slog.i(TAG, " " + w + " " + w.mWinAnimator.drawStateToString()); + }, true /* traverseTopToBottom */); + } else if (a.mDisplayContent != null && !a.mDisplayContent + .mUnknownAppVisibilityController.allResolved()) { + Slog.i(TAG, " UnknownAppVisibility: " + a.mDisplayContent + .mUnknownAppVisibilityController.getDebugMessage()); + } + }); } } + for (int i = mDependencies.size() - 1; i >= 0; --i) { allFinished = false; Slog.i(TAG, "Unfinished dependency: " + mDependencies.get(i).mSyncId); diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java index 41c1e793dd90181b494690d4fca86ba1d9e4200d..c0713966d8de80d6d9b2a369e8cc7cc216a576a8 100644 --- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java +++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java @@ -70,6 +70,9 @@ class UnknownAppVisibilityController { } boolean isVisibilityUnknown(ActivityRecord r) { + if (mUnknownApps.isEmpty()) { + return false; + } return mUnknownApps.containsKey(r); } @@ -90,6 +93,9 @@ class UnknownAppVisibilityController { } void appRemovedOrHidden(@NonNull ActivityRecord activity) { + if (mUnknownApps.isEmpty()) { + return; + } if (DEBUG_UNKNOWN_APP_VISIBILITY) { Slog.d(TAG, "App removed or hidden activity=" + activity); } @@ -117,8 +123,11 @@ class UnknownAppVisibilityController { * Notifies that {@param activity} has finished resuming. */ void notifyAppResumedFinished(@NonNull ActivityRecord activity) { - if (mUnknownApps.containsKey(activity) - && mUnknownApps.get(activity) == UNKNOWN_STATE_WAITING_RESUME) { + if (mUnknownApps.isEmpty()) { + return; + } + final Integer state = mUnknownApps.get(activity); + if (state != null && state == UNKNOWN_STATE_WAITING_RESUME) { if (DEBUG_UNKNOWN_APP_VISIBILITY) { Slog.d(TAG, "App resume finished activity=" + activity); } @@ -130,13 +139,16 @@ class UnknownAppVisibilityController { * Notifies that {@param activity} has relaid out. */ void notifyRelayouted(@NonNull ActivityRecord activity) { - if (!mUnknownApps.containsKey(activity)) { + if (mUnknownApps.isEmpty()) { + return; + } + final Integer state = mUnknownApps.get(activity); + if (state == null) { return; } if (DEBUG_UNKNOWN_APP_VISIBILITY) { Slog.d(TAG, "App relayouted appWindow=" + activity); } - int state = mUnknownApps.get(activity); if (state == UNKNOWN_STATE_WAITING_RELAYOUT || activity.mStartingWindow != null) { mUnknownApps.put(activity, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE); mDisplayContent.notifyKeyguardFlagsChanged(); diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java index 75a8dd822914b6c3266ce713f8ae4bbca3e55fb1..085eddd2e73d808459a108441919d98fe7e8ef8d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.platform.test.annotations.Presubmit; @@ -94,10 +95,14 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase { public void testRemoveFinishingInvisibleActivityFromUnknown() { final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity); - activity.finishing = true; - activity.setVisibleRequested(true); - activity.setVisibility(false); + assertFalse(mDisplayContent.mUnknownAppVisibilityController.allResolved()); + activity.makeFinishingLocked(); assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved()); + + mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity); + assertTrue(mDisplayContent.mUnknownAppVisibilityController.isVisibilityUnknown(activity)); + activity.setState(ActivityRecord.State.STOPPED, "test"); + assertFalse(mDisplayContent.mUnknownAppVisibilityController.isVisibilityUnknown(activity)); } @Test