Merge "Reland "Finish sync for activities under a drawn shared starting window"" into main
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5fa2610..3a792d0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2495,7 +2495,14 @@
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
mStartingData = new SnapshotStartingData(mWmService, snapshot, typeParams);
- if (task.forAllLeafTaskFragments(TaskFragment::isEmbedded)) {
+ if ((!mStyleFillsParent && task.getChildCount() > 1)
+ || task.forAllLeafTaskFragments(TaskFragment::isEmbedded)) {
+ // Case 1:
+ // If it is moving a Task{[0]=main activity, [1]=translucent activity} to front, use
+ // shared starting window so that the transition doesn't need to wait for the activity
+ // behind the translucent activity. Also, onFirstWindowDrawn will check all visible
+ // activities are drawn in the task to remove the snapshot starting window.
+ // Case 2:
// Associate with the task so if this activity is resized by task fragment later, the
// starting window can keep the same bounds as the task.
associateStartingDataWithTask();
@@ -10616,6 +10623,14 @@
@Override
boolean isSyncFinished(BLASTSyncEngine.SyncGroup group) {
+ if (task != null && task.mSharedStartingData != null) {
+ final WindowState startingWin = task.topStartingWindow();
+ if (startingWin != null && startingWin.mSyncState == SYNC_STATE_READY
+ && mDisplayContent.mUnknownAppVisibilityController.allResolved()) {
+ // The sync is ready if a drawn starting window covered the task.
+ return true;
+ }
+ }
if (!super.isSyncFinished(group)) return false;
if (mDisplayContent != null && mDisplayContent.mUnknownAppVisibilityController
.isVisibilityUnknown(this)) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 27fe49b..a7a6bf2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1411,12 +1411,13 @@
return isUidPresent;
}
+ WindowState topStartingWindow() {
+ return getWindow(w -> w.mAttrs.type == TYPE_APPLICATION_STARTING);
+ }
+
ActivityRecord topActivityContainsStartingWindow() {
- if (getParent() == null) {
- return null;
- }
- return getActivity((r) -> r.getWindow(window ->
- window.getBaseType() == TYPE_APPLICATION_STARTING) != null);
+ final WindowState startingWindow = topStartingWindow();
+ return startingWindow != null ? startingWindow.mActivityRecord : null;
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index be30593..6c5f975 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -145,6 +146,25 @@
}
@Test
+ public void testFinishSyncByStartingWindow() {
+ final ActivityRecord taskRoot = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = taskRoot.getTask();
+ final ActivityRecord translucentTop = new ActivityBuilder(mAtm).setTask(task)
+ .setActivityTheme(android.R.style.Theme_Translucent).build();
+ createWindow(null, TYPE_BASE_APPLICATION, taskRoot, "win");
+ final WindowState startingWindow = createWindow(null, TYPE_APPLICATION_STARTING,
+ translucentTop, "starting");
+ startingWindow.mStartingData = new SnapshotStartingData(mWm, null, 0);
+ task.mSharedStartingData = startingWindow.mStartingData;
+ task.prepareSync();
+
+ final BLASTSyncEngine.SyncGroup group = mock(BLASTSyncEngine.SyncGroup.class);
+ assertFalse(task.isSyncFinished(group));
+ startingWindow.onSyncFinishedDrawing();
+ assertTrue(task.isSyncFinished(group));
+ }
+
+ @Test
public void testInvisibleSyncCallback() {
TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);