diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 4f87b1a22f029..90ac1aad6dcdd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -6578,12 +6578,29 @@ 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() { + final boolean wasTaskVisible = task.getHasBeenVisible(); + if (wasTaskVisible) { + return false; + } + if (inTransition()) { + // The deferring will be canceled until transition is ready so it won't dispatch + // intermediate states to organizer. + task.setDeferTaskAppear(true); + } + task.setHasBeenVisible(true); + return true; + } + void onStartingWindowDrawn() { boolean wasTaskVisible = false; if (task != null) { mSplashScreenStyleSolidColor = true; - wasTaskVisible = task.getHasBeenVisible(); - task.setHasBeenVisible(true); + wasTaskVisible = !setTaskHasBeenVisible(); } // The transition may not be executed if the starting process hasn't attached. But if the @@ -6621,7 +6638,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } finishLaunchTickingLocked(); if (task != null) { - task.setHasBeenVisible(true); + setTaskHasBeenVisible(); } // Clear indicated launch root task because there's no trampoline activity to expect after // the windows are drawn. diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index b7021c8671ca0..a76d8362eaab2 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4148,21 +4148,28 @@ class Task extends TaskFragment { void setHasBeenVisible(boolean hasBeenVisible) { mHasBeenVisible = hasBeenVisible; - if (hasBeenVisible) { - if (!mDeferTaskAppear) sendTaskAppeared(); - if (!isRootTask()) { - getRootTask().setHasBeenVisible(true); + if (!hasBeenVisible || mDeferTaskAppear) { + return; + } + sendTaskAppeared(); + for (WindowContainer parent = getParent(); parent != null; parent = parent.getParent()) { + final Task parentTask = parent.asTask(); + if (parentTask == null) { + break; } + parentTask.setHasBeenVisible(true); } } + boolean getHasBeenVisible() { return mHasBeenVisible; } void setDeferTaskAppear(boolean deferTaskAppear) { + final boolean wasDeferred = mDeferTaskAppear; mDeferTaskAppear = deferTaskAppear; - if (!mDeferTaskAppear) { + if (wasDeferred && !deferTaskAppear) { sendTaskAppeared(); } } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 8b1fb51cb6b76..7d3367fe8bf7a 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1156,12 +1156,15 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { private void commitVisibleActivities(SurfaceControl.Transaction transaction) { for (int i = mParticipants.size() - 1; i >= 0; --i) { final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); - if (ar == null || !ar.isVisibleRequested()) { + if (ar == null || ar.getTask() == null) { continue; } - ar.commitVisibility(true /* visible */, false /* performLayout */, - true /* fromTransition */); - ar.commitFinishDrawing(transaction); + if (ar.isVisibleRequested()) { + ar.commitVisibility(true /* visible */, false /* performLayout */, + true /* fromTransition */); + ar.commitFinishDrawing(transaction); + } + ar.getTask().setDeferTaskAppear(false); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 21135e0a80cc6..90181389c772f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -566,6 +566,8 @@ public class TransitionTests extends WindowTestsBase { doReturn(mock(IBinder.class)).when(delegateProc.getThread()).asBinder(); final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true) .setVisible(false).build(); + final Task task = app.getTask(); + task.setTaskOrganizer(mock(ITaskOrganizer.class), true /* skipTaskAppeared */); app.setVisibleRequested(true); final TransitionController controller = app.mTransitionController; final Transition transition = controller.createTransition(TRANSIT_OPEN); @@ -576,7 +578,11 @@ public class TransitionTests extends WindowTestsBase { controller.requestStartTransition(transition, null /* startTask */, remoteTransition, null /* displayChange */); testPlayer.startTransition(); + app.onStartingWindowDrawn(); + // The task appeared event should be deferred until transition ready. + assertFalse(task.taskAppearedReady()); testPlayer.onTransactionReady(app.getSyncTransaction()); + assertTrue(task.taskAppearedReady()); assertTrue(playerProc.isRunningRemoteTransition()); assertTrue(delegateProc.isRunningRemoteTransition()); assertTrue(controller.mRemotePlayer.reportRunning(delegateProc.getThread()));