summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/ITaskFragmentOrganizerController.aidl13
-rw-r--r--core/java/android/window/TaskFragmentOrganizer.java29
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java23
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java1
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java5
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java224
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java79
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java309
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java267
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java20
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java88
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java69
-rw-r--r--services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java73
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java371
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java14
15 files changed, 5 insertions, 1580 deletions
diff --git a/core/java/android/window/ITaskFragmentOrganizerController.aidl b/core/java/android/window/ITaskFragmentOrganizerController.aidl
index 4706dfd1a76c..2c64b8ed456d 100644
--- a/core/java/android/window/ITaskFragmentOrganizerController.aidl
+++ b/core/java/android/window/ITaskFragmentOrganizerController.aidl
@@ -39,19 +39,6 @@ interface ITaskFragmentOrganizerController {
void unregisterOrganizer(in ITaskFragmentOrganizer organizer);
/**
- * Registers remote animations per transition type for the organizer. It will override the
- * animations if the transition only contains windows that belong to the organized
- * TaskFragments in the given Task.
- */
- void registerRemoteAnimations(in ITaskFragmentOrganizer organizer,
- in RemoteAnimationDefinition definition);
-
- /**
- * Unregisters remote animations per transition type for the organizer.
- */
- void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer);
-
- /**
* Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and
* only occupies a portion of Task bounds.
*/
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 461eab61e393..d4c3fbee0f79 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -32,7 +32,6 @@ import android.annotation.TestApi;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
import com.android.window.flags.Flags;
@@ -205,34 +204,6 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
}
/**
- * Registers remote animations per transition type for the organizer. It will override the
- * animations if the transition only contains windows that belong to the organized
- * TaskFragments, and at least one of the transition window is embedded (not filling the Task).
- * @hide
- */
- @CallSuper
- public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) {
- try {
- getController().registerRemoteAnimations(mInterface, definition);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Unregisters remote animations per transition type for the organizer.
- * @hide
- */
- @CallSuper
- public void unregisterRemoteAnimations() {
- try {
- getController().unregisterRemoteAnimations(mInterface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Notifies the server that the organizer has finished handling the given transaction. The
* server should apply the given {@link WindowContainerTransaction} for the necessary changes.
*
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 9ea2943bc6da..1eb95c1efb08 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -70,10 +70,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
@NonNull
private final TaskFragmentCallback mCallback;
- @VisibleForTesting
- @Nullable
- TaskFragmentAnimationController mAnimationController;
-
/**
* Callback that notifies the controller about changes to task fragments.
*/
@@ -91,25 +87,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
mCallback = callback;
}
- @Override
- public void unregisterOrganizer() {
- if (mAnimationController != null) {
- mAnimationController.unregisterRemoteAnimations();
- mAnimationController = null;
- }
- super.unregisterOrganizer();
- }
-
- /**
- * Overrides the animation for transitions of embedded activities organized by this organizer.
- */
- void overrideSplitAnimation() {
- if (mAnimationController == null) {
- mAnimationController = new TaskFragmentAnimationController(this);
- }
- mAnimationController.registerRemoteAnimations();
- }
-
/**
* Starts a new Activity and puts it into split with an existing Activity side-by-side.
* @param launchingFragmentToken token for the launching TaskFragment. If it exists, it will
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 7ddda1f98809..3261a370d2ca 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -114,7 +114,6 @@ import java.util.function.BiConsumer;
public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
ActivityEmbeddingComponent, DividerPresenter.DragEventCallback {
static final String TAG = "SplitController";
- static final boolean ENABLE_SHELL_TRANSITIONS = true;
// TODO(b/243518738): Move to WM Extensions if we have requirement of overlay without
// association. It's not set in WM Extensions nor Wm Jetpack library currently.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index eb1fc23d6b00..ea60b1531a3f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -166,11 +166,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
mWindowLayoutComponent = windowLayoutComponent;
mController = controller;
registerOrganizer();
- if (!SplitController.ENABLE_SHELL_TRANSITIONS) {
- // TODO(b/207070762): cleanup with legacy app transition
- // Animation will be handled by WM Shell when Shell transition is enabled.
- overrideSplitAnimation();
- }
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
deleted file mode 100644
index 33220c44a3b5..000000000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.window.extensions.embedding;
-
-import static android.graphics.Matrix.MTRANS_X;
-import static android.graphics.Matrix.MTRANS_Y;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.view.Choreographer;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
-
-import androidx.annotation.NonNull;
-
-/**
- * Wrapper to handle the TaskFragment animation update in one {@link SurfaceControl.Transaction}.
- *
- * The base adapter can be used for {@link RemoteAnimationTarget} that is simple open/close.
- */
-class TaskFragmentAnimationAdapter {
-
- /**
- * If {@link #mOverrideLayer} is set to this value, we don't want to override the surface layer.
- */
- private static final int LAYER_NO_OVERRIDE = -1;
-
- @NonNull
- final Animation mAnimation;
- @NonNull
- final RemoteAnimationTarget mTarget;
- @NonNull
- final SurfaceControl mLeash;
- /** Area in absolute coordinate that the animation surface shouldn't go beyond. */
- @NonNull
- private final Rect mWholeAnimationBounds = new Rect();
- /**
- * Area in absolute coordinate that should represent all the content to show for this window.
- * This should be the end bounds for opening window, and start bounds for closing window in case
- * the window is resizing during the open/close transition.
- */
- @NonNull
- private final Rect mContentBounds = new Rect();
- /** Offset relative to the window parent surface for {@link #mContentBounds}. */
- @NonNull
- private final Point mContentRelOffset = new Point();
-
- @NonNull
- final Transformation mTransformation = new Transformation();
- @NonNull
- final float[] mMatrix = new float[9];
- @NonNull
- final float[] mVecs = new float[4];
- @NonNull
- final Rect mRect = new Rect();
- private boolean mIsFirstFrame = true;
- private int mOverrideLayer = LAYER_NO_OVERRIDE;
-
- TaskFragmentAnimationAdapter(@NonNull Animation animation,
- @NonNull RemoteAnimationTarget target) {
- this(animation, target, target.leash, target.screenSpaceBounds);
- }
-
- /**
- * @param leash the surface to animate.
- * @param wholeAnimationBounds area in absolute coordinate that the animation surface shouldn't
- * go beyond.
- */
- TaskFragmentAnimationAdapter(@NonNull Animation animation,
- @NonNull RemoteAnimationTarget target, @NonNull SurfaceControl leash,
- @NonNull Rect wholeAnimationBounds) {
- mAnimation = animation;
- mTarget = target;
- mLeash = leash;
- mWholeAnimationBounds.set(wholeAnimationBounds);
- if (target.mode == MODE_CLOSING) {
- // When it is closing, we want to show the content at the start position in case the
- // window is resizing as well. For example, when the activities is changing from split
- // to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
- final Rect startBounds = target.startBounds;
- final Rect endBounds = target.screenSpaceBounds;
- mContentBounds.set(startBounds);
- mContentRelOffset.set(target.localBounds.left, target.localBounds.top);
- mContentRelOffset.offset(
- startBounds.left - endBounds.left,
- startBounds.top - endBounds.top);
- } else {
- mContentBounds.set(target.screenSpaceBounds);
- mContentRelOffset.set(target.localBounds.left, target.localBounds.top);
- }
- }
-
- /**
- * Surface layer to be set at the first frame of the animation. We will not set the layer if it
- * is set to {@link #LAYER_NO_OVERRIDE}.
- */
- final void overrideLayer(int layer) {
- mOverrideLayer = layer;
- }
-
- /** Called on frame update. */
- final void onAnimationUpdate(@NonNull SurfaceControl.Transaction t, long currentPlayTime) {
- if (mIsFirstFrame) {
- t.show(mLeash);
- if (mOverrideLayer != LAYER_NO_OVERRIDE) {
- t.setLayer(mLeash, mOverrideLayer);
- }
- mIsFirstFrame = false;
- }
-
- // Extract the transformation to the current time.
- mAnimation.getTransformation(Math.min(currentPlayTime, mAnimation.getDuration()),
- mTransformation);
- t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
- onAnimationUpdateInner(t);
- }
-
- /** To be overridden by subclasses to adjust the animation surface change. */
- void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
- // Update the surface position and alpha.
- mTransformation.getMatrix().postTranslate(mContentRelOffset.x, mContentRelOffset.y);
- t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
- t.setAlpha(mLeash, mTransformation.getAlpha());
-
- // Get current surface bounds in absolute coordinate.
- // positionX/Y are in local coordinate, so minus the local offset to get the slide amount.
- final int positionX = Math.round(mMatrix[MTRANS_X]);
- final int positionY = Math.round(mMatrix[MTRANS_Y]);
- final Rect cropRect = new Rect(mContentBounds);
- cropRect.offset(positionX - mContentRelOffset.x, positionY - mContentRelOffset.y);
-
- // Store the current offset of the surface top left from (0,0) in absolute coordinate.
- final int offsetX = cropRect.left;
- final int offsetY = cropRect.top;
-
- // Intersect to make sure the animation happens within the whole animation bounds.
- if (!cropRect.intersect(mWholeAnimationBounds)) {
- // Hide the surface when it is outside of the animation area.
- t.setAlpha(mLeash, 0);
- }
-
- // cropRect is in absolute coordinate, so we need to translate it to surface top left.
- cropRect.offset(-offsetX, -offsetY);
- t.setCrop(mLeash, cropRect);
- }
-
- /** Called after animation finished. */
- final void onAnimationEnd(@NonNull SurfaceControl.Transaction t) {
- onAnimationUpdate(t, mAnimation.getDuration());
- }
-
- final long getDurationHint() {
- return mAnimation.computeDurationHint();
- }
-
- /**
- * Should be used for the animation of the snapshot of a {@link RemoteAnimationTarget} that has
- * size change.
- */
- static class SnapshotAdapter extends TaskFragmentAnimationAdapter {
-
- SnapshotAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) {
- // Start leash is the snapshot of the starting surface.
- super(animation, target, target.startLeash, target.screenSpaceBounds);
- }
-
- @Override
- void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
- // Snapshot should always be placed at the top left of the animation leash.
- mTransformation.getMatrix().postTranslate(0, 0);
- t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
- t.setAlpha(mLeash, mTransformation.getAlpha());
- }
- }
-
- /**
- * Should be used for the animation of the {@link RemoteAnimationTarget} that has size change.
- */
- static class BoundsChangeAdapter extends TaskFragmentAnimationAdapter {
-
- BoundsChangeAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) {
- super(animation, target);
- }
-
- @Override
- void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) {
- mTransformation.getMatrix().postTranslate(
- mTarget.localBounds.left, mTarget.localBounds.top);
- t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
- t.setAlpha(mLeash, mTransformation.getAlpha());
-
- // The following applies an inverse scale to the clip-rect so that it crops "after" the
- // scale instead of before.
- mVecs[1] = mVecs[2] = 0;
- mVecs[0] = mVecs[3] = 1;
- mTransformation.getMatrix().mapVectors(mVecs);
- mVecs[0] = 1.f / mVecs[0];
- mVecs[3] = 1.f / mVecs[3];
- final Rect clipRect = mTransformation.getClipRect();
- mRect.left = (int) (clipRect.left * mVecs[0] + 0.5f);
- mRect.right = (int) (clipRect.right * mVecs[0] + 0.5f);
- mRect.top = (int) (clipRect.top * mVecs[3] + 0.5f);
- mRect.bottom = (int) (clipRect.bottom * mVecs[3] + 0.5f);
- t.setWindowCrop(mLeash, mRect);
- }
- }
-}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
deleted file mode 100644
index d7eb9a01f57c..000000000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.window.extensions.embedding;
-
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
-
-import android.util.Log;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationDefinition;
-import android.window.TaskFragmentOrganizer;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/** Controls the TaskFragment remote animations. */
-class TaskFragmentAnimationController {
-
- private static final String TAG = "TaskFragAnimationCtrl";
- static final boolean DEBUG = false;
-
- private final TaskFragmentOrganizer mOrganizer;
- private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner();
- @VisibleForTesting
- final RemoteAnimationDefinition mDefinition;
- private boolean mIsRegistered;
-
- TaskFragmentAnimationController(@NonNull TaskFragmentOrganizer organizer) {
- mOrganizer = organizer;
- mDefinition = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter animationAdapter =
- new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */);
- mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter);
- mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter);
- mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter);
- mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter);
- mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
- }
-
- void registerRemoteAnimations() {
- if (DEBUG) {
- Log.v(TAG, "registerRemoteAnimations");
- }
- if (mIsRegistered) {
- return;
- }
- mOrganizer.registerRemoteAnimations(mDefinition);
- mIsRegistered = true;
- }
-
- void unregisterRemoteAnimations() {
- if (DEBUG) {
- Log.v(TAG, "unregisterRemoteAnimations");
- }
- if (!mIsRegistered) {
- return;
- }
- mOrganizer.unregisterRemoteAnimations();
- mIsRegistered = false;
- }
-}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
deleted file mode 100644
index d9b73a8290f5..000000000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.window.extensions.embedding;
-
-import static android.os.Process.THREAD_PRIORITY_DISPLAY;
-import static android.view.RemoteAnimationTarget.MODE_CHANGING;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
-import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
-
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.view.animation.Animation;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.BiFunction;
-
-/** To run the TaskFragment animations. */
-class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub {
-
- private static final String TAG = "TaskFragAnimationRunner";
- private final Handler mHandler;
- private final TaskFragmentAnimationSpec mAnimationSpec;
-
- TaskFragmentAnimationRunner() {
- HandlerThread animationThread = new HandlerThread(
- "androidx.window.extensions.embedding", THREAD_PRIORITY_DISPLAY);
- animationThread.start();
- mHandler = animationThread.getThreadHandler();
- mAnimationSpec = new TaskFragmentAnimationSpec(mHandler);
- }
-
- @Nullable
- private Animator mAnimator;
-
- @Override
- public void onAnimationStart(@WindowManager.TransitionOldType int transit,
- @NonNull RemoteAnimationTarget[] apps,
- @NonNull RemoteAnimationTarget[] wallpapers,
- @NonNull RemoteAnimationTarget[] nonApps,
- @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
- if (wallpapers.length != 0 || nonApps.length != 0) {
- throw new IllegalArgumentException("TaskFragment shouldn't handle animation with"
- + "wallpaper or non-app windows.");
- }
- if (TaskFragmentAnimationController.DEBUG) {
- Log.v(TAG, "onAnimationStart transit=" + transit);
- }
- mHandler.post(() -> startAnimation(transit, apps, finishedCallback));
- }
-
- @Override
- public void onAnimationCancelled() {
- mHandler.post(this::cancelAnimation);
- }
-
- /** Creates and starts animation. */
- private void startAnimation(@WindowManager.TransitionOldType int transit,
- @NonNull RemoteAnimationTarget[] targets,
- @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
- if (mAnimator != null) {
- Log.w(TAG, "start new animation when the previous one is not finished yet.");
- mAnimator.cancel();
- }
- mAnimator = createAnimator(transit, targets, finishedCallback);
- mAnimator.start();
- }
-
- /** Cancels animation. */
- private void cancelAnimation() {
- if (mAnimator == null) {
- return;
- }
- mAnimator.cancel();
- mAnimator = null;
- }
-
- /** Creates the animator given the transition type and windows. */
- @NonNull
- private Animator createAnimator(@WindowManager.TransitionOldType int transit,
- @NonNull RemoteAnimationTarget[] targets,
- @NonNull IRemoteAnimationFinishedCallback finishedCallback) {
- final List<TaskFragmentAnimationAdapter> adapters =
- createAnimationAdapters(transit, targets);
- long duration = 0;
- for (TaskFragmentAnimationAdapter adapter : adapters) {
- duration = Math.max(duration, adapter.getDurationHint());
- }
- final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
- animator.setDuration(duration);
- animator.addUpdateListener((anim) -> {
- // Update all adapters in the same transaction.
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- for (TaskFragmentAnimationAdapter adapter : adapters) {
- adapter.onAnimationUpdate(t, animator.getCurrentPlayTime());
- }
- t.apply();
- });
- animator.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {}
-
- @Override
- public void onAnimationEnd(Animator animation) {
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- for (TaskFragmentAnimationAdapter adapter : adapters) {
- adapter.onAnimationEnd(t);
- }
- t.apply();
-
- try {
- finishedCallback.onAnimationFinished();
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- mAnimator = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {}
-
- @Override
- public void onAnimationRepeat(Animator animation) {}
- });
- return animator;
- }
-
- /** List of {@link TaskFragmentAnimationAdapter} to handle animations on all window targets. */
- @NonNull
- private List<TaskFragmentAnimationAdapter> createAnimationAdapters(
- @WindowManager.TransitionOldType int transit,
- @NonNull RemoteAnimationTarget[] targets) {
- switch (transit) {
- case TRANSIT_OLD_ACTIVITY_OPEN:
- case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
- return createOpenAnimationAdapters(targets);
- case TRANSIT_OLD_ACTIVITY_CLOSE:
- case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
- return createCloseAnimationAdapters(targets);
- case TRANSIT_OLD_TASK_FRAGMENT_CHANGE:
- return createChangeAnimationAdapters(targets);
- default:
- throw new IllegalArgumentException("Unhandled transit type=" + transit);
- }
- }
-
- @NonNull
- private List<TaskFragmentAnimationAdapter> createOpenAnimationAdapters(
- @NonNull RemoteAnimationTarget[] targets) {
- return createOpenCloseAnimationAdapters(targets, true /* isOpening */,
- mAnimationSpec::loadOpenAnimation);
- }
-
- @NonNull
- private List<TaskFragmentAnimationAdapter> createCloseAnimationAdapters(
- @NonNull RemoteAnimationTarget[] targets) {
- return createOpenCloseAnimationAdapters(targets, false /* isOpening */,
- mAnimationSpec::loadCloseAnimation);
- }
-
- /**
- * Creates {@link TaskFragmentAnimationAdapter} for OPEN and CLOSE types of transition.
- * @param isOpening {@code true} for OPEN type, {@code false} for CLOSE type.
- */
- @NonNull
- private List<TaskFragmentAnimationAdapter> createOpenCloseAnimationAdapters(
- @NonNull RemoteAnimationTarget[] targets, boolean isOpening,
- @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider) {
- // We need to know if the target window is only a partial of the whole animation screen.
- // If so, we will need to adjust it to make the whole animation screen looks like one.
- final List<RemoteAnimationTarget> openingTargets = new ArrayList<>();
- final List<RemoteAnimationTarget> closingTargets = new ArrayList<>();
- final Rect openingWholeScreenBounds = new Rect();
- final Rect closingWholeScreenBounds = new Rect();
- for (RemoteAnimationTarget target : targets) {
- if (target.mode != MODE_CLOSING) {
- openingTargets.add(target);
- openingWholeScreenBounds.union(target.screenSpaceBounds);
- } else {
- closingTargets.add(target);
- closingWholeScreenBounds.union(target.screenSpaceBounds);
- // Union the start bounds since this may be the ClosingChanging animation.
- closingWholeScreenBounds.union(target.startBounds);
- }
- }
-
- // For OPEN transition, open windows should be above close windows.
- // For CLOSE transition, open windows should be below close windows.
- int offsetLayer = TYPE_LAYER_OFFSET;
- final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>();
- for (RemoteAnimationTarget target : openingTargets) {
- final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target,
- animationProvider, openingWholeScreenBounds);
- if (isOpening) {
- adapter.overrideLayer(offsetLayer++);
- }
- adapters.add(adapter);
- }
- for (RemoteAnimationTarget target : closingTargets) {
- final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target,
- animationProvider, closingWholeScreenBounds);
- if (!isOpening) {
- adapter.overrideLayer(offsetLayer++);
- }
- adapters.add(adapter);
- }
- return adapters;
- }
-
- @NonNull
- private TaskFragmentAnimationAdapter createOpenCloseAnimationAdapter(
- @NonNull RemoteAnimationTarget target,
- @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider,
- @NonNull Rect wholeAnimationBounds) {
- final Animation animation = animationProvider.apply(target, wholeAnimationBounds);
- return new TaskFragmentAnimationAdapter(animation, target, target.leash,
- wholeAnimationBounds);
- }
-
- @NonNull
- private List<TaskFragmentAnimationAdapter> createChangeAnimationAdapters(
- @NonNull RemoteAnimationTarget[] targets) {
- if (shouldUseJumpCutForChangeAnimation(targets)) {
- return new ArrayList<>();
- }
-
- final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>();
- for (RemoteAnimationTarget target : targets) {
- if (target.mode == MODE_CHANGING) {
- // This is the target with bounds change.
- final Animation[] animations =
- mAnimationSpec.createChangeBoundsChangeAnimations(target);
- // Adapter for the starting snapshot leash.
- adapters.add(new TaskFragmentAnimationAdapter.SnapshotAdapter(
- animations[0], target));
- // Adapter for the ending bounds changed leash.
- adapters.add(new TaskFragmentAnimationAdapter.BoundsChangeAdapter(
- animations[1], target));
- continue;
- }
-
- // These are the other targets that don't have bounds change in the same transition.
- final Animation animation;
- if (target.hasAnimatingParent) {
- // No-op if it will be covered by the changing parent window.
- animation = TaskFragmentAnimationSpec.createNoopAnimation(target);
- } else if (target.mode == MODE_CLOSING) {
- animation = mAnimationSpec.createChangeBoundsCloseAnimation(target);
- } else {
- animation = mAnimationSpec.createChangeBoundsOpenAnimation(target);
- }
- adapters.add(new TaskFragmentAnimationAdapter(animation, target));
- }
- return adapters;
- }
-
- /**
- * Whether we should use jump cut for the change transition.
- * This normally happens when opening a new secondary with the existing primary using a
- * different split layout. This can be complicated, like from horizontal to vertical split with
- * new split pairs.
- * Uses a jump cut animation to simplify.
- */
- private boolean shouldUseJumpCutForChangeAnimation(@NonNull RemoteAnimationTarget[] targets) {
- boolean hasOpeningWindow = false;
- boolean hasClosingWindow = false;
- for (RemoteAnimationTarget target : targets) {
- if (target.hasAnimatingParent) {
- continue;
- }
- hasOpeningWindow |= target.mode == MODE_OPENING;
- hasClosingWindow |= target.mode == MODE_CLOSING;
- }
- return hasOpeningWindow && hasClosingWindow;
- }
-}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
deleted file mode 100644
index 1f866c3b99c9..000000000000
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.window.extensions.embedding;
-
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-
-import android.app.ActivityThread;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.provider.Settings;
-import android.view.RemoteAnimationTarget;
-import android.view.WindowManager;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
-import android.view.animation.AnimationUtils;
-import android.view.animation.ClipRectAnimation;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.ScaleAnimation;
-import android.view.animation.TranslateAnimation;
-
-import androidx.annotation.NonNull;
-
-import com.android.internal.R;
-import com.android.internal.policy.AttributeCache;
-import com.android.internal.policy.TransitionAnimation;
-
-/** Animation spec for TaskFragment transition. */
-// TODO(b/206557124): provide an easier way to customize animation
-class TaskFragmentAnimationSpec {
-
- private static final String TAG = "TaskFragAnimationSpec";
- private static final int CHANGE_ANIMATION_DURATION = 517;
- private static final int CHANGE_ANIMATION_FADE_DURATION = 80;
- private static final int CHANGE_ANIMATION_FADE_OFFSET = 30;
-
- private final Context mContext;
- private final TransitionAnimation mTransitionAnimation;
- private final Interpolator mFastOutExtraSlowInInterpolator;
- private final LinearInterpolator mLinearInterpolator;
- private float mTransitionAnimationScaleSetting;
-
- TaskFragmentAnimationSpec(@NonNull Handler handler) {
- mContext = ActivityThread.currentActivityThread().getApplication();
- mTransitionAnimation = new TransitionAnimation(mContext, false /* debug */, TAG);
- // Initialize the AttributeCache for the TransitionAnimation.
- AttributeCache.init(mContext);
- mFastOutExtraSlowInInterpolator = AnimationUtils.loadInterpolator(
- mContext, android.R.interpolator.fast_out_extra_slow_in);
- mLinearInterpolator = new LinearInterpolator();
-
- // The transition animation should be adjusted based on the developer option.
- final ContentResolver resolver = mContext.getContentResolver();
- mTransitionAnimationScaleSetting = getTransitionAnimationScaleSetting();
- resolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.TRANSITION_ANIMATION_SCALE), false,
- new SettingsObserver(handler));
- }
-
- /** For target that doesn't need to be animated. */
- @NonNull
- static Animation createNoopAnimation(@NonNull RemoteAnimationTarget target) {
- // Noop but just keep the target showing/hiding.
- final float alpha = target.mode == MODE_CLOSING ? 0f : 1f;
- return new AlphaAnimation(alpha, alpha);
- }
-
- /** Animation for target that is opening in a change transition. */
- @NonNull
- Animation createChangeBoundsOpenAnimation(@NonNull RemoteAnimationTarget target) {
- final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
- final Rect bounds = target.screenSpaceBounds;
- final int startLeft;
- final int startTop;
- if (parentBounds.top == bounds.top && parentBounds.bottom == bounds.bottom) {
- // The window will be animated in from left or right depending on its position.
- startTop = 0;
- startLeft = parentBounds.left == bounds.left ? -bounds.width() : bounds.width();
- } else {
- // The window will be animated in from top or bottom depending on its position.
- startTop = parentBounds.top == bounds.top ? -bounds.height() : bounds.height();
- startLeft = 0;
- }
-
- // The position should be 0-based as we will post translate in
- // TaskFragmentAnimationAdapter#onAnimationUpdate
- final Animation animation = new TranslateAnimation(startLeft, 0, startTop, 0);
- animation.setInterpolator(mFastOutExtraSlowInInterpolator);
- animation.setDuration(CHANGE_ANIMATION_DURATION);
- animation.initialize(bounds.width(), bounds.height(), bounds.width(), bounds.height());
- animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- return animation;
- }
-
- /** Animation for target that is closing in a change transition. */
- @NonNull
- Animation createChangeBoundsCloseAnimation(@NonNull RemoteAnimationTarget target) {
- final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
- // Use startBounds if the window is closing in case it may also resize.
- final Rect bounds = target.startBounds;
- final int endTop;
- final int endLeft;
- if (parentBounds.top == bounds.top && parentBounds.bottom == bounds.bottom) {
- // The window will be animated out to left or right depending on its position.
- endTop = 0;
- endLeft = parentBounds.left == bounds.left ? -bounds.width() : bounds.width();
- } else {
- // The window will be animated out to top or bottom depending on its position.
- endTop = parentBounds.top == bounds.top ? -bounds.height() : bounds.height();
- endLeft = 0;
- }
-
- // The position should be 0-based as we will post translate in
- // TaskFragmentAnimationAdapter#onAnimationUpdate
- final Animation animation = new TranslateAnimation(0, endLeft, 0, endTop);
- animation.setInterpolator(mFastOutExtraSlowInInterpolator);
- animation.setDuration(CHANGE_ANIMATION_DURATION);
- animation.initialize(bounds.width(), bounds.height(), bounds.width(), bounds.height());
- animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- return animation;
- }
-
- /**
- * Animation for target that is changing (bounds change) in a change transition.
- * @return the return array always has two elements. The first one is for the start leash, and
- * the second one is for the end leash.
- */
- @NonNull
- Animation[] createChangeBoundsChangeAnimations(@NonNull RemoteAnimationTarget target) {
- // Both start bounds and end bounds are in screen coordinates. We will post translate
- // to the local coordinates in TaskFragmentAnimationAdapter#onAnimationUpdate
- final Rect startBounds = target.startBounds;
- final Rect parentBounds = target.taskInfo.configuration.windowConfiguration.getBounds();
- final Rect endBounds = target.screenSpaceBounds;
- float scaleX = ((float) startBounds.width()) / endBounds.width();
- float scaleY = ((float) startBounds.height()) / endBounds.height();
- // Start leash is a child of the end leash. Reverse the scale so that the start leash won't
- // be scaled up with its parent.
- float startScaleX = 1.f / scaleX;
- float startScaleY = 1.f / scaleY;
-
- // The start leash will be fade out.
- final AnimationSet startSet = new AnimationSet(false /* shareInterpolator */);
- final Animation startAlpha = new AlphaAnimation(1f, 0f);
- startAlpha.setInterpolator(mLinearInterpolator);
- startAlpha.setDuration(CHANGE_ANIMATION_FADE_DURATION);
- startAlpha.setStartOffset(CHANGE_ANIMATION_FADE_OFFSET);
- startSet.addAnimation(startAlpha);
- final Animation startScale = new ScaleAnimation(startScaleX, startScaleX, startScaleY,
- startScaleY);
- startScale.setInterpolator(mFastOutExtraSlowInInterpolator);
- startScale.setDuration(CHANGE_ANIMATION_DURATION);
- startSet.addAnimation(startScale);
- startSet.initialize(startBounds.width(), startBounds.height(), endBounds.width(),
- endBounds.height());
- startSet.scaleCurrentDuration(mTransitionAnimationScaleSetting);
-
- // The end leash will be moved into the end position while scaling.
- final AnimationSet endSet = new AnimationSet(true /* shareInterpolator */);
- endSet.setInterpolator(mFastOutExtraSlowInInterpolator);
- final Animation endScale = new ScaleAnimation(scaleX, 1, scaleY, 1);
- endScale.setDuration(CHANGE_ANIMATION_DURATION);
- endSet.addAnimation(endScale);
- // The position should be 0-based as we will post translate in
- // TaskFragmentAnimationAdapter#onAnimationUpdate
- final Animation endTranslate = new TranslateAnimation(startBounds.left - endBounds.left, 0,
- startBounds.top - endBounds.top, 0);
- endTranslate.setDuration(CHANGE_ANIMATION_DURATION);
- endSet.addAnimation(endTranslate);
- // The end leash is resizing, we should update the window crop based on the clip rect.
- final Rect startClip = new Rect(startBounds);
- final Rect endClip = new Rect(endBounds);
- startClip.offsetTo(0, 0);
- endClip.offsetTo(0, 0);
- final Animation clipAnim = new ClipRectAnimation(startClip, endClip);
- clipAnim.setDuration(CHANGE_ANIMATION_DURATION);
- endSet.addAnimation(clipAnim);
- endSet.initialize(startBounds.width(), startBounds.height(), parentBounds.width(),
- parentBounds.height());
- endSet.scaleCurrentDuration(mTransitionAnimationScaleSetting);
-
- return new Animation[]{startSet, endSet};
- }
-
- @NonNull
- Animation loadOpenAnimation(@NonNull RemoteAnimationTarget target,
- @NonNull Rect wholeAnimationBounds) {
- final boolean isEnter = target.mode != MODE_CLOSING;
- final Animation animation;
- // Background color on TaskDisplayArea has already been set earlier in
- // WindowContainer#getAnimationAdapter.
- if (target.showBackdrop) {
- animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_clear_top_open_enter
- : com.android.internal.R.anim.task_fragment_clear_top_open_exit);
- } else {
- animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_open_enter
- : com.android.internal.R.anim.task_fragment_open_exit);
- }
- // Use the whole animation bounds instead of the change bounds, so that when multiple change
- // targets are opening at the same time, the animation applied to each will be the same.
- // Otherwise, we may see gap between the activities that are launching together.
- animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(),
- wholeAnimationBounds.width(), wholeAnimationBounds.height());
- animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- return animation;
- }
-
- @NonNull
- Animation loadCloseAnimation(@NonNull RemoteAnimationTarget target,
- @NonNull Rect wholeAnimationBounds) {
- final boolean isEnter = target.mode != MODE_CLOSING;
- final Animation animation;
- if (target.showBackdrop) {
- animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_clear_top_close_enter
- : com.android.internal.R.anim.task_fragment_clear_top_close_exit);
- } else {
- animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_close_enter
- : com.android.internal.R.anim.task_fragment_close_exit);
- }
- // Use the whole animation bounds instead of the change bounds, so that when multiple change
- // targets are closing at the same time, the animation applied to each will be the same.
- // Otherwise, we may see gap between the activities that are finishing together.
- animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(),
- wholeAnimationBounds.width(), wholeAnimationBounds.height());
- animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
- return animation;
- }
-
- private float getTransitionAnimationScaleSetting() {
- return WindowManager.fixScale(Settings.Global.getFloat(mContext.getContentResolver(),
- Settings.Global.TRANSITION_ANIMATION_SCALE, mContext.getResources().getFloat(
- R.dimen.config_appTransitionAnimationDurationScaleDefault)));
- }
-
- private class SettingsObserver extends ContentObserver {
- SettingsObserver(@NonNull Handler handler) {
- super(handler);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- mTransitionAnimationScaleSetting = getTransitionAnimationScaleSetting();
- }
- }
-}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index 7b473b04548c..ad41b18dcbc6 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -23,8 +23,6 @@ import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTest
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -86,24 +84,6 @@ public class JetpackTaskFragmentOrganizerTest {
}
@Test
- public void testUnregisterOrganizer() {
- mOrganizer.overrideSplitAnimation();
- mOrganizer.unregisterOrganizer();
-
- verify(mOrganizer).unregisterRemoteAnimations();
- }
-
- @Test
- public void testOverrideSplitAnimation() {
- assertNull(mOrganizer.mAnimationController);
-
- mOrganizer.overrideSplitAnimation();
-
- assertNotNull(mOrganizer.mAnimationController);
- verify(mOrganizer).registerRemoteAnimations(mOrganizer.mAnimationController.mDefinition);
- }
-
- @Test
public void testExpandTaskFragment() {
final TaskContainer taskContainer = createTestTaskContainer();
doReturn(taskContainer).when(mSplitController).getTaskContainer(anyInt());
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
deleted file mode 100644
index a1e9f08585f6..000000000000
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentAnimationControllerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.window.extensions.embedding;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-
-import static org.mockito.Mockito.never;
-
-import android.platform.test.annotations.Presubmit;
-import android.window.TaskFragmentOrganizer;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-/**
- * Test class for {@link TaskFragmentAnimationController}.
- *
- * Build/Install/Run:
- * atest WMJetpackUnitTests:TaskFragmentAnimationControllerTest
- */
-@Presubmit
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class TaskFragmentAnimationControllerTest {
- @Rule
- public MockitoRule rule = MockitoJUnit.rule();
-
- @Mock
- private TaskFragmentOrganizer mOrganizer;
- private TaskFragmentAnimationController mAnimationController;
-
- @Before
- public void setup() {
- mAnimationController = new TaskFragmentAnimationController(mOrganizer);
- }
-
- @Test
- public void testRegisterRemoteAnimations() {
- mAnimationController.registerRemoteAnimations();
-
- verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition);
-
- mAnimationController.registerRemoteAnimations();
-
- // No extra call if it has been registered.
- verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition);
- }
-
- @Test
- public void testUnregisterRemoteAnimations() {
- mAnimationController.unregisterRemoteAnimations();
-
- // No call if it is not registered.
- verify(mOrganizer, never()).unregisterRemoteAnimations();
-
- mAnimationController.registerRemoteAnimations();
- mAnimationController.unregisterRemoteAnimations();
-
- verify(mOrganizer).unregisterRemoteAnimations();
-
- mAnimationController.unregisterRemoteAnimations();
-
- // No extra call if it has been unregistered.
- verify(mOrganizer).unregisterRemoteAnimations();
- }
-}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 44b414f1ea7e..78636a7870cf 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -98,7 +98,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -290,12 +289,10 @@ public class AppTransitionController {
getTopApp(mDisplayContent.mChangingContainers, false /* ignoreHidden */);
final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
- // 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);
- }
+ // No AE remote animation with Shell transition.
+ // Unfreeze the windows that were previously frozen for TaskFragment animation.
+ unfreezeEmbeddedChangingWindows();
+ overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mClosingApps)
|| containsVoiceInteraction(mDisplayContent.mOpeningApps);
@@ -726,64 +723,6 @@ public class AppTransitionController {
}
/**
- * Overrides the pending transition with the remote animation defined by the
- * {@link ITaskFragmentOrganizer} if all windows in the transition are children of
- * {@link TaskFragment} that are organized by the same organizer.
- *
- * @return {@code true} if the transition is overridden.
- */
- private boolean overrideWithTaskFragmentRemoteAnimation(@TransitionOldType int transit,
- ArraySet<Integer> activityTypes) {
- if (transitionMayContainNonAppWindows(transit)) {
- return false;
- }
- if (!transitionContainsTaskFragmentWithBoundsOverride()) {
- // No need to play TaskFragment remote animation if all embedded TaskFragment in the
- // transition fill the Task.
- return false;
- }
-
- final Task task = findParentTaskForAllEmbeddedWindows();
- final ITaskFragmentOrganizer organizer = findTaskFragmentOrganizer(task);
- final RemoteAnimationDefinition definition = organizer != null
- ? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
- .getRemoteAnimationDefinition(organizer)
- : null;
- final RemoteAnimationAdapter adapter = definition != null
- ? definition.getAdapter(transit, activityTypes)
- : null;
- if (adapter == null) {
- return false;
- }
- mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(
- adapter, false /* sync */, true /*isActivityEmbedding*/);
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "Override with TaskFragment remote animation for transit=%s",
- AppTransition.appTransitionOldToString(transit));
-
- final int organizerUid = mDisplayContent.mAtmService.mTaskFragmentOrganizerController
- .getTaskFragmentOrganizerUid(organizer);
- final boolean shouldDisableInputForRemoteAnimation = !task.isFullyTrustedEmbedding(
- organizerUid);
- final RemoteAnimationController remoteAnimationController =
- mDisplayContent.mAppTransition.getRemoteAnimationController();
- if (shouldDisableInputForRemoteAnimation && remoteAnimationController != null) {
- // We are going to use client-driven animation, Disable all input on activity windows
- // during the animation (unless it is fully trusted) to ensure it is safe to allow
- // client to animate the surfaces.
- // This is needed for all activity windows in the animation Task.
- remoteAnimationController.setOnRemoteAnimationReady(() -> {
- final Consumer<ActivityRecord> updateActivities =
- activity -> activity.setDropInputForAnimation(true);
- task.forAllActivities(updateActivities);
- });
- ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "Task=%d contains embedded TaskFragment."
- + " Disabled all input during TaskFragment remote animation.", task.mTaskId);
- }
- return true;
- }
-
- /**
* Overrides the pending transition with the remote animation defined for the transition in the
* set of defined remote animations in the app window token.
*/
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index b6b6cf2dc430..439c7bb4050b 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -46,7 +46,6 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
import android.window.ITaskFragmentOrganizer;
import android.window.ITaskFragmentOrganizerController;
@@ -58,8 +57,8 @@ import android.window.TaskFragmentTransaction;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.ProtoLog;
+import com.android.internal.protolog.ProtoLogGroup;
import com.android.window.flags.Flags;
import java.lang.annotation.Retention;
@@ -146,13 +145,6 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
private final boolean mIsSystemOrganizer;
/**
- * {@link RemoteAnimationDefinition} for embedded activities transition animation that is
- * organized by this organizer.
- */
- @Nullable
- private RemoteAnimationDefinition mRemoteAnimationDefinition;
-
- /**
* Map from {@link TaskFragmentTransaction#getTransactionToken()} to the
* {@link Transition#getSyncId()} that has been deferred. {@link TransitionController} will
* wait until the organizer finished handling the {@link TaskFragmentTransaction}.
@@ -533,50 +525,6 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
}
@Override
- public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer,
- @NonNull RemoteAnimationDefinition definition) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- synchronized (mGlobalLock) {
- ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
- "Register remote animations for organizer=%s uid=%d pid=%d",
- organizer.asBinder(), uid, pid);
- final TaskFragmentOrganizerState organizerState =
- mTaskFragmentOrganizerState.get(organizer.asBinder());
- if (organizerState == null) {
- throw new IllegalStateException("The organizer hasn't been registered.");
- }
- if (organizerState.mRemoteAnimationDefinition != null) {
- throw new IllegalStateException(
- "The organizer has already registered remote animations="
- + organizerState.mRemoteAnimationDefinition);
- }
-
- definition.setCallingPidUid(pid, uid);
- organizerState.mRemoteAnimationDefinition = definition;
- }
- }
-
- @Override
- public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer) {
- final int pid = Binder.getCallingPid();
- final long uid = Binder.getCallingUid();
- synchronized (mGlobalLock) {
- ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
- "Unregister remote animations for organizer=%s uid=%d pid=%d",
- organizer.asBinder(), uid, pid);
- final TaskFragmentOrganizerState organizerState =
- mTaskFragmentOrganizerState.get(organizer.asBinder());
- if (organizerState == null) {
- Slog.e(TAG, "The organizer hasn't been registered.");
- return;
- }
-
- organizerState.mRemoteAnimationDefinition = null;
- }
- }
-
- @Override
public void onTransactionHandled(@NonNull IBinder transactionToken,
@NonNull WindowContainerTransaction wct,
@WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
@@ -617,25 +565,6 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
}
}
- /**
- * Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. Returns
- * {@code null} if it doesn't.
- */
- @Nullable
- public RemoteAnimationDefinition getRemoteAnimationDefinition(
- @NonNull ITaskFragmentOrganizer organizer) {
- synchronized (mGlobalLock) {
- final TaskFragmentOrganizerState organizerState =
- mTaskFragmentOrganizerState.get(organizer.asBinder());
- if (organizerState == null) {
- Slog.e(TAG, "TaskFragmentOrganizer has been unregistered or died when trying"
- + " to play animation on its organized windows.");
- return null;
- }
- return organizerState.mRemoteAnimationDefinition;
- }
- }
-
int getTaskFragmentOrganizerUid(@NonNull ITaskFragmentOrganizer organizer) {
final TaskFragmentOrganizerState state = validateAndGetState(organizer);
return state.mOrganizerUid;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 0c1fbf3cb3d7..af4394acce67 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -25,15 +25,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -41,7 +37,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -51,14 +46,11 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.annotation.Nullable;
-import android.graphics.Rect;
-import android.gui.DropInputMode;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -841,353 +833,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
}
@Test
- public void testOverrideTaskFragmentAdapter_overrideWithEmbeddedActivity() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord activity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(activity);
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation run by the remote handler.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_noOverrideWithOnlyTaskFragmentFillingTask() {
- final Task task = createTask(mDisplayContent);
- final ActivityRecord closingActivity = createActivityRecord(task);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
-
- // Make sure the TaskFragment is not embedded.
- assertFalse(taskFragment.isEmbeddedWithBoundsOverride());
- final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(closingActivity);
- prepareActivityForAppTransition(openingActivity);
- final int uid = 12345;
- closingActivity.info.applicationInfo.uid = uid;
- openingActivity.info.applicationInfo.uid = uid;
- task.effectiveUid = uid;
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity,
- null /* changingTaskFragment */);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation is not run by the remote handler because the activity is filling the Task.
- assertFalse(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_overrideWithTaskFragmentNotFillingTask() {
- final Task task = createTask(mDisplayContent);
- final ActivityRecord closingActivity = createActivityRecord(task);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
-
- // Make sure the TaskFragment is embedded.
- taskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
- final Rect embeddedBounds = new Rect(task.getBounds());
- embeddedBounds.right = embeddedBounds.left + embeddedBounds.width() / 2;
- taskFragment.setBounds(embeddedBounds);
- assertTrue(taskFragment.isEmbeddedWithBoundsOverride());
- final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(closingActivity);
- prepareActivityForAppTransition(openingActivity);
- final int uid = 12345;
- closingActivity.info.applicationInfo.uid = uid;
- openingActivity.info.applicationInfo.uid = uid;
- task.effectiveUid = uid;
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity,
- null /* changingTaskFragment */);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation run by the remote handler.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_overrideWithNonEmbeddedActivity() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Closing non-embedded activity.
- final ActivityRecord closingActivity = createActivityRecord(task);
- prepareActivityForAppTransition(closingActivity);
- // Opening TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(openingActivity);
- task.effectiveUid = openingActivity.getUid();
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation run by the remote handler.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_overrideEmbeddedActivityWithDiffUid() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Closing TaskFragment with embedded activity.
- final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord closingActivity = taskFragment1.getTopMostActivity();
- prepareActivityForAppTransition(closingActivity);
- closingActivity.info.applicationInfo.uid = 12345;
- // Opening TaskFragment with embedded activity with different UID.
- final TaskFragment taskFragment2 = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord openingActivity = taskFragment2.getTopMostActivity();
- prepareActivityForAppTransition(openingActivity);
- openingActivity.info.applicationInfo.uid = 54321;
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment1);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation run by the remote handler.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_noOverrideWithTwoApps() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Closing activity in Task1.
- final ActivityRecord closingActivity = createActivityRecord(mDisplayContent);
- prepareActivityForAppTransition(closingActivity);
- // Opening TaskFragment with embedded activity in Task2.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(openingActivity);
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation not run by the remote handler.
- assertFalse(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_noOverrideNonEmbeddedActivityWithDiffUid() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Closing TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord closingActivity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(closingActivity);
- closingActivity.info.applicationInfo.uid = 12345;
- task.effectiveUid = closingActivity.getUid();
- // Opening non-embedded activity with different UID.
- final ActivityRecord openingActivity = createActivityRecord(task);
- prepareActivityForAppTransition(openingActivity);
- openingActivity.info.applicationInfo.uid = 54321;
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(openingActivity, closingActivity, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation should not run by the remote handler when there are non-embedded activities of
- // different UID.
- assertFalse(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_noOverrideWithWallpaper() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with embedded activity.
- final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
- final ActivityRecord activity = taskFragment.getTopMostActivity();
- prepareActivityForAppTransition(activity);
- // Set wallpaper as visible.
- final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
- mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
- spyOn(mDisplayContent.mWallpaperController);
- doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // Animation should not run by the remote handler when there is wallpaper in the transition.
- assertFalse(remoteAnimationRunner.isAnimationStarted());
- }
-
- @Test
- public void testOverrideTaskFragmentAdapter_inputProtectedForUntrustedAnimation() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with embedded activities, one is trusted embedded, and the other
- // one is untrusted embedded.
- final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .createActivityCount(2)
- .setOrganizer(organizer)
- .build();
- final ActivityRecord activity0 = taskFragment.getChildAt(0).asActivityRecord();
- final ActivityRecord activity1 = taskFragment.getChildAt(1).asActivityRecord();
- // Also create a non-embedded activity in the Task.
- final ActivityRecord activity2 = new ActivityBuilder(mAtm).build();
- task.addChild(activity2, POSITION_BOTTOM);
- prepareActivityForAppTransition(activity0);
- prepareActivityForAppTransition(activity1);
- prepareActivityForAppTransition(activity2);
- doReturn(false).when(taskFragment).isAllowedToEmbedActivityInTrustedMode(activity0);
- doReturn(true).when(taskFragment).isAllowedToEmbedActivityInTrustedMode(activity1);
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(activity1, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // The animation will be animated remotely by client and all activities are input disabled
- // for untrusted animation.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- verify(activity0).setDropInputForAnimation(true);
- verify(activity1).setDropInputForAnimation(true);
- verify(activity2).setDropInputForAnimation(true);
- verify(activity0).setDropInputMode(DropInputMode.ALL);
- verify(activity1).setDropInputMode(DropInputMode.ALL);
- verify(activity2).setDropInputMode(DropInputMode.ALL);
-
- // Reset input after animation is finished.
- clearInvocations(activity0);
- clearInvocations(activity1);
- clearInvocations(activity2);
- remoteAnimationRunner.finishAnimation();
-
- verify(activity0).setDropInputForAnimation(false);
- verify(activity1).setDropInputForAnimation(false);
- verify(activity2).setDropInputForAnimation(false);
- verify(activity0).setDropInputMode(DropInputMode.OBSCURED);
- verify(activity1).setDropInputMode(DropInputMode.NONE);
- verify(activity2).setDropInputMode(DropInputMode.NONE);
- }
-
- /**
- * Since we don't have any use case to rely on handling input during animation, disable it even
- * if it is trusted embedding so that it could cover some edge-cases when a previously trusted
- * host starts doing something bad.
- */
- @Test
- public void testOverrideTaskFragmentAdapter_inputProtectedForTrustedAnimation() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with only trusted embedded activity
- final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .createActivityCount(1)
- .setOrganizer(organizer)
- .build();
- final ActivityRecord activity = taskFragment.getChildAt(0).asActivityRecord();
- prepareActivityForAppTransition(activity);
- doReturn(true).when(taskFragment).isAllowedToEmbedActivityInTrustedMode(activity);
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // The animation will be animated remotely by client and all activities are input disabled
- // for untrusted animation.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- verify(activity).setDropInputForAnimation(true);
- verify(activity).setDropInputMode(DropInputMode.ALL);
-
- // Reset input after animation is finished.
- clearInvocations(activity);
- remoteAnimationRunner.finishAnimation();
-
- verify(activity).setDropInputForAnimation(false);
- verify(activity).setDropInputMode(DropInputMode.NONE);
- }
-
- /**
- * We don't need to drop input for fully trusted embedding (system app, and embedding in the
- * same app). This will allow users to do fast tapping.
- */
- @Test
- public void testOverrideTaskFragmentAdapter_noInputProtectedForFullyTrustedAnimation() {
- final Task task = createTask(mDisplayContent);
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner();
- setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner);
-
- // Create a TaskFragment with only trusted embedded activity
- final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .createActivityCount(1)
- .setOrganizer(organizer)
- .build();
- final ActivityRecord activity = taskFragment.getChildAt(0).asActivityRecord();
- prepareActivityForAppTransition(activity);
- final int uid = mAtm.mTaskFragmentOrganizerController.getTaskFragmentOrganizerUid(
- getITaskFragmentOrganizer(organizer));
- doReturn(true).when(task).isFullyTrustedEmbedding(uid);
- spyOn(mDisplayContent.mAppTransition);
-
- // Prepare and start transition.
- prepareAndTriggerAppTransition(activity, null /* closingActivity */, taskFragment);
- mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
-
- // The animation will be animated remotely by client, but input should not be dropped for
- // fully trusted.
- assertTrue(remoteAnimationRunner.isAnimationStarted());
- verify(activity, never()).setDropInputForAnimation(true);
- verify(activity, never()).setDropInputMode(DropInputMode.ALL);
- }
-
- @Test
public void testTransitionGoodToGoForTaskFragments() {
final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
final Task task = createTask(mDisplayContent);
@@ -1253,22 +898,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
verify(mDisplayContent.mAppTransition).goodToGo(anyInt(), any());
}
- /** Registers remote animation for the organizer. */
- private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer,
- TestRemoteAnimationRunner remoteAnimationRunner) {
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- remoteAnimationRunner, 10, 1);
- final ITaskFragmentOrganizer iOrganizer = getITaskFragmentOrganizer(organizer);
- final RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, adapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, adapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, adapter);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, adapter);
- registerTaskFragmentOrganizer(iOrganizer);
- mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, definition);
- }
-
private static ITaskFragmentOrganizer getITaskFragmentOrganizer(
TaskFragmentOrganizer organizer) {
return ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index a71b81e025d2..d013053a063d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -90,7 +90,6 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
-import android.view.RemoteAnimationDefinition;
import android.view.SurfaceControl;
import android.window.IRemoteTransition;
import android.window.ITaskFragmentOrganizer;
@@ -140,7 +139,6 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
private IBinder mFragmentToken;
private WindowContainerTransaction mTransaction;
private WindowContainerToken mFragmentWindowToken;
- private RemoteAnimationDefinition mDefinition;
private IBinder mErrorToken;
private Rect mTaskFragBounds;
@@ -169,7 +167,6 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
mTransaction = new WindowContainerTransaction();
mTransaction.setTaskFragmentOrganizer(mIOrganizer);
mFragmentWindowToken = mTaskFragment.mRemoteToken.toWindowContainerToken();
- mDefinition = new RemoteAnimationDefinition();
mErrorToken = new Binder();
final Rect displayBounds = mDisplayContent.getBounds();
mTaskFragBounds = new Rect(displayBounds.left, displayBounds.top, displayBounds.centerX(),
@@ -579,17 +576,6 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
}
@Test
- public void testRegisterRemoteAnimations() {
- mController.registerRemoteAnimations(mIOrganizer, mDefinition);
-
- assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer));
-
- mController.unregisterRemoteAnimations(mIOrganizer);
-
- assertNull(mController.getRemoteAnimationDefinition(mIOrganizer));
- }
-
- @Test
public void testApplyTransaction_disallowRemoteTransitionForNonSystemOrganizer() {
mTransaction.setRelativeBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100));
mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,