From d7fb5d979ce2adc7d33be14548224a83d471b0b2 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Thu, 13 Apr 2023 09:58:17 +0000 Subject: [PATCH] Defer remove splash screen window until start transaction apply. In previous CL ag/22494388, there try to defer remove starting window if it is in collect, which miss the case that transition may already playing. So in this CL, by override the waitForSyncTransactionCommit and onSyncTransactionCommitted, there can defer remove starting window until the starting transaction apply, which should ensure the surface of app window is drawn. Bug: 276692049 Test: manual launch app from notification shade several times, verify no blank window occur. Change-Id: I4ad3f4c892939ee70cbb544d63be03123c7425bc --- .../com/android/server/wm/ActivityRecord.java | 40 +++++++++++++------ .../com/android/server/wm/StartingData.java | 20 ++++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 64e1ae5b8c9e5..6273bc3f3a626 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2822,6 +2822,27 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } + @Override + void waitForSyncTransactionCommit(ArraySet wcAwaitingCommit) { + super.waitForSyncTransactionCommit(wcAwaitingCommit); + if (mStartingData != null) { + mStartingData.mWaitForSyncTransactionCommit = true; + } + } + + @Override + void onSyncTransactionCommitted(SurfaceControl.Transaction t) { + super.onSyncTransactionCommitted(t); + if (mStartingData == null) { + return; + } + mStartingData.mWaitForSyncTransactionCommit = false; + if (mStartingData.mRemoveAfterTransaction) { + mStartingData.mRemoveAfterTransaction = false; + removeStartingWindowAnimation(mStartingData.mPrepareRemoveAnimation); + } + } + void removeStartingWindowAnimation(boolean prepareAnimation) { mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_IDLE; if (task != null) { @@ -2844,6 +2865,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final WindowState startingWindow = mStartingWindow; final boolean animate; if (mStartingData != null) { + if (mStartingData.mWaitForSyncTransactionCommit + || mTransitionController.inCollectingTransition(startingWindow)) { + mStartingData.mRemoveAfterTransaction = true; + mStartingData.mPrepareRemoveAnimation = prepareAnimation; + return; + } animate = prepareAnimation && mStartingData.needRevealAnimation() && mStartingWindow.isVisibleByPolicy(); ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s" @@ -2864,18 +2891,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A this); return; } - - if (animate && mTransitionController.inCollectingTransition(startingWindow)) { - // Defer remove starting window after transition start. - // The surface of app window could really show after the transition finish. - startingWindow.mSyncTransaction.addTransactionCommittedListener(Runnable::run, () -> { - synchronized (mAtmService.mGlobalLock) { - surface.remove(true); - } - }); - } else { - surface.remove(animate); - } + surface.remove(animate); } /** diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java index 300a894d15c91..cff86add7efce 100644 --- a/services/core/java/com/android/server/wm/StartingData.java +++ b/services/core/java/com/android/server/wm/StartingData.java @@ -41,6 +41,26 @@ public abstract class StartingData { /** Whether the starting window is drawn. */ boolean mIsDisplayed; + /** + * For Shell transition. + * There will be a transition happen on attached activity, do not remove starting window during + * this period, because the transaction to show app window may not apply before remove starting + * window. + * Note this isn't equal to transition playing, the period should be + * Sync finishNow -> Start transaction apply. + */ + boolean mWaitForSyncTransactionCommit; + + /** + * For Shell transition. + * This starting window should be removed after applying the start transaction of transition, + * which ensures the app window has shown. + */ + boolean mRemoveAfterTransaction; + + /** Whether to prepare the removal animation. */ + boolean mPrepareRemoveAnimation; + protected StartingData(WindowManagerService service, int typeParams) { mService = service; mTypeParams = typeParams;