diff options
14 files changed, 194 insertions, 191 deletions
diff --git a/core/java/android/window/ITaskFragmentOrganizerController.aidl b/core/java/android/window/ITaskFragmentOrganizerController.aidl index 3250dd8f7308..d25c8a834c7b 100644 --- a/core/java/android/window/ITaskFragmentOrganizerController.aidl +++ b/core/java/android/window/ITaskFragmentOrganizerController.aidl @@ -39,13 +39,13 @@ interface ITaskFragmentOrganizerController { * animations if the transition only contains windows that belong to the organized * TaskFragments in the given Task. */ - void registerRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId, + void registerRemoteAnimations(in ITaskFragmentOrganizer organizer, in RemoteAnimationDefinition definition); /** * Unregisters remote animations per transition type for the organizer. */ - void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer, int taskId); + void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer); /** * Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java index 8df6541aed9e..ef19c55019dc 100644 --- a/core/java/android/window/TaskFragmentOrganizer.java +++ b/core/java/android/window/TaskFragmentOrganizer.java @@ -122,16 +122,13 @@ 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 in the given Task. - * - * @param taskId overrides if the transition only contains windows belonging to this Task. + * TaskFragments, and at least one of the transition window is embedded (not filling the Task). * @hide */ @CallSuper - public void registerRemoteAnimations(int taskId, - @NonNull RemoteAnimationDefinition definition) { + public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) { try { - getController().registerRemoteAnimations(mInterface, taskId, definition); + getController().registerRemoteAnimations(mInterface, definition); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -142,9 +139,9 @@ public class TaskFragmentOrganizer extends WindowOrganizer { * @hide */ @CallSuper - public void unregisterRemoteAnimations(int taskId) { + public void unregisterRemoteAnimations() { try { - getController().unregisterRemoteAnimations(mInterface, taskId); + getController().unregisterRemoteAnimations(mInterface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } 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 9d841ea2e55d..d7d43aa19757 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java @@ -37,7 +37,6 @@ import android.window.TaskFragmentOrganizer; import android.window.TaskFragmentTransaction; import android.window.WindowContainerTransaction; -import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -85,26 +84,20 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { @Override public void unregisterOrganizer() { if (mAnimationController != null) { - mAnimationController.unregisterAllRemoteAnimations(); + mAnimationController.unregisterRemoteAnimations(); mAnimationController = null; } super.unregisterOrganizer(); } - /** Overrides the animation if the transition is on the given Task. */ - void startOverrideSplitAnimation(int taskId) { + /** + * Overrides the animation for transitions of embedded activities organized by this organizer. + */ + void overrideSplitAnimation() { if (mAnimationController == null) { mAnimationController = new TaskFragmentAnimationController(this); } - mAnimationController.registerRemoteAnimations(taskId); - } - - /** No longer overrides the animation if the transition is on the given Task. */ - @GuardedBy("mLock") - void stopOverrideSplitAnimation(int taskId) { - if (mAnimationController != null) { - mAnimationController.unregisterRemoteAnimations(taskId); - } + mAnimationController.registerRemoteAnimations(); } /** 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 d52caaf4c3e8..c06548ad81a1 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -193,7 +193,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen continue; } updateContainersInTask(wct, taskContainer); - updateAnimationOverride(taskContainer); } // The WCT should be applied and merged to the device state change transition if // there is one. @@ -208,9 +207,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen synchronized (mLock) { mSplitRules.clear(); mSplitRules.addAll(rules); - for (int i = mTaskContainers.size() - 1; i >= 0; i--) { - updateAnimationOverride(mTaskContainers.valueAt(i)); - } } } @@ -612,7 +608,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } if (taskContainer.isEmpty()) { // Cleanup the TaskContainer if it becomes empty. - mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId()); mTaskContainers.remove(taskContainer.getTaskId()); } return; @@ -622,43 +617,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @GuardedBy("mLock") private void onTaskContainerInfoChanged(@NonNull TaskContainer taskContainer, @NonNull Configuration config) { - final boolean wasInPip = taskContainer.isInPictureInPicture(); - final boolean isInPIp = isInPictureInPicture(config); - - // We need to check the animation override when enter/exit PIP or has bounds changed. - boolean shouldUpdateAnimationOverride = wasInPip != isInPIp; - if (taskContainer.setTaskBounds(config.windowConfiguration.getBounds()) - && !isInPIp) { - // We don't care the bounds change when it has already entered PIP. - shouldUpdateAnimationOverride = true; - } - if (shouldUpdateAnimationOverride) { - updateAnimationOverride(taskContainer); - } - } - - /** - * Updates if we should override transition animation. We only want to override if the Task - * bounds is large enough for at least one split rule. - */ - @GuardedBy("mLock") - private void updateAnimationOverride(@NonNull TaskContainer taskContainer) { - if (ENABLE_SHELL_TRANSITIONS) { - // TODO(b/207070762): cleanup with legacy app transition - // Animation will be handled by WM Shell with Shell transition enabled. - return; - } - if (!taskContainer.isTaskBoundsInitialized()) { - // We don't know about the Task bounds/windowingMode yet. - return; - } - - // We only want to override if the TaskContainer may show split. - if (mayShowSplit(taskContainer)) { - mPresenter.startOverrideSplitAnimation(taskContainer.getTaskId()); - } else { - mPresenter.stopOverrideSplitAnimation(taskContainer.getTaskId()); - } + taskContainer.setTaskBounds(config.windowConfiguration.getBounds()); } /** Returns whether the given {@link TaskContainer} may show in split. */ @@ -1283,7 +1242,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen Log.w(TAG, "Can't find bounds from activity=" + activityInTask); } } - updateAnimationOverride(taskContainer); return container; } 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 cb470bac5c9a..f494b32cff14 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -139,6 +139,11 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { super(executor, controller); 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/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java index ee2e139bb0b2..d7eb9a01f57c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java @@ -18,13 +18,10 @@ 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_CLOSE; 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 android.util.ArraySet; import android.util.Log; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationDefinition; @@ -44,8 +41,7 @@ class TaskFragmentAnimationController { private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner(); @VisibleForTesting final RemoteAnimationDefinition mDefinition; - /** Task Ids that we have registered for remote animation. */ - private final ArraySet<Integer> mRegisterTasks = new ArraySet<>(); + private boolean mIsRegistered; TaskFragmentAnimationController(@NonNull TaskFragmentOrganizer organizer) { mOrganizer = organizer; @@ -54,39 +50,30 @@ class TaskFragmentAnimationController { 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_TASK_OPEN, animationAdapter); mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter); mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter); - mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter); mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter); } - void registerRemoteAnimations(int taskId) { + void registerRemoteAnimations() { if (DEBUG) { Log.v(TAG, "registerRemoteAnimations"); } - if (mRegisterTasks.contains(taskId)) { + if (mIsRegistered) { return; } - mOrganizer.registerRemoteAnimations(taskId, mDefinition); - mRegisterTasks.add(taskId); + mOrganizer.registerRemoteAnimations(mDefinition); + mIsRegistered = true; } - void unregisterRemoteAnimations(int taskId) { + void unregisterRemoteAnimations() { if (DEBUG) { Log.v(TAG, "unregisterRemoteAnimations"); } - if (!mRegisterTasks.contains(taskId)) { + if (!mIsRegistered) { return; } - mOrganizer.unregisterRemoteAnimations(taskId); - mRegisterTasks.remove(taskId); - } - - void unregisterAllRemoteAnimations() { - final ArraySet<Integer> tasks = new ArraySet<>(mRegisterTasks); - for (int taskId : tasks) { - unregisterRemoteAnimations(taskId); - } + 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 index 8c416e881059..0e13c59e593c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -20,11 +20,9 @@ import static android.os.Process.THREAD_PRIORITY_DISPLAY; import static android.view.RemoteAnimationTarget.MODE_CLOSING; 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_CLOSE; 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.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; @@ -169,11 +167,9 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { switch (transit) { case TRANSIT_OLD_ACTIVITY_OPEN: case TRANSIT_OLD_TASK_FRAGMENT_OPEN: - case TRANSIT_OLD_TASK_OPEN: return createOpenAnimationAdapters(targets); case TRANSIT_OLD_ACTIVITY_CLOSE: case TRANSIT_OLD_TASK_FRAGMENT_CLOSE: - case TRANSIT_OLD_TASK_CLOSE: return createCloseAnimationAdapters(targets); case TRANSIT_OLD_TASK_FRAGMENT_CHANGE: return createChangeAnimationAdapters(targets); 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 79813c7d064e..31aa09c902b1 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 @@ -18,7 +18,6 @@ package androidx.window.extensions.embedding; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID; import static androidx.window.extensions.embedding.EmbeddingTestUtils.createTestTaskContainer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -26,10 +25,8 @@ 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; -import static org.mockito.Mockito.never; import android.content.Intent; import android.content.res.Configuration; @@ -85,35 +82,20 @@ public class JetpackTaskFragmentOrganizerTest { @Test public void testUnregisterOrganizer() { - mOrganizer.startOverrideSplitAnimation(TASK_ID); - mOrganizer.startOverrideSplitAnimation(TASK_ID + 1); + mOrganizer.overrideSplitAnimation(); mOrganizer.unregisterOrganizer(); - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID + 1); + verify(mOrganizer).unregisterRemoteAnimations(); } @Test - public void testStartOverrideSplitAnimation() { + public void testOverrideSplitAnimation() { assertNull(mOrganizer.mAnimationController); - mOrganizer.startOverrideSplitAnimation(TASK_ID); + mOrganizer.overrideSplitAnimation(); assertNotNull(mOrganizer.mAnimationController); - verify(mOrganizer).registerRemoteAnimations(TASK_ID, - mOrganizer.mAnimationController.mDefinition); - } - - @Test - public void testStopOverrideSplitAnimation() { - mOrganizer.stopOverrideSplitAnimation(TASK_ID); - - verify(mOrganizer, never()).unregisterRemoteAnimations(anyInt()); - - mOrganizer.startOverrideSplitAnimation(TASK_ID); - mOrganizer.stopOverrideSplitAnimation(TASK_ID); - - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); + verify(mOrganizer).registerRemoteAnimations(mOrganizer.mAnimationController.mDefinition); } @Test 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 index d31342bfb309..379ea0c534ba 100644 --- 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 @@ -16,11 +16,8 @@ package androidx.window.extensions.embedding; -import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID; - import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; import android.platform.test.annotations.Presubmit; @@ -57,41 +54,31 @@ public class TaskFragmentAnimationControllerTest { @Test public void testRegisterRemoteAnimations() { - mAnimationController.registerRemoteAnimations(TASK_ID); + mAnimationController.registerRemoteAnimations(); - verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition); + verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition); - mAnimationController.registerRemoteAnimations(TASK_ID); + mAnimationController.registerRemoteAnimations(); // No extra call if it has been registered. - verify(mOrganizer).registerRemoteAnimations(TASK_ID, mAnimationController.mDefinition); + verify(mOrganizer).registerRemoteAnimations(mAnimationController.mDefinition); } @Test public void testUnregisterRemoteAnimations() { - mAnimationController.unregisterRemoteAnimations(TASK_ID); + mAnimationController.unregisterRemoteAnimations(); // No call if it is not registered. - verify(mOrganizer, never()).unregisterRemoteAnimations(anyInt()); + verify(mOrganizer, never()).unregisterRemoteAnimations(); - mAnimationController.registerRemoteAnimations(TASK_ID); - mAnimationController.unregisterRemoteAnimations(TASK_ID); + mAnimationController.registerRemoteAnimations(); + mAnimationController.unregisterRemoteAnimations(); - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); + verify(mOrganizer).unregisterRemoteAnimations(); - mAnimationController.unregisterRemoteAnimations(TASK_ID); + mAnimationController.unregisterRemoteAnimations(); // No extra call if it has been unregistered. - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); - } - - @Test - public void testUnregisterAllRemoteAnimations() { - mAnimationController.registerRemoteAnimations(TASK_ID); - mAnimationController.registerRemoteAnimations(TASK_ID + 1); - mAnimationController.unregisterAllRemoteAnimations(); - - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID); - verify(mOrganizer).unregisterRemoteAnimations(TASK_ID + 1); + 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 bd22b32742a1..5380de760a82 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -570,6 +570,34 @@ public class AppTransitionController { } /** + * Whether the transition contains any embedded {@link TaskFragment} that does not fill the + * parent {@link Task} before or after the transition. + */ + private boolean transitionContainsTaskFragmentWithBoundsOverride() { + for (int i = mDisplayContent.mChangingContainers.size() - 1; i >= 0; i--) { + final WindowContainer wc = mDisplayContent.mChangingContainers.valueAt(i); + if (wc.isEmbedded()) { + // Contains embedded TaskFragment with bounds changed. + return true; + } + } + mTempTransitionWindows.clear(); + mTempTransitionWindows.addAll(mDisplayContent.mClosingApps); + mTempTransitionWindows.addAll(mDisplayContent.mOpeningApps); + boolean containsTaskFragmentWithBoundsOverride = false; + for (int i = mTempTransitionWindows.size() - 1; i >= 0; i--) { + final ActivityRecord r = mTempTransitionWindows.get(i).asActivityRecord(); + final TaskFragment tf = r.getTaskFragment(); + if (tf != null && tf.isEmbeddedWithBoundsOverride()) { + containsTaskFragmentWithBoundsOverride = true; + break; + } + } + mTempTransitionWindows.clear(); + return containsTaskFragmentWithBoundsOverride; + } + + /** * Finds the common parent {@link Task} that is parent of all embedded app windows in the * current transition. * @return {@code null} if app windows in the transition are not children of the same Task, or @@ -672,12 +700,17 @@ public class AppTransitionController { 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, task.mTaskId) + .getRemoteAnimationDefinition(organizer) : null; final RemoteAnimationAdapter adapter = definition != null ? definition.getAdapter(transit, activityTypes) diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 911a8da1db99..f0e3644a3ff5 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -583,15 +583,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { @Override boolean isEmbedded() { - if (mIsEmbedded) { - return true; - } - final WindowContainer<?> parent = getParent(); - if (parent != null) { - final TaskFragment taskFragment = parent.asTaskFragment(); - return taskFragment != null && taskFragment.isEmbedded(); - } - return false; + return mIsEmbedded; } @EmbeddingCheckResult @@ -2510,6 +2502,22 @@ class TaskFragment extends WindowContainer<WindowContainer> { return mTaskFragmentOrganizer != null; } + /** + * Whether this is an embedded {@link TaskFragment} that does not fill the parent {@link Task}. + */ + boolean isEmbeddedWithBoundsOverride() { + if (!mIsEmbedded) { + return false; + } + final Task task = getTask(); + if (task == null) { + return false; + } + final Rect taskBounds = task.getBounds(); + final Rect taskFragBounds = getBounds(); + return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds); + } + /** Whether the Task should be visible. */ boolean isTaskVisibleRequested() { final Task task = getTask(); diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 2e716ae23f20..484de2b3bc34 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -36,7 +36,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Intent; import android.content.res.Configuration; -import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -133,12 +132,11 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr new WeakHashMap<>(); /** - * Map from Task Id to {@link RemoteAnimationDefinition}. - * @see android.window.TaskFragmentOrganizer#registerRemoteAnimations(int, - * RemoteAnimationDefinition) ) + * {@link RemoteAnimationDefinition} for embedded activities transition animation that is + * organized by this organizer. */ - private final SparseArray<RemoteAnimationDefinition> mRemoteAnimationDefinitions = - new SparseArray<>(); + @Nullable + private RemoteAnimationDefinition mRemoteAnimationDefinition; /** * Map from {@link TaskFragmentTransaction#getTransactionToken()} to the @@ -455,7 +453,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr } @Override - public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer, int taskId, + public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer, @NonNull RemoteAnimationDefinition definition) { final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); @@ -468,20 +466,19 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr if (organizerState == null) { throw new IllegalStateException("The organizer hasn't been registered."); } - if (organizerState.mRemoteAnimationDefinitions.contains(taskId)) { + if (organizerState.mRemoteAnimationDefinition != null) { throw new IllegalStateException( "The organizer has already registered remote animations=" - + organizerState.mRemoteAnimationDefinitions.get(taskId) - + " for TaskId=" + taskId); + + organizerState.mRemoteAnimationDefinition); } definition.setCallingPidUid(pid, uid); - organizerState.mRemoteAnimationDefinitions.put(taskId, definition); + organizerState.mRemoteAnimationDefinition = definition; } } @Override - public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer, int taskId) { + public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer) { final int pid = Binder.getCallingPid(); final long uid = Binder.getCallingUid(); synchronized (mGlobalLock) { @@ -495,7 +492,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr return; } - organizerState.mRemoteAnimationDefinitions.remove(taskId); + organizerState.mRemoteAnimationDefinition = null; } } @@ -527,16 +524,16 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr /** * Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. Returns - * {@code null} if it doesn't, or if the organizer has activity(ies) embedded in untrusted mode. + * {@code null} if it doesn't. */ @Nullable public RemoteAnimationDefinition getRemoteAnimationDefinition( - @NonNull ITaskFragmentOrganizer organizer, int taskId) { + @NonNull ITaskFragmentOrganizer organizer) { synchronized (mGlobalLock) { final TaskFragmentOrganizerState organizerState = mTaskFragmentOrganizerState.get(organizer.asBinder()); return organizerState != null - ? organizerState.mRemoteAnimationDefinitions.get(taskId) + ? organizerState.mRemoteAnimationDefinition : null; } } @@ -1085,16 +1082,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr return false; } final TaskFragment taskFragment = activity.getOrganizedTaskFragment(); - if (taskFragment == null) { - return false; - } - final Task parentTask = taskFragment.getTask(); - if (parentTask != null) { - final Rect taskBounds = parentTask.getBounds(); - final Rect taskFragBounds = taskFragment.getBounds(); - return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds); - } - return false; + return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride(); } } 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 0332c4b4597b..43e79f9cbb15 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -25,6 +25,7 @@ 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; @@ -56,6 +57,7 @@ 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; @@ -918,7 +920,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Create a TaskFragment with embedded activity. final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer); @@ -935,11 +937,77 @@ public class AppTransitionControllerTest extends WindowTestsBase { } @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, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Closing non-embedded activity. final ActivityRecord closingActivity = createActivityRecord(task); @@ -964,7 +1032,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Closing TaskFragment with embedded activity. final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, organizer); @@ -991,7 +1059,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Closing activity in Task1. final ActivityRecord closingActivity = createActivityRecord(mDisplayContent); @@ -1015,7 +1083,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Closing TaskFragment with embedded activity. final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer); @@ -1043,7 +1111,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Create a TaskFragment with embedded activity. final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer); @@ -1069,7 +1137,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Create a TaskFragment with embedded activities, one is trusted embedded, and the other // one is untrusted embedded. @@ -1128,7 +1196,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Create a TaskFragment with only trusted embedded activity final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) @@ -1168,7 +1236,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { final Task task = createTask(mDisplayContent); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); final TestRemoteAnimationRunner remoteAnimationRunner = new TestRemoteAnimationRunner(); - setupTaskFragmentRemoteAnimation(organizer, task.mTaskId, remoteAnimationRunner); + setupTaskFragmentRemoteAnimation(organizer, remoteAnimationRunner); // Create a TaskFragment with only trusted embedded activity final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) @@ -1259,7 +1327,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { } /** Registers remote animation for the organizer. */ - private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer, int taskId, + private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer, TestRemoteAnimationRunner remoteAnimationRunner) { final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter( remoteAnimationRunner, 10, 1); @@ -1268,9 +1336,10 @@ public class AppTransitionControllerTest extends WindowTestsBase { 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); mAtm.mTaskFragmentOrganizerController.registerOrganizer(iOrganizer); - mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, taskId, - definition); + mAtm.mTaskFragmentOrganizerController.registerRemoteAnimations(iOrganizer, definition); } private static ITaskFragmentOrganizer getITaskFragmentOrganizer( 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 c53518210af9..426afffdb880 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -474,13 +474,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Test public void testRegisterRemoteAnimations() { - mController.registerRemoteAnimations(mIOrganizer, TASK_ID, mDefinition); + mController.registerRemoteAnimations(mIOrganizer, mDefinition); - assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID)); + assertEquals(mDefinition, mController.getRemoteAnimationDefinition(mIOrganizer)); - mController.unregisterRemoteAnimations(mIOrganizer, TASK_ID); + mController.unregisterRemoteAnimations(mIOrganizer); - assertNull(mController.getRemoteAnimationDefinition(mIOrganizer, TASK_ID)); + assertNull(mController.getRemoteAnimationDefinition(mIOrganizer)); } @Test |