summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java106
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java17
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java2
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java1352
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java27
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java64
-rw-r--r--services/core/java/com/android/server/wm/SnapshotController.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java54
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java1306
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java520
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java78
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java13
18 files changed, 29 insertions, 3586 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d84016b3816e..e3070ef31dcc 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -113,7 +113,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED;
import static android.view.WindowManager.PROPERTY_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING_STATE_SHARING;
import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_UNSET;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
import static android.view.WindowManager.hasWindowExtensionsEnabled;
@@ -856,12 +855,6 @@ final class ActivityRecord extends WindowToken {
})
@interface SplashScreenBehavior { }
- // Force an app transition to be ran in the case the visibility of the app did not change.
- // We use this for the case of moving a Root Task to the back with multiple activities, and the
- // top activity enters PIP; the bottom activity's visibility stays the same, but we need to
- // run the transition.
- boolean mRequestForceTransition;
-
boolean mEnteringAnimation;
boolean mOverrideTaskTransition;
boolean mDismissKeyguardIfInsecure;
@@ -1788,7 +1781,6 @@ final class ActivityRecord extends WindowToken {
if (prevDc.mOpeningApps.remove(this)) {
// Transfer opening transition to new display.
mDisplayContent.mOpeningApps.add(this);
- mDisplayContent.transferAppTransitionFrom(prevDc);
mDisplayContent.executeAppTransition();
}
@@ -4631,12 +4623,6 @@ final class ActivityRecord extends WindowToken {
}
}
- // In this case, the starting icon has already been displayed, so start
- // letting windows get shown immediately without any more transitions.
- if (fromActivity.mVisible) {
- mDisplayContent.mSkipAppTransitionAnimation = true;
- }
-
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
+ " from %s to %s", tStartingWindow, fromActivity, this);
@@ -5667,76 +5653,17 @@ final class ActivityRecord extends WindowToken {
mTransitionController.mValidateCommitVis.add(this);
return;
}
- // If we are preparing an app transition, then delay changing
- // the visibility of this token until we execute that transition.
- if (deferCommitVisibilityChange(visible)) {
- return;
- }
commitVisibility(visible, true /* performLayout */);
updateReportedVisibilityLocked();
}
- /**
- * Returns {@code true} if this activity is either added to opening-apps or closing-apps.
- * Then its visibility will be committed until the transition is ready.
- */
- private boolean deferCommitVisibilityChange(boolean visible) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- // Shell transition doesn't use opening/closing sets.
- return false;
- }
- if (!mDisplayContent.mAppTransition.isTransitionSet()) {
- return false;
- }
- if (mWaitForEnteringPinnedMode && mVisible == visible) {
- // If the visibility is not changed during enter PIP, we don't want to include it in
- // app transition to affect the animation theme, because the Pip organizer will
- // animate the entering PIP instead.
- return false;
- }
-
- // The animation will be visible soon so do not skip by screen off.
- final boolean ignoreScreenOn = canTurnScreenOn() || mTaskSupervisor.getKeyguardController()
- .isKeyguardGoingAway(mDisplayContent.mDisplayId);
- // Ignore display frozen so the opening / closing transition type can be updated correctly
- // even if the display is frozen. And it's safe since in applyAnimation will still check
- // DC#okToAnimate again if the transition animation is fine to apply.
- if (!okToAnimate(true /* ignoreFrozen */, ignoreScreenOn)) {
- return false;
- }
- if (visible) {
- mDisplayContent.mOpeningApps.add(this);
- mEnteringAnimation = true;
- } else if (mVisible) {
- mDisplayContent.mClosingApps.add(this);
- mEnteringAnimation = false;
- }
- if ((mDisplayContent.mAppTransition.getTransitFlags() & TRANSIT_FLAG_OPEN_BEHIND) != 0) {
- // Add the launching-behind activity to mOpeningApps.
- final WindowState win = mDisplayContent.findFocusedWindow();
- if (win != null) {
- final ActivityRecord focusedActivity = win.mActivityRecord;
- if (focusedActivity != null) {
- ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
- "TRANSIT_FLAG_OPEN_BEHIND, adding %s to mOpeningApps",
- focusedActivity);
- // Force animation to be loaded.
- mDisplayContent.mOpeningApps.add(focusedActivity);
- }
- }
- }
- return true;
- }
-
@Override
boolean applyAnimation(LayoutParams lp, @TransitionOldType int transit, boolean enter,
boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
if ((mTransitionChangeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
return false;
}
- // If it was set to true, reset the last request to force the transition.
- mRequestForceTransition = false;
return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
}
@@ -5899,27 +5826,6 @@ final class ActivityRecord extends WindowToken {
}
/**
- * Check if visibility of this {@link ActivityRecord} should be updated as part of an app
- * transition.
- *
- * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is
- * already set to {@link #mVisible}, we don't need to update the visibility. So {@code false} is
- * returned.</p>
- *
- * @param visible {@code true} if this {@link ActivityRecord} should become visible,
- * {@code false} if this should become invisible.
- * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and
- * an app transition animation should be run.
- */
- boolean shouldApplyAnimation(boolean visible) {
- // Allow for state update and animation to be applied if:
- // * activity is transitioning visibility state
- // * or the activity was marked as hidden and is exiting before we had a chance to play the
- // transition animation
- return isVisible() != visible || mRequestForceTransition || (!isVisible() && mIsExiting);
- }
-
- /**
* See {@link Activity#setRecentsScreenshotEnabled}.
*/
void setRecentsScreenshotEnabled(boolean enabled) {
@@ -7670,17 +7576,7 @@ final class ActivityRecord extends WindowToken {
// new layer.
if (mNeedsAnimationBoundsLayer) {
mTmpRect.setEmpty();
- if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
- getTransit(), task)) {
- task.getBounds(mTmpRect);
- } else {
- final Task rootTask = getRootTask();
- if (rootTask == null) {
- return;
- }
- // Set clip rect to root task bounds.
- rootTask.getBounds(mTmpRect);
- }
+ task.getBounds(mTmpRect);
mAnimationBoundsLayer = createAnimationBoundsLayer(t);
// Crop to root task bounds.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 254127dee7a8..819e117e6d05 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4128,22 +4128,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void registerRemoteAnimationsForDisplay(int displayId,
RemoteAnimationDefinition definition) {
- mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
- "registerRemoteAnimations");
- definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
- synchronized (mGlobalLock) {
- final DisplayContent display = mRootWindowContainer.getDisplayContent(displayId);
- if (display == null) {
- Slog.e(TAG, "Couldn't find display with id: " + displayId);
- return;
- }
- final long origId = Binder.clearCallingIdentity();
- try {
- display.registerRemoteAnimations(definition);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
+ // TODO(b/365884835): Remove callers.
}
/** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 932f26857105..9c4b722feb47 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1462,7 +1462,7 @@ public class AppTransition implements Dump {
}
boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) {
- if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
+ if (WindowManagerService.sEnableShellTransitions) {
return false;
}
mNextAppTransitionRequests.add(transit);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
deleted file mode 100644
index d5fe056a2ba4..000000000000
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.wm;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
-import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_NONE;
-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_ACTIVITY_RELAUNCH;
-import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
-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_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
-import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM;
-import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_OLD_NONE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
-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.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
-import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_RELAUNCH;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
-
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
-import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
-import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
-import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
-import static com.android.server.wm.AppTransition.isNormalTransit;
-import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldAttachNavBarToApp;
-import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldStartNonAppWindowAnimationsForKeyguardExit;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
-import static com.android.server.wm.WallpaperAnimationAdapter.shouldStartWallpaperAnimation;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.annotation.IntDef;
-import android.annotation.Nullable;
-import android.graphics.Rect;
-import android.os.Trace;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Pair;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationDefinition;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.WindowManager.TransitionFlags;
-import android.view.WindowManager.TransitionOldType;
-import android.view.WindowManager.TransitionType;
-import android.window.ITaskFragmentOrganizer;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.protolog.ProtoLog;
-
-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;
-
-/**
- * Checks for app transition readiness, resolves animation attributes and performs visibility
- * change for apps that animate as part of an app transition.
- */
-public class AppTransitionController {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "AppTransitionController" : TAG_WM;
- private final WindowManagerService mService;
- private final DisplayContent mDisplayContent;
- private final WallpaperController mWallpaperControllerLocked;
- private RemoteAnimationDefinition mRemoteAnimationDefinition = null;
-
- private static final int TYPE_NONE = 0;
- private static final int TYPE_ACTIVITY = 1;
- private static final int TYPE_TASK_FRAGMENT = 2;
- private static final int TYPE_TASK = 3;
-
- @IntDef(prefix = { "TYPE_" }, value = {
- TYPE_NONE,
- TYPE_ACTIVITY,
- TYPE_TASK_FRAGMENT,
- TYPE_TASK
- })
- @Retention(RetentionPolicy.SOURCE)
- @interface TransitContainerType {}
-
- private final ArrayMap<WindowContainer, Integer> mTempTransitionReasons = new ArrayMap<>();
- private final ArrayList<WindowContainer> mTempTransitionWindows = new ArrayList<>();
-
- AppTransitionController(WindowManagerService service, DisplayContent displayContent) {
- mService = service;
- mDisplayContent = displayContent;
- mWallpaperControllerLocked = mDisplayContent.mWallpaperController;
- }
-
- void registerRemoteAnimations(RemoteAnimationDefinition definition) {
- mRemoteAnimationDefinition = definition;
- }
-
- /**
- * Returns the currently visible window that is associated with the wallpaper in case we are
- * transitioning from an activity with a wallpaper to one without.
- */
- @Nullable
- private WindowState getOldWallpaper() {
- final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
- final @TransitionType int firstTransit =
- mDisplayContent.mAppTransition.getFirstAppTransition();
-
- final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, true /* visible */);
- final boolean showWallpaper = wallpaperTarget != null
- && (wallpaperTarget.hasWallpaper()
- // Update task open transition to wallpaper transition when wallpaper is visible.
- // (i.e.launching app info activity from recent tasks)
- || ((firstTransit == TRANSIT_OPEN || firstTransit == TRANSIT_TO_FRONT)
- && (!openingWcs.isEmpty() && openingWcs.valueAt(0).asTask() != null)
- && mWallpaperControllerLocked.isWallpaperVisible()));
- // If wallpaper is animating or wallpaperTarget doesn't have SHOW_WALLPAPER flag set,
- // don't consider upgrading to wallpaper transition.
- return (mWallpaperControllerLocked.isWallpaperTargetAnimating() || !showWallpaper)
- ? null : wallpaperTarget;
- }
-
- /**
- * Handle application transition for given display.
- */
- void handleAppTransitionReady() {
- mTempTransitionReasons.clear();
- if (!transitionGoodToGo(mDisplayContent.mOpeningApps, mTempTransitionReasons)
- || !transitionGoodToGo(mDisplayContent.mChangingContainers, mTempTransitionReasons)
- || !transitionGoodToGoForTaskFragments()) {
- return;
- }
-
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
-
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
- // TODO(b/205335975): Remove window which stuck in animatingExit status. Find actual cause.
- mDisplayContent.forAllWindows(WindowState::cleanupAnimatingExitWindow,
- true /* traverseTopToBottom */);
- // TODO(new-app-transition): Remove code using appTransition.getAppTransition()
- final AppTransition appTransition = mDisplayContent.mAppTransition;
-
- mDisplayContent.mNoAnimationNotifyOnTransitionFinished.clear();
-
- appTransition.removeAppTransitionTimeoutCallbacks();
-
- mDisplayContent.mWallpaperMayChange = false;
-
- int appCount = mDisplayContent.mOpeningApps.size();
- for (int i = 0; i < appCount; ++i) {
- // Clearing the mAnimatingExit flag before entering animation. It's set to true if app
- // window is removed, or window relayout to invisible. This also affects window
- // visibility. We need to clear it *before* maybeUpdateTransitToWallpaper() as the
- // transition selection depends on wallpaper target visibility.
- mDisplayContent.mOpeningApps.valueAtUnchecked(i).clearAnimatingFlags();
- }
- appCount = mDisplayContent.mChangingContainers.size();
- for (int i = 0; i < appCount; ++i) {
- // Clearing for same reason as above.
- final ActivityRecord activity = getAppFromContainer(
- mDisplayContent.mChangingContainers.valueAtUnchecked(i));
- if (activity != null) {
- activity.clearAnimatingFlags();
- }
- }
-
- // Adjust wallpaper before we pull the lower/upper target, since pending changes
- // (like the clearAnimatingFlags() above) might affect wallpaper target result.
- // Or, the opening app window should be a wallpaper target.
- mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(
- mDisplayContent.mOpeningApps);
-
- ArraySet<ActivityRecord> tmpOpenApps = mDisplayContent.mOpeningApps;
- ArraySet<ActivityRecord> tmpCloseApps = mDisplayContent.mClosingApps;
- if (mDisplayContent.mAtmService.mBackNavigationController.isMonitoringFinishTransition()) {
- tmpOpenApps = new ArraySet<>(mDisplayContent.mOpeningApps);
- tmpCloseApps = new ArraySet<>(mDisplayContent.mClosingApps);
- }
-
- @TransitionOldType final int transit = getTransitCompatType(
- mDisplayContent.mAppTransition, tmpOpenApps,
- tmpCloseApps, mDisplayContent.mChangingContainers,
- mWallpaperControllerLocked.getWallpaperTarget(), getOldWallpaper(),
- mDisplayContent.mSkipAppTransitionAnimation);
- mDisplayContent.mSkipAppTransitionAnimation = false;
-
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "handleAppTransitionReady: displayId=%d appTransition={%s}"
- + " openingApps=[%s] closingApps=[%s] transit=%s",
- mDisplayContent.mDisplayId, appTransition.toString(), tmpOpenApps,
- tmpCloseApps, AppTransition.appTransitionOldToString(transit));
-
- // Find the layout params of the top-most application window in the tokens, which is
- // what will control the animation theme. If all closing windows are obscured, then there is
- // no need to do an animation. This is the case, for example, when this transition is being
- // done behind a dream window.
- final ArraySet<Integer> activityTypes = collectActivityTypes(tmpOpenApps,
- tmpCloseApps, mDisplayContent.mChangingContainers);
- final ActivityRecord animLpActivity = findAnimLayoutParamsToken(transit, activityTypes,
- tmpOpenApps, tmpCloseApps, mDisplayContent.mChangingContainers);
- final ActivityRecord topOpeningApp =
- getTopApp(tmpOpenApps, false /* ignoreHidden */);
- final ActivityRecord topClosingApp =
- getTopApp(tmpCloseApps, false /* ignoreHidden */);
- final ActivityRecord topChangingApp =
- 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.
- overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
- }
-
- final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mClosingApps)
- || containsVoiceInteraction(mDisplayContent.mOpeningApps);
-
- final int layoutRedo;
- mService.mSurfaceAnimationRunner.deferStartingAnimations();
- try {
- applyAnimations(tmpOpenApps, tmpCloseApps, transit, animLp, voiceInteraction);
- handleClosingApps();
- handleOpeningApps();
- handleChangingApps(transit);
- handleClosingChangingContainers();
-
- appTransition.setLastAppTransition(transit, topOpeningApp,
- topClosingApp, topChangingApp);
-
- final int flags = appTransition.getTransitFlags();
- layoutRedo = appTransition.goodToGo(transit, topOpeningApp);
- appTransition.postAnimationCallback();
- } finally {
- appTransition.clear();
- mService.mSurfaceAnimationRunner.continueStartingAnimations();
- }
-
- mService.mSnapshotController.onTransitionStarting(mDisplayContent);
-
- mDisplayContent.mOpeningApps.clear();
- mDisplayContent.mClosingApps.clear();
- mDisplayContent.mChangingContainers.clear();
- mDisplayContent.mUnknownAppVisibilityController.clear();
- mDisplayContent.mClosingChangingContainers.clear();
-
- // This has changed the visibility of windows, so perform
- // a new layout to get them all up-to-date.
- mDisplayContent.setLayoutNeeded();
-
- mDisplayContent.computeImeTarget(true /* updateImeTarget */);
-
- mService.mAtmService.mTaskSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
- mTempTransitionReasons);
-
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
-
- mDisplayContent.pendingLayoutChanges |=
- layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
- }
-
- /**
- * Get old transit type based on the current transit requests.
- *
- * @param appTransition {@link AppTransition} for managing app transition state.
- * @param openingApps {@link ActivityRecord}s which are becoming visible.
- * @param closingApps {@link ActivityRecord}s which are becoming invisible.
- * @param changingContainers {@link WindowContainer}s which are changed in configuration.
- * @param wallpaperTarget If non-null, this is the currently visible window that is associated
- * with the wallpaper.
- * @param oldWallpaper The currently visible window that is associated with the wallpaper in
- * case we are transitioning from an activity with a wallpaper to one
- * without. Otherwise null.
- */
- @TransitionOldType static int getTransitCompatType(AppTransition appTransition,
- ArraySet<ActivityRecord> openingApps, ArraySet<ActivityRecord> closingApps,
- ArraySet<WindowContainer> changingContainers, @Nullable WindowState wallpaperTarget,
- @Nullable WindowState oldWallpaper, boolean skipAppTransitionAnimation) {
-
- final ActivityRecord topOpeningApp = getTopApp(openingApps, false /* ignoreHidden */);
- final ActivityRecord topClosingApp = getTopApp(closingApps, true /* ignoreHidden */);
-
- // Determine if closing and opening app token sets are wallpaper targets, in which case
- // special animations are needed.
- final boolean openingAppHasWallpaper = canBeWallpaperTarget(openingApps)
- && wallpaperTarget != null;
- final boolean closingAppHasWallpaper = canBeWallpaperTarget(closingApps)
- && wallpaperTarget != null;
-
- // Keyguard transit has high priority.
- switch (appTransition.getKeyguardTransition()) {
- case TRANSIT_KEYGUARD_GOING_AWAY:
- return openingAppHasWallpaper ? TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER
- : TRANSIT_OLD_KEYGUARD_GOING_AWAY;
- case TRANSIT_KEYGUARD_OCCLUDE:
- // When there is a closing app, the keyguard has already been occluded by an
- // activity, and another activity has started on top of that activity, so normal
- // app transition animation should be used.
- if (!closingApps.isEmpty()) {
- return TRANSIT_OLD_ACTIVITY_OPEN;
- }
- if (!openingApps.isEmpty() && openingApps.valueAt(0).getActivityType()
- == ACTIVITY_TYPE_DREAM) {
- return TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM;
- }
- return TRANSIT_OLD_KEYGUARD_OCCLUDE;
- case TRANSIT_KEYGUARD_UNOCCLUDE:
- return TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
- }
-
- // Determine whether the top opening and closing activity is a dream activity. If so, this
- // has higher priority than others except keyguard transit.
- if (topOpeningApp != null && topOpeningApp.getActivityType() == ACTIVITY_TYPE_DREAM) {
- return TRANSIT_OLD_DREAM_ACTIVITY_OPEN;
- } else if (topClosingApp != null
- && topClosingApp.getActivityType() == ACTIVITY_TYPE_DREAM) {
- return TRANSIT_OLD_DREAM_ACTIVITY_CLOSE;
- }
-
- // This is not keyguard transition and one of the app has request to skip app transition.
- if (skipAppTransitionAnimation) {
- return WindowManager.TRANSIT_OLD_UNSET;
- }
- @TransitionFlags final int flags = appTransition.getTransitFlags();
- @TransitionType final int firstTransit = appTransition.getFirstAppTransition();
-
- // Special transitions
- // TODO(new-app-transitions): Revisit if those can be rewritten by using flags.
- if (appTransition.containsTransitRequest(TRANSIT_CHANGE) && !changingContainers.isEmpty()) {
- @TransitContainerType int changingType =
- getTransitContainerType(changingContainers.valueAt(0));
- switch (changingType) {
- case TYPE_TASK:
- return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
- case TYPE_TASK_FRAGMENT:
- return TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
- default:
- throw new IllegalStateException(
- "TRANSIT_CHANGE with unrecognized changing type=" + changingType);
- }
- }
- if ((flags & TRANSIT_FLAG_APP_CRASHED) != 0) {
- return TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
- }
- if (firstTransit == TRANSIT_NONE) {
- return TRANSIT_OLD_NONE;
- }
-
- /*
- * There are cases where we open/close a new task/activity, but in reality only a
- * translucent activity on top of existing activities is opening/closing. For that one, we
- * have a different animation because non of the task/activity animations actually work well
- * with translucent apps.
- */
- if (isNormalTransit(firstTransit)) {
- boolean allOpeningVisible = true;
- boolean allTranslucentOpeningApps = !openingApps.isEmpty();
- for (int i = openingApps.size() - 1; i >= 0; i--) {
- final ActivityRecord activity = openingApps.valueAt(i);
- if (!activity.isVisible()) {
- allOpeningVisible = false;
- if (activity.fillsParent()) {
- allTranslucentOpeningApps = false;
- }
- }
- }
- boolean allTranslucentClosingApps = !closingApps.isEmpty();
- for (int i = closingApps.size() - 1; i >= 0; i--) {
- if (closingApps.valueAt(i).fillsParent()) {
- allTranslucentClosingApps = false;
- break;
- }
- }
-
- if (allTranslucentClosingApps && allOpeningVisible) {
- return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
- }
- if (allTranslucentOpeningApps && closingApps.isEmpty()) {
- return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
- }
- }
-
- if (closingAppHasWallpaper && openingAppHasWallpaper) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
- switch (firstTransit) {
- case TRANSIT_OPEN:
- case TRANSIT_TO_FRONT:
- return TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
- case TRANSIT_CLOSE:
- case TRANSIT_TO_BACK:
- return TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
- }
- } else if (oldWallpaper != null && !openingApps.isEmpty()
- && !openingApps.contains(oldWallpaper.mActivityRecord)
- && closingApps.contains(oldWallpaper.mActivityRecord)
- && topClosingApp == oldWallpaper.mActivityRecord) {
- // We are transitioning from an activity with a wallpaper to one without.
- return TRANSIT_OLD_WALLPAPER_CLOSE;
- } else if (wallpaperTarget != null && wallpaperTarget.isVisible()
- && openingApps.contains(wallpaperTarget.mActivityRecord)
- && topOpeningApp == wallpaperTarget.mActivityRecord
- /* && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE */) {
- // We are transitioning from an activity without
- // a wallpaper to now showing the wallpaper
- return TRANSIT_OLD_WALLPAPER_OPEN;
- }
-
- final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
- openingApps, closingApps, true /* visible */);
- final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
- openingApps, closingApps, false /* visible */);
- final WindowContainer<?> openingContainer = !openingWcs.isEmpty()
- ? openingWcs.valueAt(0) : null;
- final WindowContainer<?> closingContainer = !closingWcs.isEmpty()
- ? closingWcs.valueAt(0) : null;
- @TransitContainerType int openingType = getTransitContainerType(openingContainer);
- @TransitContainerType int closingType = getTransitContainerType(closingContainer);
- if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && openingType == TYPE_TASK) {
- if (topOpeningApp != null && topOpeningApp.isActivityTypeHome()) {
- // If we are opening the home task, we want to play an animation as if
- // the task on top is being brought to back.
- return TRANSIT_OLD_TASK_TO_BACK;
- }
- return TRANSIT_OLD_TASK_TO_FRONT;
- }
- if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && closingType == TYPE_TASK) {
- return TRANSIT_OLD_TASK_TO_BACK;
- }
- if (appTransition.containsTransitRequest(TRANSIT_OPEN)) {
- if (openingType == TYPE_TASK) {
- return (appTransition.getTransitFlags() & TRANSIT_FLAG_OPEN_BEHIND) != 0
- ? TRANSIT_OLD_TASK_OPEN_BEHIND : TRANSIT_OLD_TASK_OPEN;
- }
- if (openingType == TYPE_ACTIVITY) {
- return TRANSIT_OLD_ACTIVITY_OPEN;
- }
- if (openingType == TYPE_TASK_FRAGMENT) {
- return TRANSIT_OLD_TASK_FRAGMENT_OPEN;
- }
- }
- if (appTransition.containsTransitRequest(TRANSIT_CLOSE)) {
- if (closingType == TYPE_TASK) {
- return TRANSIT_OLD_TASK_CLOSE;
- }
- if (closingType == TYPE_TASK_FRAGMENT) {
- return TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
- }
- if (closingType == TYPE_ACTIVITY) {
- for (int i = closingApps.size() - 1; i >= 0; i--) {
- if (closingApps.valueAt(i).visibleIgnoringKeyguard) {
- return TRANSIT_OLD_ACTIVITY_CLOSE;
- }
- }
- // Skip close activity transition since no closing app can be visible
- return WindowManager.TRANSIT_OLD_UNSET;
- }
- }
- if (appTransition.containsTransitRequest(TRANSIT_RELAUNCH)
- && !openingWcs.isEmpty() && !openingApps.isEmpty()) {
- return TRANSIT_OLD_ACTIVITY_RELAUNCH;
- }
- return TRANSIT_OLD_NONE;
- }
-
- @TransitContainerType
- private static int getTransitContainerType(@Nullable WindowContainer<?> container) {
- if (container == null) {
- return TYPE_NONE;
- }
- if (container.asTask() != null) {
- return TYPE_TASK;
- }
- if (container.asTaskFragment() != null) {
- return TYPE_TASK_FRAGMENT;
- }
- if (container.asActivityRecord() != null) {
- return TYPE_ACTIVITY;
- }
- return TYPE_NONE;
- }
-
- @Nullable
- private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
- final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
- return mainWindow != null ? mainWindow.mAttrs : null;
- }
-
- RemoteAnimationAdapter getRemoteAnimationOverride(@Nullable WindowContainer container,
- @TransitionOldType int transit, ArraySet<Integer> activityTypes) {
- if (container != null) {
- final RemoteAnimationDefinition definition = container.getRemoteAnimationDefinition();
- if (definition != null) {
- final RemoteAnimationAdapter adapter = definition.getAdapter(transit,
- activityTypes);
- if (adapter != null) {
- return adapter;
- }
- }
- }
- return mRemoteAnimationDefinition != null
- ? mRemoteAnimationDefinition.getAdapter(transit, activityTypes)
- : null;
- }
-
- private boolean transitionMayContainNonAppWindows(@TransitionOldType int transit) {
- // We don't want to have the client to animate any non-app windows.
- // Having {@code transit} of those types doesn't mean it will contain non-app windows, but
- // non-app windows will only be included with those transition types. And we don't currently
- // have any use case of those for TaskFragment transition.
- return shouldStartNonAppWindowAnimationsForKeyguardExit(transit)
- || shouldAttachNavBarToApp(mService, mDisplayContent, transit)
- || shouldStartWallpaperAnimation(mDisplayContent);
- }
-
- /**
- * 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
- * if none of the app windows is embedded.
- */
- @Nullable
- private Task findParentTaskForAllEmbeddedWindows() {
- mTempTransitionWindows.clear();
- mTempTransitionWindows.addAll(mDisplayContent.mClosingApps);
- mTempTransitionWindows.addAll(mDisplayContent.mOpeningApps);
- mTempTransitionWindows.addAll(mDisplayContent.mChangingContainers);
-
- // It should only animated by the organizer if all windows are below the same leaf Task.
- Task leafTask = null;
- for (int i = mTempTransitionWindows.size() - 1; i >= 0; i--) {
- final ActivityRecord r = getAppFromContainer(mTempTransitionWindows.get(i));
- if (r == null) {
- leafTask = null;
- break;
- }
- // There are also cases where the Task contains non-embedded activity, such as launching
- // split TaskFragments from a non-embedded activity.
- // The hierarchy may looks like this:
- // - Task
- // - Activity
- // - TaskFragment
- // - Activity
- // - TaskFragment
- // - Activity
- // We also want to have the organizer handle the transition for such case.
- final Task task = r.getTask();
- // We don't support embedding in PiP, leave the animation to the PipTaskOrganizer.
- if (task == null || task.inPinnedWindowingMode()) {
- leafTask = null;
- break;
- }
- // We don't want the organizer to handle transition of other non-embedded Task.
- if (leafTask != null && leafTask != task) {
- leafTask = null;
- break;
- }
- final ActivityRecord rootActivity = task.getRootActivity();
- // We don't want the organizer to handle transition when the whole app is closing.
- if (rootActivity == null) {
- leafTask = null;
- break;
- }
- // We don't want the organizer to handle transition of non-embedded activity of other
- // app.
- if (r.getUid() != task.effectiveUid && !r.isEmbedded()) {
- leafTask = null;
- break;
- }
- leafTask = task;
- }
- mTempTransitionWindows.clear();
- return leafTask;
- }
-
- /**
- * Finds the common {@link android.window.TaskFragmentOrganizer} that organizes all embedded
- * {@link TaskFragment} belong to the given {@link Task}.
- * @return {@code null} if there is no such organizer, or if there are more than one.
- */
- @Nullable
- private ITaskFragmentOrganizer findTaskFragmentOrganizer(@Nullable Task task) {
- if (task == null) {
- return null;
- }
- // We don't support remote animation for Task with multiple TaskFragmentOrganizers.
- final ITaskFragmentOrganizer[] organizer = new ITaskFragmentOrganizer[1];
- final boolean hasMultipleOrganizers = task.forAllLeafTaskFragments(taskFragment -> {
- final ITaskFragmentOrganizer tfOrganizer = taskFragment.getTaskFragmentOrganizer();
- if (tfOrganizer == null) {
- return false;
- }
- if (organizer[0] != null && !organizer[0].asBinder().equals(tfOrganizer.asBinder())) {
- return true;
- }
- organizer[0] = tfOrganizer;
- return false;
- });
- if (hasMultipleOrganizers) {
- ProtoLog.e(WM_DEBUG_APP_TRANSITIONS, "We don't support remote animation for"
- + " Task with multiple TaskFragmentOrganizers.");
- return null;
- }
- return organizer[0];
- }
-
- /**
- * 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.
- */
- private void overrideWithRemoteAnimationIfSet(@Nullable ActivityRecord animLpActivity,
- @TransitionOldType int transit, ArraySet<Integer> activityTypes) {
- RemoteAnimationAdapter adapter = null;
- if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
- // The crash transition has higher priority than any involved remote animations.
- } else if (AppTransition.isKeyguardGoingAwayTransitOld(transit)) {
- adapter = mRemoteAnimationDefinition != null
- ? mRemoteAnimationDefinition.getAdapter(transit, activityTypes)
- : null;
- } else if (mDisplayContent.mAppTransition.getRemoteAnimationController() == null) {
- adapter = getRemoteAnimationOverride(animLpActivity, transit, activityTypes);
- }
- if (adapter != null) {
- mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(adapter);
- }
- }
-
- @Nullable
- static Task findRootTaskFromContainer(WindowContainer wc) {
- return wc.asTaskFragment() != null ? wc.asTaskFragment().getRootTask()
- : wc.asActivityRecord().getRootTask();
- }
-
- @Nullable
- static ActivityRecord getAppFromContainer(WindowContainer wc) {
- return wc.asTaskFragment() != null ? wc.asTaskFragment().getTopNonFinishingActivity()
- : wc.asActivityRecord();
- }
-
- /**
- * @return The window token that determines the animation theme.
- */
- @Nullable
- private ActivityRecord findAnimLayoutParamsToken(@TransitionOldType int transit,
- ArraySet<Integer> activityTypes, ArraySet<ActivityRecord> openingApps,
- ArraySet<ActivityRecord> closingApps, ArraySet<WindowContainer> changingApps) {
- ActivityRecord result;
-
- // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
- result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
- w -> w.getRemoteAnimationDefinition() != null
- && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
- if (result != null) {
- return result;
- }
- result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
- w -> w.fillsParent() && w.findMainWindow() != null);
- if (result != null) {
- return result;
- }
- return lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
- w -> w.findMainWindow() != null);
- }
-
- /**
- * @return The set of {@link android.app.WindowConfiguration.ActivityType}s contained in the set
- * of apps in {@code array1}, {@code array2}, and {@code array3}.
- */
- private static ArraySet<Integer> collectActivityTypes(ArraySet<ActivityRecord> array1,
- ArraySet<ActivityRecord> array2, ArraySet<WindowContainer> array3) {
- final ArraySet<Integer> result = new ArraySet<>();
- for (int i = array1.size() - 1; i >= 0; i--) {
- result.add(array1.valueAt(i).getActivityType());
- }
- for (int i = array2.size() - 1; i >= 0; i--) {
- result.add(array2.valueAt(i).getActivityType());
- }
- for (int i = array3.size() - 1; i >= 0; i--) {
- result.add(array3.valueAt(i).getActivityType());
- }
- return result;
- }
-
- private static ActivityRecord lookForHighestTokenWithFilter(ArraySet<ActivityRecord> array1,
- ArraySet<ActivityRecord> array2, ArraySet<WindowContainer> array3,
- Predicate<ActivityRecord> filter) {
- final int array2base = array1.size();
- final int array3base = array2.size() + array2base;
- final int count = array3base + array3.size();
- int bestPrefixOrderIndex = Integer.MIN_VALUE;
- ActivityRecord bestToken = null;
- for (int i = 0; i < count; i++) {
- final WindowContainer wtoken = i < array2base
- ? array1.valueAt(i)
- : (i < array3base
- ? array2.valueAt(i - array2base)
- : array3.valueAt(i - array3base));
- final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
- final ActivityRecord r = getAppFromContainer(wtoken);
- if (r != null && filter.test(r) && prefixOrderIndex > bestPrefixOrderIndex) {
- bestPrefixOrderIndex = prefixOrderIndex;
- bestToken = r;
- }
- }
- return bestToken;
- }
-
- private boolean containsVoiceInteraction(ArraySet<ActivityRecord> apps) {
- for (int i = apps.size() - 1; i >= 0; i--) {
- if (apps.valueAt(i).mVoiceInteraction) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Apply animation to the set of window containers.
- *
- * @param wcs The list of {@link WindowContainer}s to which an app transition animation applies.
- * @param apps The list of {@link ActivityRecord}s being transitioning.
- * @param transit The current transition type.
- * @param visible {@code true} if the apps becomes visible, {@code false} if the apps becomes
- * invisible.
- * @param animLp Layout parameters in which an app transition animation runs.
- * @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice
- * interaction session driving task.
- */
- private void applyAnimations(ArraySet<WindowContainer> wcs, ArraySet<ActivityRecord> apps,
- @TransitionOldType int transit, boolean visible, LayoutParams animLp,
- boolean voiceInteraction) {
- final int wcsCount = wcs.size();
- for (int i = 0; i < wcsCount; i++) {
- final WindowContainer wc = wcs.valueAt(i);
- // If app transition animation target is promoted to higher level, SurfaceAnimator
- // triggers WC#onAnimationFinished only on the promoted target. So we need to take care
- // of triggering AR#onAnimationFinished on each ActivityRecord which is a part of the
- // app transition.
- final ArrayList<ActivityRecord> transitioningDescendants = new ArrayList<>();
- for (int j = 0; j < apps.size(); ++j) {
- final ActivityRecord app = apps.valueAt(j);
- if (app.isDescendantOf(wc)) {
- transitioningDescendants.add(app);
- }
- }
- wc.applyAnimation(animLp, transit, visible, voiceInteraction, transitioningDescendants);
- }
- }
-
- /**
- * Returns {@code true} if a given {@link WindowContainer} is an embedded Task in
- * {@link TaskView}.
- *
- * Note that this is a short term workaround to support Android Auto until it migrate to
- * ShellTransition. This should only be used by {@link #getAnimationTargets}.
- *
- * TODO(b/213312721): Remove this predicate and its callers once ShellTransition is enabled.
- */
- static boolean isTaskViewTask(WindowContainer wc) {
- // Use Task#mRemoveWithTaskOrganizer to identify an embedded Task, but this is a hack and
- // it is not guaranteed to work this logic in the future version.
- boolean isTaskViewTask = wc instanceof Task && ((Task) wc).mRemoveWithTaskOrganizer;
- if (isTaskViewTask) {
- return true;
- }
-
- WindowContainer parent = wc.getParent();
- boolean isParentATaskViewTask = parent != null
- && parent instanceof Task
- && ((Task) parent).mRemoveWithTaskOrganizer;
- return isParentATaskViewTask;
- }
-
- /**
- * Find WindowContainers to be animated from a set of opening and closing apps. We will promote
- * animation targets to higher level in the window hierarchy if possible.
- *
- * @param visible {@code true} to get animation targets for opening apps, {@code false} to get
- * animation targets for closing apps.
- * @return {@link WindowContainer}s to be animated.
- */
- @VisibleForTesting
- static ArraySet<WindowContainer> getAnimationTargets(
- ArraySet<ActivityRecord> openingApps, ArraySet<ActivityRecord> closingApps,
- boolean visible) {
-
- // The candidates of animation targets, which might be able to promote to higher level.
- final ArrayDeque<WindowContainer> candidates = new ArrayDeque<>();
- final ArraySet<ActivityRecord> apps = visible ? openingApps : closingApps;
- for (int i = 0; i < apps.size(); ++i) {
- final ActivityRecord app = apps.valueAt(i);
- if (app.shouldApplyAnimation(visible)) {
- candidates.add(app);
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "Changing app %s visible=%b performLayout=%b",
- app, app.isVisible(), false);
- }
- }
-
- final ArraySet<ActivityRecord> otherApps = visible ? closingApps : openingApps;
- // Ancestors of closing apps while finding animation targets for opening apps, or ancestors
- // of opening apps while finding animation targets for closing apps.
- final ArraySet<WindowContainer> otherAncestors = new ArraySet<>();
- for (int i = 0; i < otherApps.size(); ++i) {
- for (WindowContainer wc = otherApps.valueAt(i); wc != null; wc = wc.getParent()) {
- otherAncestors.add(wc);
- }
- }
-
- // The final animation targets which cannot promote to higher level anymore.
- final ArraySet<WindowContainer> targets = new ArraySet<>();
- final ArrayList<WindowContainer> siblings = new ArrayList<>();
- while (!candidates.isEmpty()) {
- final WindowContainer current = candidates.removeFirst();
- final WindowContainer parent = current.getParent();
- siblings.clear();
- siblings.add(current);
- boolean canPromote = true;
-
- if (isTaskViewTask(current)) {
- // Don't animate an embedded Task in app transition. This is a short term workaround
- // to prevent conflict of surface hierarchy changes between legacy app transition
- // and TaskView (b/205189147).
- // TODO(b/213312721): Remove this once ShellTransition is enabled.
- continue;
- } else if (parent == null || !parent.canCreateRemoteAnimationTarget()
- // We cannot promote the animation on Task's parent when the task is in
- // clearing task in case the animating get stuck when performing the opening
- // task that behind it.
- || (current.asTask() != null && current.asTask().mInRemoveTask)
- // We cannot promote the animation to changing window. This may happen when an
- // activity is open in a TaskFragment that is resizing, while the existing
- // activity in the TaskFragment is reparented to another TaskFragment.
- || parent.isChangingAppTransition()) {
- canPromote = false;
- } else {
- // In case a descendant of the parent belongs to the other group, we cannot promote
- // the animation target from "current" to the parent.
- //
- // Example: Imagine we're checking if we can animate a Task instead of a set of
- // ActivityRecords. In case an activity starts a new activity within a same Task,
- // an ActivityRecord of an existing activity belongs to the opening apps, at the
- // same time, the other ActivityRecord of a new activity belongs to the closing
- // apps. In this case, we cannot promote the animation target to Task level, but
- // need to animate each individual activity.
- //
- // [Task] +- [ActivityRecord1] (in opening apps)
- // +- [ActivityRecord2] (in closing apps)
- if (otherAncestors.contains(parent)) {
- canPromote = false;
- }
-
- // If the current window container is a task with adjacent task set, the both
- // adjacent tasks will be opened or closed together. To get their opening or
- // closing animation target independently, skip promoting their animation targets.
- if (current.asTask() != null && current.asTask().hasAdjacentTask()) {
- canPromote = false;
- }
-
- // Find all siblings of the current WindowContainer in "candidates", move them into
- // a separate list "siblings", and checks if an animation target can be promoted
- // to its parent.
- //
- // We can promote an animation target to its parent if and only if all visible
- // siblings will be animating.
- //
- // Example: Imagine that a Task contains two visible activity record, but only one
- // of them is included in the opening apps and the other belongs to neither opening
- // or closing apps. This happens when an activity launches another translucent
- // activity in the same Task. In this case, we cannot animate Task, but have to
- // animate each activity, otherwise an activity behind the translucent activity also
- // animates.
- //
- // [Task] +- [ActivityRecord1] (visible, in opening apps)
- // +- [ActivityRecord2] (visible, not in opening apps)
- for (int j = 0; j < parent.getChildCount(); ++j) {
- final WindowContainer sibling = parent.getChildAt(j);
- if (candidates.remove(sibling)) {
- if (!isTaskViewTask(sibling)) {
- // Don't animate an embedded Task in app transition. This is a short
- // term workaround to prevent conflict of surface hierarchy changes
- // between legacy app transition and TaskView (b/205189147).
- // TODO(b/213312721): Remove this once ShellTransition is enabled.
- siblings.add(sibling);
- }
- } else if (sibling != current && sibling.isVisible()) {
- canPromote = false;
- }
- }
- }
-
- if (canPromote) {
- candidates.add(parent);
- } else {
- targets.addAll(siblings);
- }
- }
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "getAnimationTarget in=%s, out=%s",
- apps, targets);
- return targets;
- }
-
- /**
- * Apply an app transition animation based on a set of {@link ActivityRecord}
- *
- * @param openingApps The list of opening apps to which an app transition animation applies.
- * @param closingApps The list of closing apps to which an app transition animation applies.
- * @param transit The current transition type.
- * @param animLp Layout parameters in which an app transition animation runs.
- * @param voiceInteraction {@code true} if one of the apps in this transition belongs to a voice
- * interaction session driving task.
- */
- private void applyAnimations(ArraySet<ActivityRecord> openingApps,
- ArraySet<ActivityRecord> closingApps, @TransitionOldType int transit,
- LayoutParams animLp, boolean voiceInteraction) {
- if (transit == WindowManager.TRANSIT_OLD_UNSET
- || (openingApps.isEmpty() && closingApps.isEmpty())) {
- return;
- }
-
- if (AppTransition.isActivityTransitOld(transit)) {
- final ArrayList<Pair<ActivityRecord, Rect>> closingLetterboxes = new ArrayList();
- for (int i = 0; i < closingApps.size(); ++i) {
- ActivityRecord closingApp = closingApps.valueAt(i);
- if (closingApp.areBoundsLetterboxed()) {
- final Rect insets = closingApp.getLetterboxInsets();
- closingLetterboxes.add(new Pair(closingApp, insets));
- }
- }
-
- for (int i = 0; i < openingApps.size(); ++i) {
- ActivityRecord openingApp = openingApps.valueAt(i);
- if (openingApp.areBoundsLetterboxed()) {
- final Rect openingInsets = openingApp.getLetterboxInsets();
- for (Pair<ActivityRecord, Rect> closingLetterbox : closingLetterboxes) {
- final Rect closingInsets = closingLetterbox.second;
- if (openingInsets.equals(closingInsets)) {
- ActivityRecord closingApp = closingLetterbox.first;
- openingApp.setNeedsLetterboxedAnimation(true);
- closingApp.setNeedsLetterboxedAnimation(true);
- }
- }
- }
- }
- }
-
- final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
- openingApps, closingApps, true /* visible */);
- final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
- openingApps, closingApps, false /* visible */);
- applyAnimations(openingWcs, openingApps, transit, true /* visible */, animLp,
- voiceInteraction);
- applyAnimations(closingWcs, closingApps, transit, false /* visible */, animLp,
- voiceInteraction);
-
- for (int i = 0; i < openingApps.size(); ++i) {
- openingApps.valueAtUnchecked(i).mOverrideTaskTransition = false;
- }
- for (int i = 0; i < closingApps.size(); ++i) {
- closingApps.valueAtUnchecked(i).mOverrideTaskTransition = false;
- }
-
- final AccessibilityController accessibilityController =
- mDisplayContent.mWmService.mAccessibilityController;
- if (accessibilityController.hasCallbacks()) {
- accessibilityController.onAppWindowTransition(mDisplayContent.getDisplayId(), transit);
- }
- }
-
- private void handleOpeningApps() {
- final ArraySet<ActivityRecord> openingApps = mDisplayContent.mOpeningApps;
- final int appsCount = openingApps.size();
-
- for (int i = 0; i < appsCount; i++) {
- final ActivityRecord app = openingApps.valueAt(i);
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", app);
-
- app.commitVisibility(true /* visible */, false /* performLayout */);
-
- // In case a trampoline activity is used, it can happen that a new ActivityRecord is
- // added and a new app transition starts before the previous app transition animation
- // ends. So we cannot simply use app.isAnimating(PARENTS) to determine if the app must
- // to be added to the list of tokens to be notified of app transition complete.
- final WindowContainer wc = app.getAnimatingContainer(PARENTS,
- ANIMATION_TYPE_APP_TRANSITION);
- if (wc == null || !wc.getAnimationSources().contains(app)) {
- // This token isn't going to be animating. Add it to the list of tokens to
- // be notified of app transition complete since the notification will not be
- // sent be the app window animator.
- mDisplayContent.mNoAnimationNotifyOnTransitionFinished.add(app.token);
- }
- app.updateReportedVisibilityLocked();
- app.showAllWindowsLocked();
-
- if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailUp()) {
- app.attachThumbnailAnimation();
- } else if (mDisplayContent.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
- app.attachCrossProfileAppsThumbnailAnimation();
- }
- }
- }
-
- private void handleClosingApps() {
- final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
- final int appsCount = closingApps.size();
-
- for (int i = 0; i < appsCount; i++) {
- final ActivityRecord app = closingApps.valueAt(i);
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now closing app %s", app);
-
- app.commitVisibility(false /* visible */, false /* performLayout */);
- app.updateReportedVisibilityLocked();
- // Force the allDrawn flag, because we want to start
- // this guy's animations regardless of whether it's
- // gotten drawn.
- app.allDrawn = true;
- // Ensure that apps that are mid-starting are also scheduled to have their
- // starting windows removed after the animation is complete
- if (app.mStartingWindow != null && !app.mStartingWindow.mAnimatingExit) {
- app.removeStartingWindow();
- }
-
- if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailDown()) {
- app.attachThumbnailAnimation();
- }
- }
- }
-
- private void handleClosingChangingContainers() {
- final ArrayMap<WindowContainer, Rect> containers =
- mDisplayContent.mClosingChangingContainers;
- while (!containers.isEmpty()) {
- final WindowContainer container = containers.keyAt(0);
- containers.remove(container);
-
- // For closing changing windows that are part of the transition, they should have been
- // removed from mClosingChangingContainers in WindowContainer#getAnimationAdapter()
- // If the closing changing TaskFragment is not part of the transition, update its
- // surface after removing it from mClosingChangingContainers.
- final TaskFragment taskFragment = container.asTaskFragment();
- if (taskFragment != null) {
- taskFragment.updateOrganizedTaskFragmentSurface();
- }
- }
- }
-
- private void handleChangingApps(@TransitionOldType int transit) {
- final ArraySet<WindowContainer> apps = mDisplayContent.mChangingContainers;
- final int appsCount = apps.size();
- for (int i = 0; i < appsCount; i++) {
- WindowContainer wc = apps.valueAt(i);
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wc);
- wc.applyAnimation(null, transit, true, false, null /* sources */);
- }
- }
-
- private boolean transitionGoodToGo(ArraySet<? extends WindowContainer> apps,
- ArrayMap<WindowContainer, Integer> outReasons) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "Checking %d opening apps (timeout=%b)...", apps.size(),
- mDisplayContent.mAppTransition.isTimeout());
- if (mDisplayContent.mAppTransition.isTimeout()) {
- return true;
- }
-
- for (int i = 0; i < apps.size(); i++) {
- WindowContainer wc = apps.valueAt(i);
- final ActivityRecord activity = getAppFromContainer(wc);
- if (activity == null) {
- continue;
- }
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "Check opening app=%s: allDrawn=%b startingDisplayed=%b "
- + "startingMoved=%b isRelaunching()=%b startingWindow=%s",
- activity, activity.allDrawn, activity.isStartingWindowDisplayed(),
- activity.startingMoved, activity.isRelaunching(),
- activity.mStartingWindow);
- final boolean allDrawn = activity.allDrawn && !activity.isRelaunching();
- if (!allDrawn && !activity.isStartingWindowDisplayed() && !activity.startingMoved) {
- return false;
- }
- if (allDrawn) {
- outReasons.put(activity, APP_TRANSITION_WINDOWS_DRAWN);
- } else {
- outReasons.put(activity,
- activity.mStartingData instanceof SplashScreenStartingData
- ? APP_TRANSITION_SPLASH_SCREEN
- : APP_TRANSITION_SNAPSHOT);
- }
- }
-
- // We also need to wait for the specs to be fetched, if needed.
- if (mDisplayContent.mAppTransition.isFetchingAppTransitionsSpecs()) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "isFetchingAppTransitionSpecs=true");
- return false;
- }
-
- if (!mDisplayContent.mUnknownAppVisibilityController.allResolved()) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "unknownApps is not empty: %s",
- mDisplayContent.mUnknownAppVisibilityController.getDebugMessage());
- return false;
- }
-
- // If the wallpaper is visible, we need to check it's ready too.
- return !mWallpaperControllerLocked.isWallpaperVisible()
- || mWallpaperControllerLocked.wallpaperTransitionReady();
- }
-
- private boolean transitionGoodToGoForTaskFragments() {
- if (mDisplayContent.mAppTransition.isTimeout()) {
- return true;
- }
-
- // Check all Tasks in this transition. This is needed because new TaskFragment created for
- // launching activity may not be in the tracking lists, but we still want to wait for the
- // activity launch to start the transition.
- final ArraySet<Task> rootTasks = new ArraySet<>();
- for (int i = mDisplayContent.mOpeningApps.size() - 1; i >= 0; i--) {
- rootTasks.add(mDisplayContent.mOpeningApps.valueAt(i).getRootTask());
- }
- for (int i = mDisplayContent.mClosingApps.size() - 1; i >= 0; i--) {
- rootTasks.add(mDisplayContent.mClosingApps.valueAt(i).getRootTask());
- }
- for (int i = mDisplayContent.mChangingContainers.size() - 1; i >= 0; i--) {
- rootTasks.add(
- findRootTaskFromContainer(mDisplayContent.mChangingContainers.valueAt(i)));
- }
-
- // Organized TaskFragment can be empty for two situations:
- // 1. New created and is waiting for Activity launch. In this case, we want to wait for
- // the Activity launch to trigger the transition.
- // 2. Last Activity is just removed. In this case, we want to wait for organizer to
- // remove the TaskFragment because it may also want to change other TaskFragments in
- // the same transition.
- for (int i = rootTasks.size() - 1; i >= 0; i--) {
- final Task rootTask = rootTasks.valueAt(i);
- if (rootTask == null) {
- // It is possible that one activity may have been removed from the hierarchy. No
- // need to check for this case.
- continue;
- }
- final boolean notReady = rootTask.forAllLeafTaskFragments(taskFragment -> {
- if (!taskFragment.isReadyToTransit()) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Organized TaskFragment is not ready= %s",
- taskFragment);
- return true;
- }
- return false;
- });
- if (notReady) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Identifies whether the current transition occurs within a single task or not. This is used
- * to determine whether animations should be clipped to the task bounds instead of root task
- * bounds.
- */
- @VisibleForTesting
- boolean isTransitWithinTask(@TransitionOldType int transit, Task task) {
- if (task == null
- || !mDisplayContent.mChangingContainers.isEmpty()) {
- // if there is no task, then we can't constrain to the task.
- // if anything is changing, it can animate outside its task.
- return false;
- }
- if (!(transit == TRANSIT_OLD_ACTIVITY_OPEN
- || transit == TRANSIT_OLD_ACTIVITY_CLOSE
- || transit == TRANSIT_OLD_ACTIVITY_RELAUNCH)) {
- // only activity-level transitions will be within-task.
- return false;
- }
- // check that all components are in the task.
- for (ActivityRecord activity : mDisplayContent.mOpeningApps) {
- Task activityTask = activity.getTask();
- if (activityTask != task) {
- return false;
- }
- }
- for (ActivityRecord activity : mDisplayContent.mClosingApps) {
- if (activity.getTask() != task) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean canBeWallpaperTarget(ArraySet<ActivityRecord> apps) {
- for (int i = apps.size() - 1; i >= 0; i--) {
- if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Finds the top app in a list of apps, using its {@link ActivityRecord#getPrefixOrderIndex} to
- * compare z-order.
- *
- * @param apps The list of apps to search.
- * @param ignoreInvisible If set to true, ignores apps that are not
- * {@link ActivityRecord#isVisible}.
- * @return The top {@link ActivityRecord}.
- */
- private static ActivityRecord getTopApp(ArraySet<? extends WindowContainer> apps,
- boolean ignoreInvisible) {
- int topPrefixOrderIndex = Integer.MIN_VALUE;
- ActivityRecord topApp = null;
- for (int i = apps.size() - 1; i >= 0; i--) {
- final ActivityRecord app = getAppFromContainer(apps.valueAt(i));
- if (app == null || ignoreInvisible && !app.isVisible()) {
- continue;
- }
- final int prefixOrderIndex = app.getPrefixOrderIndex();
- if (prefixOrderIndex > topPrefixOrderIndex) {
- topPrefixOrderIndex = prefixOrderIndex;
- topApp = app;
- }
- }
- return topApp;
- }
-}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c87087f84399..682f3d8cf1e5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -226,7 +226,6 @@ import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.MagnificationSpec;
import android.view.PrivacyIndicatorBounds;
-import android.view.RemoteAnimationDefinition;
import android.view.RoundedCorners;
import android.view.Surface;
import android.view.Surface.Rotation;
@@ -367,8 +366,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
private int mMaxUiWidth = 0;
final AppTransition mAppTransition;
- final AppTransitionController mAppTransitionController;
- boolean mSkipAppTransitionAnimation = false;
final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
@@ -1161,7 +1158,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
- mAppTransitionController = new AppTransitionController(mWmService, this);
mTransitionController.registerLegacyListener(mFixedRotationTransitionListener);
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
mRemoteDisplayChangeController = new RemoteDisplayChangeController(this);
@@ -1553,10 +1549,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mInputMethodSurfaceParentWindow;
}
- void registerRemoteAnimations(RemoteAnimationDefinition definition) {
- mAppTransitionController.registerRemoteAnimations(definition);
- }
-
void reconfigureDisplayLocked() {
if (!isReady()) {
return;
@@ -5604,20 +5596,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
/**
- * Transfer app transition from other display to this display.
- *
- * @param from Display from where the app transition is transferred.
- *
- * TODO(new-app-transition): Remove this once the shell handles app transition.
- */
- void transferAppTransitionFrom(DisplayContent from) {
- final boolean prepared = mAppTransition.transferFrom(from.mAppTransition);
- if (prepared && okToAnimate()) {
- mSkipAppTransitionAnimation = false;
- }
- }
-
- /**
* @deprecated new transition should use {@link #requestTransitionAndLegacyPrepare(int, int)}
*/
@Deprecated
@@ -5631,10 +5609,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@Deprecated
void prepareAppTransition(@WindowManager.TransitionType int transit,
@WindowManager.TransitionFlags int flags) {
- final boolean prepared = mAppTransition.prepareAppTransition(transit, flags);
- if (prepared && okToAnimate() && transit != TRANSIT_NONE) {
- mSkipAppTransitionAnimation = false;
- }
+ mAppTransition.prepareAppTransition(transit, flags);
}
/**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 95d9b3e612ac..c93efd327096 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -35,7 +35,6 @@ import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_PIP;
import static android.view.WindowManager.TRANSIT_SLEEP;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_WAKE;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS_LIGHT;
@@ -68,7 +67,6 @@ import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
-import static com.android.server.wm.KeyguardController.KEYGUARD_SLEEP_TOKEN_TAG;
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
@@ -803,8 +801,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mWmService.mAtmService.mTaskFragmentOrganizerController.dispatchPendingEvents();
mWmService.mSyncEngine.onSurfacePlacement();
- checkAppTransitionReady(surfacePlacer);
-
mWmService.mAtmService.mBackNavigationController
.checkAnimationReady(defaultDisplay.mWallpaperController);
@@ -898,38 +894,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit");
}
- private void checkAppTransitionReady(WindowSurfacePlacer surfacePlacer) {
- // Trace all displays app transition by Z-order for pending layout change.
- for (int i = mChildren.size() - 1; i >= 0; --i) {
- final DisplayContent curDisplay = mChildren.get(i);
-
- // If we are ready to perform an app transition, check through all of the app tokens
- // to be shown and see if they are ready to go.
- if (curDisplay.mAppTransition.isReady()) {
- // handleAppTransitionReady may modify curDisplay.pendingLayoutChanges.
- curDisplay.mAppTransitionController.handleAppTransitionReady();
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats("after handleAppTransitionReady",
- curDisplay.pendingLayoutChanges);
- }
- }
-
- if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppTransitioning()) {
- // We have finished the animation of an app transition. To do this, we have
- // delayed a lot of operations like showing and hiding apps, moving apps in
- // Z-order, etc.
- // The app token list reflects the correct Z-order, but the window list may now
- // be out of sync with it. So here we will just rebuild the entire app window
- // list. Fun!
- curDisplay.handleAnimatingStoppedAndTransition();
- if (DEBUG_LAYOUT_REPEATS) {
- surfacePlacer.debugLayoutRepeats("after handleAnimStopAndXitionLock",
- curDisplay.pendingLayoutChanges);
- }
- }
- }
- }
-
private void applySurfaceChangesTransaction() {
// TODO(multi-display): Support these features on secondary screens.
final DisplayContent defaultDc = mDefaultDisplay;
@@ -2266,20 +2230,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Ensure the leash of new task is in sync with its current bounds after reparent.
rootTask.maybeApplyLastRecentsAnimationTransaction();
-
- // In the case of this activity entering PIP due to it being moved to the back,
- // the old activity would have a TRANSIT_TASK_TO_BACK transition that needs to be
- // ran. But, since its visibility did not change (note how it was STOPPED/not
- // visible, and with it now at the back stack, it remains not visible), the logic to
- // add the transition is automatically skipped. We then add this activity manually
- // to the list of apps being closed, and request its transition to be ran.
- final ActivityRecord oldTopActivity = task.getTopMostActivity();
- if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
- && task.getDisplayContent().mAppTransition.containsTransitRequest(
- TRANSIT_TO_BACK)) {
- task.getDisplayContent().mClosingApps.add(oldTopActivity);
- oldTopActivity.mRequestForceTransition = true;
- }
}
// TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing
@@ -2958,20 +2908,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
display.mAllSleepTokens.remove(token);
if (display.mAllSleepTokens.isEmpty()) {
mService.updateSleepIfNeededLocked();
- // Assuming no lock screen is set and a user launches an activity, turns off the screen
- // and turn on the screen again, then the launched activity should be displayed on the
- // screen without app transition animation. When the screen turns on, both keyguard
- // sleep token and display off sleep token are removed, but the order is
- // non-deterministic.
- // Note: Display#mSkipAppTransitionAnimation will be ignored when keyguard related
- // transition exists, so this affects only when no lock screen is set. Otherwise
- // keyguard going away animation will be played.
- // See also AppTransitionController#getTransitCompatType for more details.
- if ((!mTaskSupervisor.getKeyguardController().isKeyguardOccluded(display.mDisplayId)
- && token.mTag.equals(KEYGUARD_SLEEP_TOKEN_TAG))
- || token.mTag.equals(DISPLAY_OFF_SLEEP_TOKEN_TAG)) {
- display.mSkipAppTransitionAnimation = true;
- }
}
}
diff --git a/services/core/java/com/android/server/wm/SnapshotController.java b/services/core/java/com/android/server/wm/SnapshotController.java
index dcdffa416e33..2664dcd3ae3f 100644
--- a/services/core/java/com/android/server/wm/SnapshotController.java
+++ b/services/core/java/com/android/server/wm/SnapshotController.java
@@ -72,11 +72,6 @@ class SnapshotController {
mActivitySnapshotController.notifyAppVisibilityChanged(appWindowToken, visible);
}
- // For legacy transition, which won't support activity snapshot
- void onTransitionStarting(DisplayContent displayContent) {
- mTaskSnapshotController.handleClosingApps(displayContent.mClosingApps);
- }
-
// For shell transition, record snapshots before transaction start.
void onTransactionReady(@WindowManager.TransitionType int type,
ArrayList<Transition.ChangeInfo> changeInfos) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 432ed1d0b61d..8a937721b347 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -113,27 +113,6 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
enableLowResSnapshots, lowResScaleFactor, use16BitFormat);
}
- // Still needed for legacy transition.(AppTransitionControllerTest)
- void handleClosingApps(ArraySet<ActivityRecord> closingApps) {
- if (shouldDisableSnapshots()) {
- return;
- }
- // We need to take a snapshot of the task if and only if all activities of the task are
- // either closing or hidden.
- mTmpTasks.clear();
- for (int i = closingApps.size() - 1; i >= 0; i--) {
- final ActivityRecord activity = closingApps.valueAt(i);
- if (activity.isActivityTypeHome()) continue;
- final Task task = activity.getTask();
- if (task == null) continue;
-
- getClosingTasksInner(task, mTmpTasks);
- }
- snapshotTasks(mTmpTasks);
- mTmpTasks.clear();
- mSkipClosingAppSnapshotTasks.clear();
- }
-
/**
* Adds the given {@param tasks} to the list of tasks which should not have their snapshots
* taken upon the next processing of the set of closing apps. The caller is responsible for
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 55c2668f62d0..7af542f10127 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3359,7 +3359,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) {
- if (AppTransitionController.isTaskViewTask(this) || (isOrganized()
+ if ((isOrganized()
// TODO(b/161711458): Clean-up when moved to shell.
&& getWindowingMode() != WINDOWING_MODE_FULLSCREEN
&& getWindowingMode() != WINDOWING_MODE_FREEFORM
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bb669915e366..d699a689459e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -347,7 +347,6 @@ import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.SystemConfig;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
@@ -449,11 +448,6 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Use WMShell for app transition.
*/
- private static final String ENABLE_SHELL_TRANSITIONS = "persist.wm.debug.shell_transit";
-
- /**
- * @see #ENABLE_SHELL_TRANSITIONS
- */
public static final boolean sEnableShellTransitions = getShellTransitEnabled();
/**
@@ -10311,11 +10305,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
private static boolean getShellTransitEnabled() {
- android.content.pm.FeatureInfo autoFeature = SystemConfig.getInstance()
- .getAvailableFeatures().get(PackageManager.FEATURE_AUTOMOTIVE);
- if (autoFeature != null && autoFeature.version >= 0) {
- return SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
- }
return true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 440f43e9b926..bb296148dad1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2881,7 +2881,6 @@ public class ActivityRecordTests extends WindowTestsBase {
activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1, true, true,
false, true, false, false, false);
waitUntilHandlersIdle();
- assertFalse(mDisplayContent.mSkipAppTransitionAnimation);
assertNoStartingWindow(activity1);
assertHasStartingWindow(activity2);
}
@@ -2965,7 +2964,6 @@ public class ActivityRecordTests extends WindowTestsBase {
false /* newTask */, false /* isTaskSwitch */, null /* options */,
null /* sourceRecord */);
- assertTrue(mDisplayContent.mSkipAppTransitionAnimation);
assertNull(middle.mStartingWindow);
assertHasStartingWindow(top);
assertTrue(top.isVisible());
@@ -3265,26 +3263,6 @@ public class ActivityRecordTests extends WindowTestsBase {
> activity.getConfiguration().windowConfiguration.getAppBounds().height());
}
- @Test
- public void testSetVisibility_visibleToVisible() {
- final ActivityRecord activity = new ActivityBuilder(mAtm)
- .setCreateTask(true).build();
- // By default, activity is visible.
- assertTrue(activity.isVisible());
- assertTrue(activity.isVisibleRequested());
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
-
- // Request the activity to be visible. Although the activity is already visible, app
- // transition animation should be applied on this activity. This might be unnecessary, but
- // until we verify no logic relies on this behavior, we'll keep this as is.
- mDisplayContent.prepareAppTransition(0);
- activity.setVisibility(true);
- assertTrue(activity.isVisible());
- assertTrue(activity.isVisibleRequested());
- assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
- }
-
@SetupWindows(addWindows = W_ACTIVITY)
@Test
public void testSetVisibility_visibleToInvisible() {
@@ -3316,50 +3294,30 @@ public class ActivityRecordTests extends WindowTestsBase {
public void testSetVisibility_invisibleToVisible() {
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setCreateTask(true).setVisible(false).build();
- // Activiby is invisible. However ATMS requests it to become visible, since this is a top
- // activity.
assertFalse(activity.isVisible());
- assertTrue(activity.isVisibleRequested());
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ assertFalse(activity.isVisibleRequested());
// Request the activity to be visible. Since the visibility changes, app transition
// animation should be applied on this activity.
- activity.setVisibility(true);
+ requestTransition(activity, WindowManager.TRANSIT_OPEN);
+ mWm.mRoot.resumeFocusedTasksTopActivities();
assertFalse(activity.isVisible());
assertTrue(activity.isVisibleRequested());
- assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
-
- // There should still be animation (add to opening) if keyguard is going away while the
- // screen is off because it will be visible after screen is turned on by unlocking.
- mDisplayContent.mOpeningApps.remove(activity);
- mDisplayContent.mClosingApps.remove(activity);
- activity.commitVisibility(false /* visible */, false /* performLayout */);
- mDisplayContent.getDisplayPolicy().screenTurnedOff(false /* acquireSleepToken */);
- final KeyguardController controller = mSupervisor.getKeyguardController();
- doReturn(true).when(controller).isKeyguardGoingAway(anyInt());
- activity.setVisibility(true);
- assertTrue(mDisplayContent.mOpeningApps.contains(activity));
+ assertTrue(activity.inTransition());
}
@Test
public void testSetVisibility_invisibleToInvisible() {
final ActivityRecord activity = new ActivityBuilder(mAtm)
.setCreateTask(true).setVisible(false).build();
- // Activiby is invisible. However ATMS requests it to become visible, since this is a top
- // activity.
- assertFalse(activity.isVisible());
- assertTrue(activity.isVisibleRequested());
- assertTrue(activity.mDisplayContent.mOpeningApps.contains(activity));
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ requestTransition(activity, WindowManager.TRANSIT_CLOSE);
// Request the activity to be invisible. Since the activity is already invisible, no app
// transition should be applied on this activity.
activity.setVisibility(false);
assertFalse(activity.isVisible());
assertFalse(activity.isVisibleRequested());
- assertFalse(activity.mDisplayContent.mOpeningApps.contains(activity));
- assertFalse(activity.mDisplayContent.mClosingApps.contains(activity));
+ assertFalse(activity.inTransition());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
deleted file mode 100644
index c294bc62c7ac..000000000000
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
- * Copyright (C) 2018 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 com.android.server.wm;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-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;
-
-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;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-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;
-import android.platform.test.annotations.Presubmit;
-import android.util.ArraySet;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationDefinition;
-import android.view.RemoteAnimationTarget;
-import android.view.WindowManager;
-import android.window.ITaskFragmentOrganizer;
-import android.window.TaskFragmentOrganizer;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Build/Install/Run:
- * atest WmTests:AppTransitionControllerTest
- */
-@SmallTest
-@Presubmit
-@RunWith(WindowTestRunner.class)
-public class AppTransitionControllerTest extends WindowTestsBase {
-
- private AppTransitionController mAppTransitionController;
-
- @Before
- public void setUp() throws Exception {
- assumeFalse(WindowManagerService.sEnableShellTransitions);
- mAppTransitionController = new AppTransitionController(mWm, mDisplayContent);
- mWm.mAnimator.ready();
- }
-
- @Test
- public void testSkipOccludedActivityCloseTransition() {
- final ActivityRecord behind = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord topOpening = createActivityRecord(behind.getTask());
- topOpening.setOccludesParent(true);
- topOpening.setVisible(true);
-
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
- mDisplayContent.mClosingApps.add(behind);
-
- assertEquals(WindowManager.TRANSIT_OLD_UNSET,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testClearTaskSkipAppExecuteTransition() {
- final ActivityRecord behind = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final Task task = behind.getTask();
- final ActivityRecord top = createActivityRecord(task);
- top.setState(ActivityRecord.State.RESUMED, "test");
- behind.setState(ActivityRecord.State.STARTED, "test");
- behind.setVisibleRequested(true);
-
- task.removeActivities("test", false /* excludingTaskOverlay */);
- assertFalse(mDisplayContent.mAppTransition.isReady());
- }
-
- @Test
- public void testTranslucentOpen() {
- final ActivityRecord behind = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- doReturn(false).when(translucentOpening).fillsParent();
- translucentOpening.setVisible(false);
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
- mDisplayContent.mOpeningApps.add(behind);
- mDisplayContent.mOpeningApps.add(translucentOpening);
-
- assertEquals(WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testTranslucentClose() {
- final ActivityRecord behind = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord translucentClosing = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- doReturn(false).when(translucentClosing).fillsParent();
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
- mDisplayContent.mClosingApps.add(translucentClosing);
- assertEquals(WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testDreamActivityOpenTransition() {
- final ActivityRecord dreamActivity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM);
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
- mDisplayContent.mOpeningApps.add(dreamActivity);
-
- assertEquals(TRANSIT_OLD_DREAM_ACTIVITY_OPEN,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testDreamActivityCloseTransition() {
- final ActivityRecord dreamActivity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM);
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
- mDisplayContent.mClosingApps.add(dreamActivity);
-
- assertEquals(TRANSIT_OLD_DREAM_ACTIVITY_CLOSE,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testChangeIsNotOverwritten() {
- final ActivityRecord behind = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- translucentOpening.setOccludesParent(false);
- translucentOpening.setVisible(false);
- mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
- mDisplayContent.mOpeningApps.add(behind);
- mDisplayContent.mOpeningApps.add(translucentOpening);
- mDisplayContent.mChangingContainers.add(translucentOpening.getTask());
- assertEquals(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null, null, false));
- }
-
- @Test
- public void testTransitWithinTask() {
- final ActivityRecord opening = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
- opening.setOccludesParent(false);
- final ActivityRecord closing = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
- closing.setOccludesParent(false);
- final Task task = opening.getTask();
- mDisplayContent.mOpeningApps.add(opening);
- mDisplayContent.mClosingApps.add(closing);
- assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_ACTIVITY_OPEN, task));
- closing.getTask().removeChild(closing);
- task.addChild(closing, 0);
- assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_ACTIVITY_OPEN, task));
- assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_TASK_OPEN, task));
- }
-
-
- @Test
- public void testIntraWallpaper_open() {
- final ActivityRecord opening = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- opening.setVisible(false);
- final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
- TYPE_BASE_APPLICATION);
- attrOpening.setTitle("WallpaperOpening");
- attrOpening.flags |= FLAG_SHOW_WALLPAPER;
- final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
- opening.addWindow(appWindowOpening);
-
- final ActivityRecord closing = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
- TYPE_BASE_APPLICATION);
- attrOpening.setTitle("WallpaperClosing");
- attrClosing.flags |= FLAG_SHOW_WALLPAPER;
- final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
- closing.addWindow(appWindowClosing);
-
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
- mDisplayContent.mOpeningApps.add(opening);
- mDisplayContent.mClosingApps.add(closing);
-
- assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, appWindowClosing, null, false));
- }
-
- @Test
- public void testIntraWallpaper_toFront() {
- final ActivityRecord opening = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- opening.setVisible(false);
- final WindowManager.LayoutParams attrOpening = new WindowManager.LayoutParams(
- TYPE_BASE_APPLICATION);
- attrOpening.setTitle("WallpaperOpening");
- attrOpening.flags |= FLAG_SHOW_WALLPAPER;
- final TestWindowState appWindowOpening = createWindowState(attrOpening, opening);
- opening.addWindow(appWindowOpening);
-
- final ActivityRecord closing = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final WindowManager.LayoutParams attrClosing = new WindowManager.LayoutParams(
- TYPE_BASE_APPLICATION);
- attrOpening.setTitle("WallpaperClosing");
- attrClosing.flags |= FLAG_SHOW_WALLPAPER;
- final TestWindowState appWindowClosing = createWindowState(attrClosing, closing);
- closing.addWindow(appWindowClosing);
-
- mDisplayContent.prepareAppTransition(TRANSIT_TO_FRONT);
- mDisplayContent.mOpeningApps.add(opening);
- mDisplayContent.mClosingApps.add(closing);
-
- assertEquals(WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, appWindowClosing, null, false));
- }
-
- @Test
- public void testGetAnimationTargets_visibilityAlreadyUpdated() {
- // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
- // +- [Task2] - [ActivityRecord2] (closing, invisible)
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
- activity2.setVisible(false);
- activity2.setVisibleRequested(false);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // No animation, since visibility of the opening and closing apps are already updated
- // outside of AppTransition framework.
- assertEquals(
- new ArraySet<>(),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_visibilityAlreadyUpdated_butForcedTransitionRequested() {
- // [DisplayContent] -+- [Task1] - [ActivityRecord1] (closing, invisible)
- // +- [Task2] - [ActivityRecord2] (opening, visible)
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(true);
- activity1.setVisibleRequested(true);
- activity1.mRequestForceTransition = true;
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
- activity2.setVisible(false);
- activity2.setVisibleRequested(false);
- activity2.mRequestForceTransition = true;
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // The visibility are already updated, but since forced transition is requested, it will
- // be included.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_exitingBeforeTransition() {
- // Create another non-empty task so the animation target won't promote to task display area.
- createActivityRecord(mDisplayContent);
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- activity.setVisible(false);
- activity.mIsExiting = true;
-
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity);
-
- // Animate closing apps even if it's not visible when it is exiting before we had a chance
- // to play the transition animation.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- new ArraySet<>(), closing, false /* visible */));
- }
-
- @Test
- public void testExitAnimationDone_beforeAppTransition() {
- final Task task = createTask(mDisplayContent);
- final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "Win");
- spyOn(win);
- win.mAnimatingExit = true;
- mDisplayContent.mAppTransition.setTimeout();
- mDisplayContent.mAppTransitionController.handleAppTransitionReady();
-
- verify(win).onExitAnimationDone();
- }
-
- @Test
- public void testGetAnimationTargets_openingClosingInDifferentTask() {
- // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (invisible)
- // |
- // +- [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (invisible)
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
- activity1.getTask());
- activity2.setVisible(false);
- activity2.setVisibleRequested(false);
-
- final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
- final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
- activity3.getTask());
- activity4.setVisible(false);
- activity4.setVisibleRequested(false);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity3);
-
- // Promote animation targets to root Task level. Invisible ActivityRecords don't affect
- // promotion decision.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity3.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_openingClosingInSameTask() {
- // [DisplayContent] - [Task] -+- [ActivityRecord1] (opening, invisible)
- // +- [ActivityRecord2] (closing, visible)
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
- activity1.getTask());
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Don't promote an animation target to Task level, since the same task contains both
- // opening and closing app.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_animateOnlyTranslucentApp() {
- // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (visible)
- // |
- // +- [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (visible)
-
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- activity1.setOccludesParent(false);
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
- activity1.getTask());
-
- final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
- activity3.setOccludesParent(false);
- final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
- activity3.getTask());
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity3);
-
- // Don't promote an animation target to Task level, since opening (closing) app is
- // translucent and is displayed over other non-animating app.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity3}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_animateTranslucentAndOpaqueApps() {
- // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (opening, invisible)
- // |
- // +- [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (closing, visible)
-
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- activity1.setOccludesParent(false);
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
- activity1.getTask());
- activity2.setVisible(false);
- activity2.setVisibleRequested(true);
-
- final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
- activity3.setOccludesParent(false);
- final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
- activity3.getTask());
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- opening.add(activity2);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity3);
- closing.add(activity4);
-
- // Promote animation targets to TaskStack level even though opening (closing) app is
- // translucent as long as all visible siblings animate at the same time.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity3.getRootTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_taskContainsMultipleTasks() {
- // [DisplayContent] - [Task] -+- [Task1] - [ActivityRecord1] (opening, invisible)
- // +- [Task2] - [ActivityRecord2] (closing, visible)
- final Task parentTask = createTask(mDisplayContent);
- final ActivityRecord activity1 = createActivityRecordWithParentTask(parentTask);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- final ActivityRecord activity2 = createActivityRecordWithParentTask(parentTask);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Promote animation targets up to Task level, not beyond.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1.getTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_splitScreenOpening() {
- // [DisplayContent] - [Task] -+- [split task 1] -+- [Task1] - [AR1] (opening, invisible)
- // +- [split task 2] -+- [Task2] - [AR2] (opening, invisible)
- final Task singleTopRoot = createTask(mDisplayContent);
- final TaskBuilder builder = new TaskBuilder(mSupervisor)
- .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW)
- .setParentTask(singleTopRoot)
- .setCreatedByOrganizer(true);
- final Task splitRoot1 = builder.build();
- final Task splitRoot2 = builder.build();
- splitRoot1.setAdjacentTaskFragment(splitRoot2);
- final ActivityRecord activity1 = createActivityRecordWithParentTask(splitRoot1);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- final ActivityRecord activity2 = createActivityRecordWithParentTask(splitRoot2);
- activity2.setVisible(false);
- activity2.setVisibleRequested(true);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- opening.add(activity2);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
-
- // Promote animation targets up to Task level, not beyond.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{splitRoot1, splitRoot2}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_openingClosingTaskFragment() {
- // [DefaultTDA] - [Task] -+- [TaskFragment1] - [ActivityRecord1] (opening, invisible)
- // +- [TaskFragment2] - [ActivityRecord2] (closing, visible)
- final Task parentTask = createTask(mDisplayContent);
- final TaskFragment taskFragment1 = createTaskFragmentWithActivity(parentTask);
- final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
-
- final TaskFragment taskFragment2 = createTaskFragmentWithActivity(parentTask);
- final ActivityRecord activity2 = taskFragment2.getTopMostActivity();
- activity2.setVisible(true);
- activity2.setVisibleRequested(false);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Promote animation targets up to TaskFragment level, not beyond.
- assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(new ArraySet<>(new WindowContainer[]{taskFragment2}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_openingTheOnlyTaskFragmentInTask() {
- // [DefaultTDA] -+- [Task1] - [TaskFragment1] - [ActivityRecord1] (opening, invisible)
- // +- [Task2] - [ActivityRecord2] (closing, visible)
- final Task task1 = createTask(mDisplayContent);
- final TaskFragment taskFragment1 = createTaskFragmentWithActivity(task1);
- final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
- activity2.setVisible(true);
- activity2.setVisibleRequested(false);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Promote animation targets up to leaf Task level because there's only one TaskFragment in
- // the Task.
- assertEquals(new ArraySet<>(new WindowContainer[]{task1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_closingTheOnlyTaskFragmentInTask() {
- // [DefaultTDA] -+- [Task1] - [TaskFragment1] - [ActivityRecord1] (closing, visible)
- // +- [Task2] - [ActivityRecord2] (opening, invisible)
- final Task task1 = createTask(mDisplayContent);
- final TaskFragment taskFragment1 = createTaskFragmentWithActivity(task1);
- final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
- activity1.setVisible(true);
- activity1.setVisibleRequested(false);
-
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
- activity2.setVisible(false);
- activity2.setVisibleRequested(true);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity2);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity1);
-
- // Promote animation targets up to leaf Task level because there's only one TaskFragment in
- // the Task.
- assertEquals(new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(new ArraySet<>(new WindowContainer[]{task1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
- public void testGetAnimationTargets_embeddedTask() {
- // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, invisible)
- // +- [Task2] (embedded) - [ActivityRecord2] (opening, invisible)
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
-
- final Task task2 = createTask(mDisplayContent);
- task2.mRemoveWithTaskOrganizer = true;
- final ActivityRecord activity2 = createActivityRecord(task2);
- activity2.setVisible(false);
- activity2.setVisibleRequested(true);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- opening.add(activity2);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
-
- // No animation on the embedded task.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1.getTask()}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
-
- @Test
- public void testGetAnimationTargets_activityInEmbeddedTask() {
- // [DisplayContent] - [Task] (embedded)-+- [ActivityRecord1] (opening, invisible)
- // +- [ActivityRecord2] (closing, visible)
- final Task task = createTask(mDisplayContent);
- task.mRemoveWithTaskOrganizer = true;
-
- final ActivityRecord activity1 = createActivityRecord(task);
- activity1.setVisible(false);
- activity1.setVisibleRequested(true);
- final ActivityRecord activity2 = createActivityRecord(task);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Even though embedded task itself doesn't animate, activities in an embedded task
- // animate.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- static class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
- private IRemoteAnimationFinishedCallback mFinishedCallback;
-
- @Override
- public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
- IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
- mFinishedCallback = finishedCallback;
- }
-
- @Override
- public void onAnimationCancelled() throws RemoteException {
- mFinishedCallback = null;
- }
-
- @Override
- public IBinder asBinder() {
- return new Binder();
- }
-
- boolean isAnimationStarted() {
- return mFinishedCallback != null;
- }
-
- void finishAnimation() {
- try {
- mFinishedCallback.onAnimationFinished();
- } catch (RemoteException e) {
- fail();
- }
- }
- }
-
- @Test
- public void testGetRemoteAnimationOverrideEmpty() {
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- assertNull(mAppTransitionController.getRemoteAnimationOverride(activity,
- TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- }
-
- @Test
- public void testGetRemoteAnimationOverrideWindowContainer() {
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter);
- activity.registerRemoteAnimations(definition);
-
- assertEquals(adapter,
- mAppTransitionController.getRemoteAnimationOverride(
- activity, TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- assertNull(mAppTransitionController.getRemoteAnimationOverride(
- null, TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- }
-
- @Test
- public void testGetRemoteAnimationOverrideTransitionController() {
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter);
- mAppTransitionController.registerRemoteAnimations(definition);
-
- assertEquals(adapter,
- mAppTransitionController.getRemoteAnimationOverride(
- activity, TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- assertEquals(adapter,
- mAppTransitionController.getRemoteAnimationOverride(
- null, TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- }
-
- @Test
- public void testGetRemoteAnimationOverrideBoth() {
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final RemoteAnimationDefinition definition1 = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter1 = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition1.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter1);
- activity.registerRemoteAnimations(definition1);
-
- final RemoteAnimationDefinition definition2 = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter2 = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition2.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_UNOCCLUDE, adapter2);
- mAppTransitionController.registerRemoteAnimations(definition2);
-
- assertEquals(adapter2,
- mAppTransitionController.getRemoteAnimationOverride(
- activity, TRANSIT_OLD_KEYGUARD_UNOCCLUDE, new ArraySet<Integer>()));
- assertEquals(adapter2,
- mAppTransitionController.getRemoteAnimationOverride(
- null, TRANSIT_OLD_KEYGUARD_UNOCCLUDE, new ArraySet<Integer>()));
- }
-
- @Test
- public void testGetRemoteAnimationOverrideWindowContainerHasPriority() {
- final ActivityRecord activity = createActivityRecord(mDisplayContent);
- final RemoteAnimationDefinition definition1 = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter1 = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition1.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter1);
- activity.registerRemoteAnimations(definition1);
-
- final RemoteAnimationDefinition definition2 = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter adapter2 = new RemoteAnimationAdapter(
- new TestRemoteAnimationRunner(), 10, 1);
- definition2.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, adapter2);
- mAppTransitionController.registerRemoteAnimations(definition2);
-
- assertEquals(adapter1,
- mAppTransitionController.getRemoteAnimationOverride(
- activity, TRANSIT_OLD_ACTIVITY_OPEN, new ArraySet<Integer>()));
- }
-
- @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);
- waitUntilWindowAnimatorIdle();
-
- // 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 */);
- waitUntilWindowAnimatorIdle();
-
- // 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 */);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- waitUntilWindowAnimatorIdle();
-
- // 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);
- final TaskFragment changeTaskFragment =
- createTaskFragmentWithEmbeddedActivity(task, organizer);
- final TaskFragment emptyTaskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .setOrganizer(organizer)
- .build();
- prepareActivityForAppTransition(changeTaskFragment.getTopMostActivity());
- spyOn(mDisplayContent.mAppTransition);
- spyOn(emptyTaskFragment);
-
- prepareAndTriggerAppTransition(
- null /* openingActivity */, null /* closingActivity*/, changeTaskFragment);
-
- // Transition not ready because there is an empty non-finishing TaskFragment.
- verify(mDisplayContent.mAppTransition, never()).goodToGo(anyInt(), any());
-
- doReturn(true).when(emptyTaskFragment).hasChild();
- emptyTaskFragment.remove(false /* withTransition */, "test");
-
- mDisplayContent.mAppTransitionController.handleAppTransitionReady();
-
- // Transition ready because the empty (no running activity) TaskFragment is requested to be
- // removed.
- verify(mDisplayContent.mAppTransition).goodToGo(anyInt(), any());
- }
-
- @Test
- public void testTransitionGoodToGoForTaskFragments_detachedApp() {
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final ITaskFragmentOrganizer iOrganizer = getITaskFragmentOrganizer(organizer);
- registerTaskFragmentOrganizer(iOrganizer);
- final Task task = createTask(mDisplayContent);
- final TaskFragment changeTaskFragment =
- createTaskFragmentWithEmbeddedActivity(task, organizer);
- final TaskFragment emptyTaskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .setOrganizer(organizer)
- .build();
- prepareActivityForAppTransition(changeTaskFragment.getTopMostActivity());
- // To make sure that having a detached activity won't cause any issue.
- final ActivityRecord detachedActivity = createActivityRecord(task);
- detachedActivity.removeImmediately();
- assertNull(detachedActivity.getRootTask());
- spyOn(mDisplayContent.mAppTransition);
- spyOn(emptyTaskFragment);
-
- prepareAndTriggerAppTransition(
- null /* openingActivity */, detachedActivity, changeTaskFragment);
-
- // Transition not ready because there is an empty non-finishing TaskFragment.
- verify(mDisplayContent.mAppTransition, never()).goodToGo(anyInt(), any());
-
- doReturn(true).when(emptyTaskFragment).hasChild();
- emptyTaskFragment.remove(false /* withTransition */, "test");
-
- mDisplayContent.mAppTransitionController.handleAppTransitionReady();
-
- // Transition ready because the empty (no running activity) TaskFragment is requested to be
- // removed.
- 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());
- }
-
- private void prepareAndTriggerAppTransition(@Nullable ActivityRecord openingActivity,
- @Nullable ActivityRecord closingActivity, @Nullable TaskFragment changingTaskFragment) {
- if (openingActivity != null) {
- mDisplayContent.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0);
- mDisplayContent.mOpeningApps.add(openingActivity);
- }
- if (closingActivity != null) {
- mDisplayContent.mAppTransition.prepareAppTransition(TRANSIT_CLOSE, 0);
- mDisplayContent.mClosingApps.add(closingActivity);
- }
- if (changingTaskFragment != null) {
- mDisplayContent.mAppTransition.prepareAppTransition(TRANSIT_CHANGE, 0);
- mDisplayContent.mChangingContainers.add(changingTaskFragment);
- }
- mDisplayContent.mAppTransitionController.handleAppTransitionReady();
- }
-
- private static void prepareActivityForAppTransition(ActivityRecord activity) {
- // Transition will wait until all participated activities to be drawn.
- activity.allDrawn = true;
- // Skip manipulate the SurfaceControl.
- doNothing().when(activity).setDropInputMode(anyInt());
- // Assume the activity contains a window.
- doReturn(true).when(activity).hasChild();
- // Make sure activity can create remote animation target.
- doReturn(mock(RemoteAnimationTarget.class)).when(activity).createRemoteAnimationTarget(
- any());
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
deleted file mode 100644
index 8553fbd30ab8..000000000000
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (C) 2016 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 com.android.server.wm;
-
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-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_FLAG_APP_CRASHED;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
-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_UNSET;
-import static android.view.WindowManager.TRANSIT_OPEN;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
-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.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-import android.util.ArraySet;
-import android.view.Display;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationTarget;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.view.animation.Animation;
-import android.window.ITaskFragmentOrganizer;
-import android.window.TaskFragmentOrganizer;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.policy.TransitionAnimation;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test class for {@link AppTransition}.
- *
- * Build/Install/Run:
- * atest WmTests:AppTransitionTests
- */
-@SmallTest
-@Presubmit
-@RunWith(WindowTestRunner.class)
-public class AppTransitionTests extends WindowTestsBase {
- private DisplayContent mDc;
-
- @Before
- public void setUp() throws Exception {
- doNothing().when(mWm.mRoot).performSurfacePlacement();
- mDc = mWm.getDefaultDisplayContentLocked();
- }
-
- @Test
- public void testKeyguardOverride() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_OCCLUDE);
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY);
- mDc.mOpeningApps.add(activity);
- assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testKeyguardUnoccludeOcclude() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE);
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_OCCLUDE);
- mDc.mOpeningApps.add(activity);
- assertEquals(TRANSIT_NONE,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
-
- }
-
- @Test
- public void testKeyguardKeep() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY);
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.mOpeningApps.add(activity);
- assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testCrashing() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.prepareAppTransition(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
- mDc.mClosingApps.add(activity);
- assertEquals(TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testKeepKeyguard_withCrashing() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY);
- mDc.prepareAppTransition(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
- mDc.mClosingApps.add(activity);
- assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testSkipTransitionAnimation() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- final ActivityRecord activity = createActivityRecord(dc);
-
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.prepareAppTransition(TRANSIT_CLOSE);
- mDc.mClosingApps.add(activity);
- assertEquals(TRANSIT_OLD_UNSET,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, true /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testTaskChangeWindowingMode() {
- final ActivityRecord activity = createActivityRecord(mDc);
-
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.prepareAppTransition(TRANSIT_CHANGE);
- mDc.mOpeningApps.add(activity); // Make sure TRANSIT_CHANGE has the priority
- mDc.mChangingContainers.add(activity.getTask());
-
- assertEquals(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testTaskFragmentChange() {
- final ActivityRecord activity = createActivityRecord(mDc);
- final TaskFragment taskFragment = new TaskFragment(mAtm, new Binder(),
- true /* createdByOrganizer */, true /* isEmbedded */);
- activity.getTask().addChild(taskFragment, POSITION_TOP);
- activity.reparent(taskFragment, POSITION_TOP);
-
- mDc.prepareAppTransition(TRANSIT_OPEN);
- mDc.prepareAppTransition(TRANSIT_CHANGE);
- mDc.mOpeningApps.add(activity); // Make sure TRANSIT_CHANGE has the priority
- mDc.mChangingContainers.add(taskFragment);
-
- assertEquals(TRANSIT_OLD_TASK_FRAGMENT_CHANGE,
- AppTransitionController.getTransitCompatType(mDc.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /*skipAppTransitionAnimation*/));
- }
-
- @Test
- public void testTaskFragmentOpeningTransition() {
- final ActivityRecord activity = createHierarchyForTaskFragmentTest();
- activity.setVisible(false);
-
- mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
- mDisplayContent.mOpeningApps.add(activity);
- assertEquals(TRANSIT_OLD_TASK_FRAGMENT_OPEN,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /* skipAppTransitionAnimation */));
- }
-
- @Test
- public void testTaskFragmentClosingTransition() {
- final ActivityRecord activity = createHierarchyForTaskFragmentTest();
- activity.setVisible(true);
-
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
- mDisplayContent.mClosingApps.add(activity);
- assertEquals(TRANSIT_OLD_TASK_FRAGMENT_CLOSE,
- AppTransitionController.getTransitCompatType(mDisplayContent.mAppTransition,
- mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
- mDisplayContent.mChangingContainers, null /* wallpaperTarget */,
- null /* oldWallpaper */, false /* skipAppTransitionAnimation */));
- }
-
- /**
- * Creates a {@link Task} with two {@link TaskFragment TaskFragments}.
- * The bottom TaskFragment is to prevent
- * {@link AppTransitionController#getAnimationTargets(ArraySet, ArraySet, boolean) the animation
- * target} to promote to Task or above.
- *
- * @return The Activity to be put in either opening or closing Activity
- */
- private ActivityRecord createHierarchyForTaskFragmentTest() {
- final Task parentTask = createTask(mDisplayContent);
- final TaskFragment bottomTaskFragment = createTaskFragmentWithActivity(parentTask);
- final ActivityRecord bottomActivity = bottomTaskFragment.getTopMostActivity();
- bottomActivity.setOccludesParent(true);
- bottomActivity.setVisible(true);
-
- final TaskFragment verifiedTaskFragment = createTaskFragmentWithActivity(parentTask);
- final ActivityRecord activity = verifiedTaskFragment.getTopMostActivity();
- activity.setOccludesParent(true);
-
- return activity;
- }
-
- @Test
- public void testAppTransitionStateForMultiDisplay() {
- // Create 2 displays & presume both display the state is ON for ready to display & animate.
- final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
- final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
-
- // Create 2 app window tokens to represent 2 activity window.
- final ActivityRecord activity1 = createActivityRecord(dc1);
- final ActivityRecord activity2 = createActivityRecord(dc2);
-
- activity1.allDrawn = true;
- activity1.startingMoved = true;
-
- // Simulate activity resume / finish flows to prepare app transition & set visibility,
- // make sure transition is set as expected for each display.
- dc1.prepareAppTransition(TRANSIT_OPEN);
- dc2.prepareAppTransition(TRANSIT_CLOSE);
- // One activity window is visible for resuming & the other activity window is invisible
- // for finishing in different display.
- activity1.setVisibility(true);
- activity2.setVisibility(false);
-
- // Make sure each display is in animating stage.
- assertTrue(dc1.mOpeningApps.size() > 0);
- assertTrue(dc2.mClosingApps.size() > 0);
- assertTrue(dc1.isAppTransitioning());
- assertTrue(dc2.isAppTransitioning());
- }
-
- @Test
- public void testCleanAppTransitionWhenRootTaskReparent() {
- // Create 2 displays & presume both display the state is ON for ready to display & animate.
- final DisplayContent dc1 = createNewDisplay(Display.STATE_ON);
- final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
-
- final Task rootTask1 = createTask(dc1);
- final Task task1 = createTaskInRootTask(rootTask1, 0 /* userId */);
- final ActivityRecord activity1 = createNonAttachedActivityRecord(dc1);
- task1.addChild(activity1, 0);
-
- // Simulate same app is during opening / closing transition set stage.
- dc1.mClosingApps.add(activity1);
- assertTrue(dc1.mClosingApps.size() > 0);
-
- dc1.prepareAppTransition(TRANSIT_OPEN);
- assertTrue(dc1.mAppTransition.containsTransitRequest(TRANSIT_OPEN));
- assertTrue(dc1.mAppTransition.isTransitionSet());
-
- dc1.mOpeningApps.add(activity1);
- assertTrue(dc1.mOpeningApps.size() > 0);
-
- // Move root task to another display.
- rootTask1.reparent(dc2.getDefaultTaskDisplayArea(), true);
-
- // Verify if token are cleared from both pending transition list in former display.
- assertFalse(dc1.mOpeningApps.contains(activity1));
- assertFalse(dc1.mOpeningApps.contains(activity1));
- }
-
- @Test
- public void testLoadAnimationSafely() {
- DisplayContent dc = createNewDisplay(Display.STATE_ON);
- assertNull(dc.mAppTransition.loadAnimationSafely(
- getInstrumentation().getTargetContext(), -1));
- }
-
- @Test
- public void testCancelRemoteAnimationWhenFreeze() {
- final DisplayContent dc = createNewDisplay(Display.STATE_ON);
- doReturn(false).when(dc).onDescendantOrientationChanged(any());
- final WindowState exitingAppWindow = newWindowBuilder("exiting app",
- TYPE_BASE_APPLICATION).setDisplay(dc).build();
- final ActivityRecord exitingActivity = exitingAppWindow.mActivityRecord;
- // Wait until everything in animation handler get executed to prevent the exiting window
- // from being removed during WindowSurfacePlacer Traversal.
- waitUntilHandlersIdle();
-
- // Set a remote animator.
- final TestRemoteAnimationRunner runner = new TestRemoteAnimationRunner();
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- runner, 100, 50, true /* changeNeedsSnapshot */);
- // RemoteAnimationController will tracking RemoteAnimationAdapter's caller with calling pid.
- adapter.setCallingPidUid(123, 456);
-
- // Simulate activity finish flows to prepare app transition & set visibility,
- // make sure transition is set as expected.
- dc.prepareAppTransition(TRANSIT_CLOSE);
- assertTrue(dc.mAppTransition.containsTransitRequest(TRANSIT_CLOSE));
- dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
- exitingActivity.setVisibility(false);
- assertTrue(dc.mClosingApps.size() > 0);
-
- // Make sure window is in animating stage before freeze, and cancel after freeze.
- assertTrue(dc.isAppTransitioning());
- assertFalse(runner.mCancelled);
- dc.mAppTransition.freeze();
- assertFalse(dc.isAppTransitioning());
- assertTrue(runner.mCancelled);
- }
-
- @Test
- public void testGetAnimationStyleResId() {
- // Verify getAnimationStyleResId will return as LayoutParams.windowAnimations when without
- // specifying window type.
- final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
- attrs.windowAnimations = 0x12345678;
- assertEquals(attrs.windowAnimations, mDc.mAppTransition.getAnimationStyleResId(attrs));
-
- // Verify getAnimationStyleResId will return system resource Id when the window type is
- // starting window.
- attrs.type = TYPE_APPLICATION_STARTING;
- assertEquals(mDc.mAppTransition.getDefaultWindowAnimationStyleResId(),
- mDc.mAppTransition.getAnimationStyleResId(attrs));
- }
-
- @Test
- public void testActivityRecordReparentedToTaskFragment() {
- final ActivityRecord activity = createActivityRecord(mDc);
- final SurfaceControl activityLeash = mock(SurfaceControl.class);
- doNothing().when(activity).setDropInputMode(anyInt());
- activity.setVisibility(true);
- activity.setSurfaceControl(activityLeash);
- final Task task = activity.getTask();
-
- // Add a TaskFragment of half of the Task size.
- final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run);
- final ITaskFragmentOrganizer iOrganizer =
- ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder());
- registerTaskFragmentOrganizer(iOrganizer);
- final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
- .setParentTask(task)
- .setOrganizer(organizer)
- .build();
- final Rect taskBounds = new Rect();
- task.getBounds(taskBounds);
- taskFragment.setBounds(0, 0, taskBounds.right / 2, taskBounds.bottom);
- spyOn(taskFragment);
-
- assertTrue(mDc.mChangingContainers.isEmpty());
- assertFalse(mDc.mAppTransition.isTransitionSet());
-
- // Schedule app transition when reparent activity to a TaskFragment of different size.
- final Rect startBounds = new Rect(activity.getBounds());
- activity.reparent(taskFragment, POSITION_TOP);
-
- // It should transit at TaskFragment level with snapshot on the activity surface.
- verify(taskFragment).initializeChangeTransition(activity.getBounds(), activityLeash);
- assertTrue(mDc.mChangingContainers.contains(taskFragment));
- assertTrue(mDc.mAppTransition.containsTransitRequest(TRANSIT_CHANGE));
- }
-
- @Test
- public void testGetNextAppTransitionBackgroundColor() {
- assumeFalse(WindowManagerService.sEnableShellTransitions);
-
- // No override by default.
- assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor());
-
- // Override with a custom color.
- mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0);
- final int testColor = 123;
- mDc.mAppTransition.overridePendingAppTransition("testPackage", 0 /* enterAnim */,
- 0 /* exitAnim */, testColor, null /* startedCallback */, null /* endedCallback */,
- false /* overrideTaskTransaction */);
-
- assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor());
- assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested());
-
- // Override with ActivityEmbedding remote animation. Background color should be kept.
- mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class),
- false /* sync */, true /* isActivityEmbedding */);
-
- assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor());
- assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested());
-
- // Background color should not be cleared anymore after #clear().
- mDc.mAppTransition.clear();
- assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor());
- assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested());
- }
-
- @Test
- public void testGetNextAppRequestedAnimation() {
- assumeFalse(WindowManagerService.sEnableShellTransitions);
- final String packageName = "testPackage";
- final int enterAnimResId = 1;
- final int exitAnimResId = 2;
- final int testColor = 123;
- final Animation enterAnim = mock(Animation.class);
- final Animation exitAnim = mock(Animation.class);
- final TransitionAnimation transitionAnimation = mDc.mAppTransition.mTransitionAnimation;
- spyOn(transitionAnimation);
- doReturn(enterAnim).when(transitionAnimation)
- .loadAppTransitionAnimation(packageName, enterAnimResId);
- doReturn(exitAnim).when(transitionAnimation)
- .loadAppTransitionAnimation(packageName, exitAnimResId);
-
- // No override by default.
- assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */));
- assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */));
-
- // Override with a custom animation.
- mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0);
- mDc.mAppTransition.overridePendingAppTransition(packageName, enterAnimResId, exitAnimResId,
- testColor, null /* startedCallback */, null /* endedCallback */,
- false /* overrideTaskTransaction */);
-
- assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */));
- assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */));
- assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested());
-
- // Override with ActivityEmbedding remote animation. Custom animation should be kept.
- mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class),
- false /* sync */, true /* isActivityEmbedding */);
-
- assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */));
- assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */));
- assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested());
-
- // Custom animation should not be cleared anymore after #clear().
- mDc.mAppTransition.clear();
- assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */));
- assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */));
- }
-
- private class TestRemoteAnimationRunner implements IRemoteAnimationRunner {
- boolean mCancelled = false;
- @Override
- public void onAnimationStart(@WindowManager.TransitionOldType int transit,
- RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers,
- RemoteAnimationTarget[] nonApps,
- IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
- }
-
- @Override
- public void onAnimationCancelled() {
- mCancelled = true;
- }
-
- @Override
- public IBinder asBinder() {
- return null;
- }
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 0964ebed9d25..82435b24dad6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1172,11 +1172,12 @@ public class DisplayContentTests extends WindowTestsBase {
.setScreenOrientation(getRotatedOrientation(mDisplayContent)).build();
prev.setVisibleRequested(false);
final ActivityRecord top = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setVisible(false)
.setScreenOrientation(SCREEN_ORIENTATION_BEHIND).build();
assertNotEquals(WindowConfiguration.ROTATION_UNDEFINED,
mDisplayContent.rotationForActivityInDifferentOrientation(top));
- mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0);
+ requestTransition(top, WindowManager.TRANSIT_OPEN);
top.setVisibility(true);
mDisplayContent.updateOrientation();
// The top uses "behind", so the orientation is decided by the previous.
@@ -1609,8 +1610,7 @@ public class DisplayContentTests extends WindowTestsBase {
final ActivityRecord app = mAppWindow.mActivityRecord;
app.setVisible(false);
app.setVisibleRequested(false);
- registerTestTransitionPlayer();
- mDisplayContent.requestTransitionAndLegacyPrepare(WindowManager.TRANSIT_OPEN, 0);
+ requestTransition(app, WindowManager.TRANSIT_OPEN);
app.setVisibility(true);
final int newOrientation = getRotatedOrientation(mDisplayContent);
app.setRequestedOrientation(newOrientation);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index fc4f54a431d6..e4a1bf603cf0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -454,31 +454,6 @@ public class RootWindowContainerTests extends WindowTestsBase {
}
@Test
- public void testMovingBottomMostRootTaskActivityToPinnedRootTask() {
- final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
- .setTask(fullscreenTask).build();
- final Task task = firstActivity.getTask();
-
- final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
- .setTask(fullscreenTask).build();
-
- fullscreenTask.moveTaskToBack(task);
-
- // Ensure full screen task has both tasks.
- ensureTaskPlacement(fullscreenTask, firstActivity, secondActivity);
- assertEquals(task.getTopMostActivity(), secondActivity);
- firstActivity.setState(STOPPED, "testMovingBottomMostRootTaskActivityToPinnedRootTask");
-
-
- // Move first activity to pinned root task.
- mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity, "initialMove");
-
- assertTrue(firstActivity.mRequestForceTransition);
- }
-
- @Test
public void testMultipleActivitiesTaskEnterPip() {
// Enable shell transition because the order of setting windowing mode is different.
registerTestTransitionPlayer();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index dba463a436c0..95bca2b17efb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1811,9 +1811,9 @@ public class SizeCompatTests extends WindowTestsBase {
}
addStatusBar(mActivity.mDisplayContent);
- mActivity.setVisible(false);
- mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_OPEN);
- mActivity.mDisplayContent.mOpeningApps.add(mActivity);
+ mActivity.setVisibleRequested(false);
+ requestTransition(mActivity, WindowManager.TRANSIT_OPEN);
+ mActivity.setVisibility(true);
final float maxAspect = 1.8f;
prepareUnresizable(mActivity, maxAspect, SCREEN_ORIENTATION_LANDSCAPE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 001446550304..edffab801499 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -32,8 +32,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -85,12 +83,8 @@ import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.util.ArraySet;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationRunner;
import android.view.InsetsFrameProvider;
import android.view.InsetsSource;
-import android.view.RemoteAnimationAdapter;
-import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowInsets;
@@ -1055,25 +1049,6 @@ public class WindowContainerTests extends WindowTestsBase {
}
@Test
- public void testTaskCanApplyAnimation() {
- final Task rootTask = createTask(mDisplayContent);
- final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent, task);
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent, task);
- verifyWindowContainerApplyAnimation(task, activity1, activity2);
- }
-
- @Test
- public void testRootTaskCanApplyAnimation() {
- final Task rootTask = createTask(mDisplayContent);
- final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
- createTaskInRootTask(rootTask, 0 /* userId */));
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
- createTaskInRootTask(rootTask, 0 /* userId */));
- verifyWindowContainerApplyAnimation(rootTask, activity1, activity2);
- }
-
- @Test
public void testGetDisplayArea() {
// WindowContainer
final WindowContainer windowContainer = new WindowContainer(mWm);
@@ -1103,59 +1078,6 @@ public class WindowContainerTests extends WindowTestsBase {
assertEquals(displayArea, displayArea.getDisplayArea());
}
- private void verifyWindowContainerApplyAnimation(WindowContainer wc, ActivityRecord act,
- ActivityRecord act2) {
- // Initial remote animation for app transition.
- final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
- new IRemoteAnimationRunner.Stub() {
- @Override
- public void onAnimationStart(@WindowManager.TransitionOldType int transit,
- RemoteAnimationTarget[] apps,
- RemoteAnimationTarget[] wallpapers,
- RemoteAnimationTarget[] nonApps,
- IRemoteAnimationFinishedCallback finishedCallback) {
- try {
- finishedCallback.onAnimationFinished();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onAnimationCancelled() {
- }
- }, 0, 0, false);
- adapter.setCallingPidUid(123, 456);
- wc.getDisplayContent().prepareAppTransition(TRANSIT_OPEN);
- wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
- spyOn(wc);
- doReturn(true).when(wc).okToAnimate();
-
- // Make sure animating state is as expected after applied animation.
-
- // Animation target is promoted from act to wc. act2 is a descendant of wc, but not a source
- // of the animation.
- ArrayList<WindowContainer<WindowState>> sources = new ArrayList<>();
- sources.add(act);
- assertTrue(wc.applyAnimation(null, TRANSIT_OLD_TASK_OPEN, true, false, sources));
-
- assertEquals(act, wc.getTopMostActivity());
- assertTrue(wc.isAnimating());
- assertTrue(wc.isAnimating(0, ANIMATION_TYPE_APP_TRANSITION));
- assertTrue(wc.getAnimationSources().contains(act));
- assertFalse(wc.getAnimationSources().contains(act2));
- assertTrue(act.isAnimating(PARENTS));
- assertTrue(act.isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
- assertEquals(wc, act.getAnimatingContainer(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
-
- // Make sure animation finish callback will be received and reset animating state after
- // animation finish.
- wc.getDisplayContent().mAppTransition.goodToGo(TRANSIT_OLD_TASK_OPEN, act);
- verify(wc).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), any());
- assertFalse(wc.isAnimating());
- assertFalse(act.isAnimating(PARENTS));
- }
-
@Test
public void testRegisterWindowContainerListener() {
final WindowContainer container = new WindowContainer(mWm);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b16f5283d532..7f9e591ca5e3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -961,6 +961,15 @@ public class WindowTestsBase extends SystemServiceTestsBase {
return testPlayer;
}
+ void requestTransition(WindowContainer<?> wc, int transit) {
+ final TransitionController controller = mRootWindowContainer.mTransitionController;
+ if (controller.getTransitionPlayer() == null) {
+ registerTestTransitionPlayer();
+ }
+ controller.requestTransitionIfNeeded(transit, 0 /* flags */, null /* trigger */,
+ wc.mDisplayContent);
+ }
+
/** Overrides the behavior of config_reverseDefaultRotation for the given display. */
void setReverseDefaultRotation(DisplayContent dc, boolean reverse) {
final DisplayRotation displayRotation = dc.getDisplayRotation();
@@ -1417,7 +1426,9 @@ public class WindowTestsBase extends SystemServiceTestsBase {
activity.setProcess(wpc);
// Resume top activities to make sure all other signals in the system are connected.
- mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
+ if (mVisible) {
+ mService.mRootWindowContainer.resumeFocusedTasksTopActivities();
+ }
return activity;
}
}