summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Evan Rosky <erosky@google.com> 2021-10-08 18:37:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-10-08 18:37:53 +0000
commit4097e44f2a4ca1611b600bd7d8c21c723784c8d7 (patch)
tree4b8468818635ee56ff89d810adb38d3aefe079b4
parent7a8f7189e25049d20f9211d2c8341c869219e7c2 (diff)
parent9a5b9ad6f446b2902284c7cbcb21a6b1bf68f535 (diff)
Merge "Port IME tasksnapshot over to shell transitions" into sc-v2-dev
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java17
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java1
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java71
-rw-r--r--services/core/java/com/android/server/wm/Transition.java24
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java71
7 files changed, 153 insertions, 43 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 68bc925c1a67..394ff755d252 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4890,8 +4890,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise
* this should become invisible.
* @param performLayout if {@code true}, perform surface placement after committing visibility.
+ * @param fromTransition {@code true} if this is part of finishing a transition.
*/
- void commitVisibility(boolean visible, boolean performLayout) {
+ void commitVisibility(boolean visible, boolean performLayout, boolean fromTransition) {
// Reset the state of mVisibleSetFromTransferredStartingWindow since visibility is actually
// been set by the app now.
mVisibleSetFromTransferredStartingWindow = false;
@@ -4941,7 +4942,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
mUseTransferredAnimation = false;
- postApplyAnimation(visible);
+ postApplyAnimation(visible, fromTransition);
+ }
+
+ void commitVisibility(boolean visible, boolean performLayout) {
+ commitVisibility(visible, performLayout, false /* fromTransition */);
}
/**
@@ -4952,8 +4957,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
*
* @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise
* this has become invisible.
+ * @param fromTransition {@code true} if this call is part of finishing a transition. This is
+ * needed because the shell transition is no-longer active by the time
+ * commitVisibility is called.
*/
- private void postApplyAnimation(boolean visible) {
+ private void postApplyAnimation(boolean visible, boolean fromTransition) {
final boolean usingShellTransitions = mTransitionController.isShellTransitionsEnabled();
final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION
@@ -4994,7 +5002,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final DisplayContent displayContent = getDisplayContent();
if (!displayContent.mClosingApps.contains(this)
- && !displayContent.mOpeningApps.contains(this)) {
+ && !displayContent.mOpeningApps.contains(this)
+ && !fromTransition) {
// Take the screenshot before possibly hiding the WSA, otherwise the screenshot
// will not be taken.
mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a4f188c7ad74..60a514e4d612 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -991,6 +991,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
mWindowManager = wm;
mRootWindowContainer = wm.mRoot;
+ mWindowOrganizerController.setWindowManager(wm);
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 5ce9938ff71d..ce93f2495c22 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -178,46 +178,49 @@ class TaskSnapshotController {
snapshotTasks(tasks, false /* allowSnapshotHome */);
}
- private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
- for (int i = tasks.size() - 1; i >= 0; i--) {
- final Task task = tasks.valueAt(i);
- final TaskSnapshot snapshot;
- final boolean snapshotHome = allowSnapshotHome && task.isActivityTypeHome();
- if (snapshotHome) {
- snapshot = snapshotTask(task);
- } else {
- switch (getSnapshotMode(task)) {
- case SNAPSHOT_MODE_NONE:
- continue;
- case SNAPSHOT_MODE_APP_THEME:
- snapshot = drawAppThemeSnapshot(task);
- break;
- case SNAPSHOT_MODE_REAL:
- snapshot = snapshotTask(task);
- break;
- default:
- snapshot = null;
- break;
- }
+ void recordTaskSnapshot(Task task, boolean allowSnapshotHome) {
+ final TaskSnapshot snapshot;
+ final boolean snapshotHome = allowSnapshotHome && task.isActivityTypeHome();
+ if (snapshotHome) {
+ snapshot = snapshotTask(task);
+ } else {
+ switch (getSnapshotMode(task)) {
+ case SNAPSHOT_MODE_NONE:
+ return;
+ case SNAPSHOT_MODE_APP_THEME:
+ snapshot = drawAppThemeSnapshot(task);
+ break;
+ case SNAPSHOT_MODE_REAL:
+ snapshot = snapshotTask(task);
+ break;
+ default:
+ snapshot = null;
+ break;
}
- if (snapshot != null) {
- final HardwareBuffer buffer = snapshot.getHardwareBuffer();
- if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
- buffer.close();
- Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
- + buffer.getHeight());
- } else {
- mCache.putSnapshot(task, snapshot);
- // Don't persist or notify the change for the temporal snapshot.
- if (!snapshotHome) {
- mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
- task.onSnapshotChanged(snapshot);
- }
+ }
+ if (snapshot != null) {
+ final HardwareBuffer buffer = snapshot.getHardwareBuffer();
+ if (buffer.getWidth() == 0 || buffer.getHeight() == 0) {
+ buffer.close();
+ Slog.e(TAG, "Invalid task snapshot dimensions " + buffer.getWidth() + "x"
+ + buffer.getHeight());
+ } else {
+ mCache.putSnapshot(task, snapshot);
+ // Don't persist or notify the change for the temporal snapshot.
+ if (!snapshotHome) {
+ mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
+ task.onSnapshotChanged(snapshot);
}
}
}
}
+ private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
+ for (int i = tasks.size() - 1; i >= 0; i--) {
+ recordTaskSnapshot(tasks.valueAt(i), allowSnapshotHome);
+ }
+ }
+
/**
* Retrieves a snapshot. If {@param restoreFromDisk} equals {@code true}, DO NOT HOLD THE WINDOW
* MANAGER LOCK WHEN CALLING THIS METHOD!
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index e50e8ef56778..e537c0afc147 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -415,7 +415,16 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
if (commitVisibility) {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
" Commit activity becoming invisible: %s", ar);
- ar.commitVisibility(false /* visible */, false /* performLayout */);
+ final Task task = ar.getTask();
+ if (task != null && !task.isVisibleRequested()
+ && mTransientLaunches != null) {
+ // If transition is transient, then snapshots are taken at end of
+ // transition.
+ mController.mTaskSnapshotController.recordTaskSnapshot(
+ task, false /* allowSnapshotHome */);
+ }
+ ar.commitVisibility(false /* visible */, false /* performLayout */,
+ true /* fromTransition */);
activitiesWentInvisible = true;
}
}
@@ -558,6 +567,19 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
mVisibleAtTransitionEndTokens.add(wc.asWindowToken());
}
+ // Take task snapshots before the animation so that we can capture IME before it gets
+ // transferred. If transition is transient, IME won't be moved during the transition and
+ // the tasks are still live, so we take the snapshot at the end of the transition instead.
+ if (mTransientLaunches == null) {
+ for (int i = mParticipants.size() - 1; i >= 0; --i) {
+ final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
+ if (ar == null || ar.isVisibleRequested() || ar.getTask() == null
+ || ar.getTask().isVisibleRequested()) continue;
+ mController.mTaskSnapshotController.recordTaskSnapshot(
+ ar.getTask(), false /* allowSnapshotHome */);
+ }
+ }
+
mStartTransaction = transaction;
mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
buildFinishTransaction(mFinishTransaction, info.getRootLeash());
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index fc5423942dc3..ff4cc3d1b784 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -59,6 +59,7 @@ class TransitionController {
private ITransitionPlayer mTransitionPlayer;
final ActivityTaskManagerService mAtm;
+ final TaskSnapshotController mTaskSnapshotController;
private final ArrayList<WindowManagerInternal.AppTransitionListener> mLegacyListeners =
new ArrayList<>();
@@ -79,9 +80,11 @@ class TransitionController {
// TODO(b/188595497): remove when not needed.
final StatusBarManagerInternal mStatusBar;
- TransitionController(ActivityTaskManagerService atm) {
+ TransitionController(ActivityTaskManagerService atm,
+ TaskSnapshotController taskSnapshotController) {
mAtm = atm;
mStatusBar = LocalServices.getService(StatusBarManagerInternal.class);
+ mTaskSnapshotController = taskSnapshotController;
mTransitionPlayerDeath = () -> {
synchronized (mAtm.mGlobalLock) {
// Clean-up/finish any playing transitions.
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 781b53df998e..54ce5fc6bbec 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -117,7 +117,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
final DisplayAreaOrganizerController mDisplayAreaOrganizerController;
final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
- final TransitionController mTransitionController;
+ TransitionController mTransitionController;
/**
* A Map which manages the relationship between
* {@link TaskFragmentCreationParams#getFragmentToken()} and {@link TaskFragment}
@@ -131,7 +131,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mTaskOrganizerController = new TaskOrganizerController(mService);
mDisplayAreaOrganizerController = new DisplayAreaOrganizerController(mService);
mTaskFragmentOrganizerController = new TaskFragmentOrganizerController(atm);
- mTransitionController = new TransitionController(atm);
+ }
+
+ void setWindowManager(WindowManagerService wms) {
+ mTransitionController = new TransitionController(mService, wms.mTaskSnapshotController);
}
TransitionController getTransitionController() {
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 6d60bcf1fce6..a1c24c26af35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -34,8 +34,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
@@ -448,7 +451,8 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testIntermediateVisibility() {
- final TransitionController controller = new TransitionController(mAtm);
+ final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
+ final TransitionController controller = new TransitionController(mAtm, snapshotController);
final ITransitionPlayer player = new ITransitionPlayer.Default();
controller.registerTransitionPlayer(player);
ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
@@ -511,6 +515,71 @@ public class TransitionTests extends WindowTestsBase {
assertTrue(activity2.isVisible());
}
+ @Test
+ public void testTransientLaunch() {
+ final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
+ final TransitionController controller = new TransitionController(mAtm, snapshotController);
+ final ITransitionPlayer player = new ITransitionPlayer.Default();
+ controller.registerTransitionPlayer(player);
+ ITaskOrganizer mockOrg = mock(ITaskOrganizer.class);
+ final Transition openTransition = controller.createTransition(TRANSIT_OPEN);
+
+ // Start out with task2 visible and set up a transition that closes task2 and opens task1
+ final Task task1 = createTask(mDisplayContent);
+ task1.mTaskOrganizer = mockOrg;
+ final ActivityRecord activity1 = createActivityRecord(task1);
+ activity1.mVisibleRequested = false;
+ activity1.setVisible(false);
+ final Task task2 = createTask(mDisplayContent);
+ task2.mTaskOrganizer = mockOrg;
+ final ActivityRecord activity2 = createActivityRecord(task2);
+ activity2.mVisibleRequested = true;
+ activity2.setVisible(true);
+
+ openTransition.collectExistenceChange(task1);
+ openTransition.collectExistenceChange(activity1);
+ openTransition.collectExistenceChange(task2);
+ openTransition.collectExistenceChange(activity2);
+
+ activity1.mVisibleRequested = true;
+ activity1.setVisible(true);
+ activity2.mVisibleRequested = false;
+
+ // Using abort to force-finish the sync (since we can't wait for drawing in unit test).
+ // We didn't call abort on the transition itself, so it will still run onTransactionReady
+ // normally.
+ mWm.mSyncEngine.abort(openTransition.getSyncId());
+
+ verify(snapshotController, times(1)).recordTaskSnapshot(eq(task2), eq(false));
+
+ openTransition.finishTransition();
+
+ // We are now going to simulate closing task1 to return back to (open) task2.
+ final Transition closeTransition = controller.createTransition(TRANSIT_CLOSE);
+
+ closeTransition.collectExistenceChange(task1);
+ closeTransition.collectExistenceChange(activity1);
+ closeTransition.collectExistenceChange(task2);
+ closeTransition.collectExistenceChange(activity2);
+ closeTransition.setTransientLaunch(activity2);
+
+ activity1.mVisibleRequested = false;
+ activity2.mVisibleRequested = true;
+
+ // Using abort to force-finish the sync (since we obviously can't wait for drawing).
+ // We didn't call abort on the actual transition, so it will still run onTransactionReady
+ // normally.
+ mWm.mSyncEngine.abort(closeTransition.getSyncId());
+
+ // Make sure we haven't called recordSnapshot (since we are transient, it shouldn't be
+ // called until finish).
+ verify(snapshotController, times(0)).recordTaskSnapshot(eq(task1), eq(false));
+
+ closeTransition.finishTransition();
+
+ verify(snapshotController, times(1)).recordTaskSnapshot(eq(task1), eq(false));
+ }
+
/** Fill the change map with all the parents of top. Change maps are usually fully populated */
private static void fillChangeMap(ArrayMap<WindowContainer, Transition.ChangeInfo> changes,
WindowContainer top) {