summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Li <lihongyu@google.com> 2021-09-20 10:13:36 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-09-20 10:13:36 +0000
commitf061f27f16cf194a57f6e98dd347bdac90344077 (patch)
treea381b4897fb26803801aad0f19047e2651e2cf86
parenta8ecb944346561d363cb4e56314c75d76febbd39 (diff)
parent494ce0751d7111e39949685be3e4a518a80ba564 (diff)
Merge "Include activity reparent in transition" into sc-v2-dev
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java19
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java17
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java29
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java32
5 files changed, 100 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 946fa44d1f1c..dfb2f8ff8bc9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1389,6 +1389,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return parent != null ? parent.asTaskFragment() : null;
}
+ /** Whether we should prepare a transition for this {@link ActivityRecord} parent change. */
+ private boolean shouldStartChangeTransition(
+ @Nullable TaskFragment newParent, @Nullable TaskFragment oldParent) {
+ if (mWmService.mDisableTransitionAnimation
+ || mDisplayContent == null || newParent == null || oldParent == null
+ || getSurfaceControl() == null || !isVisible() || !isVisibleRequested()) {
+ return false;
+ }
+
+ // Transition change for the activity moving into a TaskFragment of different bounds.
+ return newParent.isOrganizedTaskFragment()
+ && !newParent.getBounds().equals(oldParent.getBounds());
+ }
+
@Override
void onParentChanged(ConfigurationContainer rawNewParent, ConfigurationContainer rawOldParent) {
final TaskFragment oldParent = (TaskFragment) rawOldParent;
@@ -1397,6 +1411,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final Task newTask = newParent != null ? newParent.getTask() : null;
this.task = newTask;
+ if (shouldStartChangeTransition(newParent, oldParent)) {
+ initializeChangeTransition(getBounds());
+ }
+
super.onParentChanged(newParent, oldParent);
if (isPersistable()) {
@@ -2607,6 +2625,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return parent != null ? parent.getOrganizedTaskFragment() : null;
}
+ @Override
boolean isEmbedded() {
final TaskFragment parent = getTaskFragment();
return parent != null && parent.isEmbedded();
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 7a42351c33c1..c0b69794966b 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -237,6 +237,8 @@ public class AppTransitionController {
// Check if there is any override
if (!overrideWithTaskFragmentRemoteAnimation(transit, activityTypes)) {
+ // Unfreeze the windows that were previously frozen for TaskFragment animation.
+ unfreezeEmbeddedChangingWindows();
overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
}
@@ -341,6 +343,9 @@ public class AppTransitionController {
switch (changingType) {
case TYPE_TASK:
return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
+ case TYPE_ACTIVITY:
+ // ActivityRecord is put in a change transition only when it is reparented
+ // to an organized TaskFragment. See ActivityRecord#shouldStartChangeTransition.
case TYPE_TASK_FRAGMENT:
return TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
default:
@@ -511,6 +516,16 @@ public class AppTransitionController {
: null;
}
+ private void unfreezeEmbeddedChangingWindows() {
+ final ArraySet<WindowContainer> changingContainers = mDisplayContent.mChangingContainers;
+ for (int i = changingContainers.size() - 1; i >= 0; i--) {
+ final WindowContainer wc = changingContainers.valueAt(i);
+ if (wc.isEmbedded()) {
+ wc.mSurfaceFreezer.unfreeze(wc.getSyncTransaction());
+ }
+ }
+ }
+
/**
* Overrides the pending transition with the remote animation defined by the
* {@link ITaskFragmentOrganizer} if all windows in the transition are children of
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index c8b8b0dd5a1d..584f7bf5e5b1 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -33,7 +33,6 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -465,7 +464,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return this;
}
- /** Returns {@code true} if this is a container for embedded activities or tasks. */
+ @Override
boolean isEmbedded() {
if (mIsEmbedded) {
return true;
@@ -2073,15 +2072,6 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return !startBounds.equals(getBounds());
}
- /**
- * Initializes a change transition. See {@link SurfaceFreezer} for more information.
- */
- void initializeChangeTransition(Rect startBounds) {
- mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
- mDisplayContent.mChangingContainers.add(this);
- mSurfaceFreezer.freeze(getSyncTransaction(), startBounds);
- }
-
@Override
void setSurfaceControl(SurfaceControl sc) {
super.setSurfaceControl(sc);
@@ -2163,6 +2153,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return mTaskFragmentOrganizer != null;
}
+ /** Whether this is an organized {@link TaskFragment} and not a {@link Task}. */
+ final boolean isOrganizedTaskFragment() {
+ return mTaskFragmentOrganizer != null;
+ }
+
/** Clear {@link #mLastPausedActivity} for all {@link TaskFragment} children */
void clearLastPausedActivity() {
forAllTaskFragments(taskFragment -> taskFragment.mLastPausedActivity = null);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index cdfa5aa84a95..0862d9bedde0 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -30,6 +30,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
import static android.view.SurfaceControl.Transaction;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.TRANSIT_CHANGE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -2578,13 +2579,34 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
mSurfaceFreezer.unfreeze(getPendingTransaction());
}
+ /**
+ * Initializes a change transition. See {@link SurfaceFreezer} for more information.
+ *
+ * For now, this will only be called for the following cases:
+ * 1. {@link Task} is changing windowing mode between fullscreen and freeform.
+ * 2. {@link TaskFragment} is organized and is changing window bounds.
+ * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}.
+ *
+ * This shouldn't be called on other {@link WindowContainer} unless there is a valid use case.
+ */
+ void initializeChangeTransition(Rect startBounds) {
+ mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
+ mDisplayContent.mChangingContainers.add(this);
+ mSurfaceFreezer.freeze(getSyncTransaction(), startBounds);
+ }
+
ArraySet<WindowContainer> getAnimationSources() {
return mSurfaceAnimationSources;
}
@Override
public SurfaceControl getFreezeSnapshotTarget() {
- return null;
+ // Only allow freezing if this window is in a TRANSIT_CHANGE
+ if (!mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)
+ || !mDisplayContent.mChangingContainers.contains(this)) {
+ return null;
+ }
+ return getSurfaceControl();
}
@Override
@@ -3189,6 +3211,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return false;
}
+ /** @return {@code true} if this is a container for embedded activities or tasks. */
+ boolean isEmbedded() {
+ return false;
+ }
+
/**
* @return {@code true} if this container's surface should be shown when it is created.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index a0a3ce73265c..405d714256ab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -43,6 +43,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -54,6 +55,8 @@ import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.WindowManager;
+import android.window.ITaskFragmentOrganizer;
+import android.window.TaskFragmentOrganizer;
import androidx.test.filters.SmallTest;
@@ -391,6 +394,35 @@ public class AppTransitionTests extends WindowTestsBase {
mDc.mAppTransition.getAnimationStyleResId(attrs));
}
+ @Test
+ public void testActivityRecordReparentToTaskFragment() {
+ final ActivityRecord activity = createActivityRecord(mDc);
+ activity.setVisibility(true);
+ final Task task = activity.getTask();
+
+ // Add a TaskFragment of half of the Task size.
+ final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
+ final ITaskFragmentOrganizer iOrganizer =
+ ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder());
+ mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer);
+ final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .setOrganizer(organizer)
+ .build();
+ final Rect taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ taskFragment.setBounds(0, 0, taskBounds.right / 2, taskBounds.bottom);
+
+ assertTrue(mDc.mChangingContainers.isEmpty());
+ assertFalse(mDc.mAppTransition.isTransitionSet());
+
+ // Schedule app transition when reparent activity to a TaskFragment of different size.
+ activity.reparent(taskFragment, POSITION_TOP);
+
+ assertTrue(mDc.mChangingContainers.contains(activity));
+ assertTrue(mDc.mAppTransition.containsTransitRequest(TRANSIT_CHANGE));
+ }
+
private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
boolean mCancelled = false;
@Override