From 62bfef80eb597c00398d736bdb42cb6f90afe373 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Thu, 20 Jun 2024 15:53:29 +0800 Subject: Execute transition by starting window of cold launch existed task The check of wasTaskVisible was to make sure the transition ready is only set once for a new launch, because onStartingWindowDrawn may be called multiple times before drawState is commited. But the task-has-been-visible won't be reset even if the process is died because it is about whether the task has been appeared. So when cold launching an existed task which had been visible from background, the wasTaskVisible is true so the transition still waits until the process attaches. The latency is even worse since DEFAULT_ENABLE_WAIT_FOR_FINISH_ATTACH_APPLICATION is enabled, because it defers attachApplication until the app completes bindApplication. Because StartingData will be a new object per starting window, its mIsDisplayed can be used to replace wasTaskVisible without being restricted by the existence of task. This may reduce >100ms cold launch transition latency of existed task. Bug: 347404285 Flag: EXEMPT bugfix Test: atest ActivityRecordTests#testOnStartingWindowDrawn Test: Launch calculator. Return to home. "adb shell kill -9 $pid_of_calculator" Check the end timestamp of SyncGroupReady trace should not be at attachApplication of calculator. Change-Id: I61c62eaa17cc613fcb94e291bc14846efb08e996 --- .../java/com/android/server/wm/ActivityRecord.java | 22 ++++++++------------ .../com/android/server/wm/ActivityRecordTests.java | 24 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9bc4389282fc..326325d7ede5 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -6975,14 +6975,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateReportedVisibilityLocked(); } - /** - * Sets whether something has been visible in the task and returns {@code true} if the state - * is changed from invisible to visible. - */ - private boolean setTaskHasBeenVisible() { + /** Sets whether something has been visible in the task. */ + private void setTaskHasBeenVisible() { final boolean wasTaskVisible = task.getHasBeenVisible(); if (wasTaskVisible) { - return false; + return; } if (inTransition()) { // The deferring will be canceled until transition is ready so it won't dispatch @@ -6990,20 +6987,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A task.setDeferTaskAppear(true); } task.setHasBeenVisible(true); - return true; } void onStartingWindowDrawn() { - boolean wasTaskVisible = false; if (task != null) { mSplashScreenStyleSolidColor = true; - wasTaskVisible = !setTaskHasBeenVisible(); + setTaskHasBeenVisible(); + } + if (mStartingData == null || mStartingData.mIsDisplayed) { + return; } + mStartingData.mIsDisplayed = true; // The transition may not be executed if the starting process hasn't attached. But if the // starting window is drawn, the transition can start earlier. Exclude finishing and bubble // because it may be a trampoline. - if (!wasTaskVisible && mStartingData != null && !finishing && !mLaunchedFromBubble + if (app == null && !finishing && !mLaunchedFromBubble && mVisibleRequested && !mDisplayContent.mAppTransition.isReady() && !mDisplayContent.mAppTransition.isRunning() && mDisplayContent.isNextTransitionForward()) { @@ -7240,9 +7239,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A isInterestingAndDrawn = true; } } - } else if (mStartingData != null && w.isDrawn()) { - // The starting window for this container is drawn. - mStartingData.mIsDisplayed = true; } } 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 d143297d4abf..44cabac586f2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -3097,6 +3097,30 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse("Starting window should not be present", activity.hasStartingWindow()); } + @Test + public void testOnStartingWindowDrawn() { + final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); + // The task-has-been-visible should not affect the decision of making transition ready. + activity.getTask().setHasBeenVisible(true); + activity.detachFromProcess(); + activity.mStartingData = mock(StartingData.class); + registerTestTransitionPlayer(); + final Transition transition = activity.mTransitionController.requestTransitionIfNeeded( + WindowManager.TRANSIT_OPEN, 0 /* flags */, null /* trigger */, mDisplayContent); + activity.onStartingWindowDrawn(); + assertTrue(activity.mStartingData.mIsDisplayed); + // The transition can be ready by the starting window of a visible-requested activity + // without a running process. + assertTrue(transition.allReady()); + + // If other event makes the transition unready, the reentrant of onStartingWindowDrawn + // should not replace the readiness again. + transition.setReady(mDisplayContent, false); + activity.onStartingWindowDrawn(); + assertFalse(transition.allReady()); + } + + @Test public void testCloseToSquareFixedOrientation() { if (Flags.insetsDecoupledConfiguration()) { -- cgit v1.2.3-59-g8ed1b