Generalize back animation and transition sequence...
for both shell and legacy transition system. The general sequence will be: 1. Create animation leash in core, pass to remote animation runner. 2. Remote animation finish, collect finish transaction before transition happen. Apply finish transaction here if back event won't trigger. 3. Check whether next transition is triggered from back gesture via checking the open/close targets. The 3rd step introduce another change, which to let the back transition happen. Instead of consume next transition, we should try to find out whether the participant was the animation target, because we cannot assume what the opening target will do in resume stage. For example, the opening activity could finish itself, or start another activity at onResume, so in either case, the opening activity will become closing activity. We can only ensure that activity will participant in next transition. So the more robust way should be, find out those targets which were animated. For shell transition, and add a flag to the corresponding change, then the transition handler can determine what to do based on the targets. For legacy transition, ignore those targets when estimate the transition type in AppTransitionController#getTransitCompatType. Bug: 238474994 Bug: 131727607 Test: varify transition can be handled for some unexpected scenario: 1. launch new activity when close app. 2. launch singleInstance activity when close app. Test: do back gesture on both shell/legacy transiton system, verify no flicker happen whenever the back is triggered. Change-Id: I9364be25c608f7b5797577d26b57bc7d6f2dde9c
This commit is contained in:
@@ -89,8 +89,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
@Nullable
|
||||
private final IOnBackInvokedCallback mOnBackInvokedCallback;
|
||||
private final boolean mPrepareRemoteAnimation;
|
||||
@Nullable
|
||||
private WindowContainerToken mDepartingWindowContainerToken;
|
||||
|
||||
/**
|
||||
* Create a new {@link BackNavigationInfo} instance.
|
||||
@@ -100,20 +98,15 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
* back preview.
|
||||
* @param onBackInvokedCallback The back callback registered by the current top level window.
|
||||
* @param departingWindowContainerToken The {@link WindowContainerToken} of departing window.
|
||||
* @param isPrepareRemoteAnimation Return whether the core is preparing a back gesture
|
||||
* animation, if true, the caller of startBackNavigation should
|
||||
* be expected to receive an animation start callback.
|
||||
*/
|
||||
private BackNavigationInfo(@BackTargetType int type,
|
||||
@Nullable RemoteCallback onBackNavigationDone,
|
||||
@Nullable IOnBackInvokedCallback onBackInvokedCallback,
|
||||
boolean isPrepareRemoteAnimation,
|
||||
@Nullable WindowContainerToken departingWindowContainerToken) {
|
||||
boolean isPrepareRemoteAnimation) {
|
||||
mType = type;
|
||||
mOnBackNavigationDone = onBackNavigationDone;
|
||||
mOnBackInvokedCallback = onBackInvokedCallback;
|
||||
mPrepareRemoteAnimation = isPrepareRemoteAnimation;
|
||||
mDepartingWindowContainerToken = departingWindowContainerToken;
|
||||
}
|
||||
|
||||
private BackNavigationInfo(@NonNull Parcel in) {
|
||||
@@ -121,7 +114,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
|
||||
mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
|
||||
mPrepareRemoteAnimation = in.readBoolean();
|
||||
mDepartingWindowContainerToken = in.readTypedObject(WindowContainerToken.CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,7 +122,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
dest.writeTypedObject(mOnBackNavigationDone, flags);
|
||||
dest.writeStrongInterface(mOnBackInvokedCallback);
|
||||
dest.writeBoolean(mPrepareRemoteAnimation);
|
||||
dest.writeTypedObject(mDepartingWindowContainerToken, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,18 +154,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
return mPrepareRemoteAnimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link WindowContainerToken} of the highest container in the hierarchy being
|
||||
* removed.
|
||||
* <p>
|
||||
* For example, if an Activity is the last one of its Task, the Task's token will be given.
|
||||
* Otherwise, it will be the Activity's token.
|
||||
*/
|
||||
@Nullable
|
||||
public WindowContainerToken getDepartingWindowContainerToken() {
|
||||
return mDepartingWindowContainerToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be called when the back preview is finished in order to notify the server that
|
||||
* it can clean up the resources created for the animation.
|
||||
@@ -212,7 +191,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
+ "mType=" + typeToString(mType) + " (" + mType + ")"
|
||||
+ ", mOnBackNavigationDone=" + mOnBackNavigationDone
|
||||
+ ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
|
||||
+ ", mWindowContainerToken=" + mDepartingWindowContainerToken
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@@ -248,8 +226,6 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
@Nullable
|
||||
private IOnBackInvokedCallback mOnBackInvokedCallback = null;
|
||||
private boolean mPrepareRemoteAnimation;
|
||||
@Nullable
|
||||
private WindowContainerToken mDepartingWindowContainerToken = null;
|
||||
|
||||
/**
|
||||
* @see BackNavigationInfo#getType()
|
||||
@@ -284,21 +260,13 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BackNavigationInfo#getDepartingWindowContainerToken()
|
||||
*/
|
||||
public void setDepartingWCT(@NonNull WindowContainerToken windowContainerToken) {
|
||||
mDepartingWindowContainerToken = windowContainerToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns an instance of {@link BackNavigationInfo}
|
||||
*/
|
||||
public BackNavigationInfo build() {
|
||||
return new BackNavigationInfo(mType, mOnBackNavigationDone,
|
||||
mOnBackInvokedCallback,
|
||||
mPrepareRemoteAnimation,
|
||||
mDepartingWindowContainerToken);
|
||||
mPrepareRemoteAnimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +138,11 @@ public final class TransitionInfo implements Parcelable {
|
||||
/** The container is a system window, excluding wallpaper and input-method. */
|
||||
public static final int FLAG_IS_SYSTEM_WINDOW = 1 << 16;
|
||||
|
||||
/** The window was animated by back gesture. */
|
||||
public static final int FLAG_BACK_GESTURE_ANIMATED = 1 << 17;
|
||||
|
||||
/** The first unused bit. This can be used by remotes to attach custom flags to this change. */
|
||||
public static final int FLAG_FIRST_CUSTOM = 1 << 17;
|
||||
public static final int FLAG_FIRST_CUSTOM = 1 << 18;
|
||||
|
||||
/** The change belongs to a window that won't contain activities. */
|
||||
public static final int FLAGS_IS_NON_APP_WINDOW =
|
||||
@@ -165,6 +168,7 @@ public final class TransitionInfo implements Parcelable {
|
||||
FLAG_IS_BEHIND_STARTING_WINDOW,
|
||||
FLAG_IS_OCCLUDED,
|
||||
FLAG_IS_SYSTEM_WINDOW,
|
||||
FLAG_BACK_GESTURE_ANIMATED,
|
||||
FLAG_FIRST_CUSTOM
|
||||
})
|
||||
public @interface ChangeFlags {}
|
||||
@@ -380,6 +384,9 @@ public final class TransitionInfo implements Parcelable {
|
||||
if ((flags & FLAG_IS_SYSTEM_WINDOW) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("FLAG_IS_SYSTEM_WINDOW");
|
||||
}
|
||||
if ((flags & FLAG_BACK_GESTURE_ANIMATED) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("FLAG_BACK_GESTURE_ANIMATED");
|
||||
}
|
||||
if ((flags & FLAG_FIRST_CUSTOM) != 0) {
|
||||
sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM");
|
||||
}
|
||||
|
||||
@@ -2173,12 +2173,6 @@
|
||||
"group": "WM_DEBUG_ANIM",
|
||||
"at": "com\/android\/server\/wm\/WindowContainer.java"
|
||||
},
|
||||
"-23020844": {
|
||||
"message": "Back: Reset surfaces",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_BACK_PREVIEW",
|
||||
"at": "com\/android\/server\/wm\/BackNavigationController.java"
|
||||
},
|
||||
"-21399771": {
|
||||
"message": "activity %s already destroying, skipping request with reason:%s",
|
||||
"level": "VERBOSE",
|
||||
@@ -3817,12 +3811,6 @@
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"1544805551": {
|
||||
"message": "Skipping app transition animation. task=%s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_BACK_PREVIEW",
|
||||
"at": "com\/android\/server\/wm\/Task.java"
|
||||
},
|
||||
"1557732761": {
|
||||
"message": "For Intent %s bringing to top: %s",
|
||||
"level": "DEBUG",
|
||||
|
||||
@@ -62,7 +62,6 @@ import com.android.wm.shell.common.annotations.ShellBackgroundThread;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
import com.android.wm.shell.sysui.ShellController;
|
||||
import com.android.wm.shell.sysui.ShellInit;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -82,8 +81,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
SETTING_VALUE_OFF) == SETTING_VALUE_ON;
|
||||
/** Predictive back animation developer option */
|
||||
private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
|
||||
// TODO (b/241808055) Find a appropriate time to remove during refactor
|
||||
private static final boolean ENABLE_SHELL_TRANSITIONS = Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||
/**
|
||||
* Max duration to wait for a transition to finish before accepting another gesture start
|
||||
* request.
|
||||
@@ -121,8 +118,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private final TouchTracker mTouchTracker = new TouchTracker();
|
||||
|
||||
private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>();
|
||||
private final Transitions mTransitions;
|
||||
private BackTransitionHandler mBackTransitionHandler;
|
||||
|
||||
@VisibleForTesting
|
||||
final IWindowFocusObserver mFocusObserver = new IWindowFocusObserver.Stub() {
|
||||
@@ -148,11 +143,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
@NonNull ShellController shellController,
|
||||
@NonNull @ShellMainThread ShellExecutor shellExecutor,
|
||||
@NonNull @ShellBackgroundThread Handler backgroundHandler,
|
||||
Context context,
|
||||
Transitions transitions) {
|
||||
Context context) {
|
||||
this(shellInit, shellController, shellExecutor, backgroundHandler,
|
||||
ActivityTaskManager.getService(), context, context.getContentResolver(),
|
||||
transitions);
|
||||
ActivityTaskManager.getService(), context, context.getContentResolver());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -162,8 +155,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
@NonNull @ShellMainThread ShellExecutor shellExecutor,
|
||||
@NonNull @ShellBackgroundThread Handler bgHandler,
|
||||
@NonNull IActivityTaskManager activityTaskManager,
|
||||
Context context, ContentResolver contentResolver,
|
||||
Transitions transitions) {
|
||||
Context context, ContentResolver contentResolver) {
|
||||
mShellController = shellController;
|
||||
mShellExecutor = shellExecutor;
|
||||
mActivityTaskManager = activityTaskManager;
|
||||
@@ -171,7 +163,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mContentResolver = contentResolver;
|
||||
mBgHandler = bgHandler;
|
||||
shellInit.addInitCallback(this::onInit, this);
|
||||
mTransitions = transitions;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -182,10 +173,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private void onInit() {
|
||||
setupAnimationDeveloperSettingsObserver(mContentResolver, mBgHandler);
|
||||
createAdapter();
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
mBackTransitionHandler = new BackTransitionHandler(this);
|
||||
mTransitions.addHandler(mBackTransitionHandler);
|
||||
}
|
||||
mShellController.addExternalInterface(KEY_EXTRA_SHELL_BACK_ANIMATION,
|
||||
this::createExternalInterface, this);
|
||||
|
||||
@@ -335,17 +322,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
}
|
||||
}
|
||||
|
||||
// In legacy transition, it would use `Task.mBackGestureStarted` in core to handle the
|
||||
// following transition when back callback is invoked.
|
||||
// If the back callback is not invoked, we should reset the token and finish the whole back
|
||||
// navigation without waiting the transition.
|
||||
if (!ENABLE_SHELL_TRANSITIONS) {
|
||||
finishBackNavigation();
|
||||
} else if (!mTriggerBack) {
|
||||
// reset the token to prevent it consume next transition.
|
||||
mBackTransitionHandler.setDepartingWindowContainerToken(null);
|
||||
finishBackNavigation();
|
||||
}
|
||||
finishBackNavigation();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,10 +591,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
return;
|
||||
}
|
||||
mTransitionInProgress = true;
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
mBackTransitionHandler.setDepartingWindowContainerToken(
|
||||
mBackNavigationInfo.getDepartingWindowContainerToken());
|
||||
}
|
||||
mShellExecutor.executeDelayed(mResetTransitionRunnable, MAX_TRANSITION_DURATION);
|
||||
}
|
||||
|
||||
@@ -626,19 +599,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mTransitionInProgress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called from {@link BackTransitionHandler#startAnimation} when the following
|
||||
* transition is triggered by the real back callback in {@link #onBackAnimationFinished}.
|
||||
* Will consume the default transition and finish current back navigation.
|
||||
*/
|
||||
void finishTransition(Transitions.TransitionFinishCallback finishCallback) {
|
||||
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishTransition()");
|
||||
mShellExecutor.execute(() -> {
|
||||
finishBackNavigation();
|
||||
finishCallback.onTransitionFinished(null, null);
|
||||
});
|
||||
}
|
||||
|
||||
private void createAdapter() {
|
||||
IBackAnimationRunner runner = new IBackAnimationRunner.Stub() {
|
||||
@Override
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.wm.shell.back;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.TransitionRequestInfo;
|
||||
import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
class BackTransitionHandler implements Transitions.TransitionHandler {
|
||||
private BackAnimationController mBackAnimationController;
|
||||
private WindowContainerToken mDepartingWindowContainerToken;
|
||||
|
||||
BackTransitionHandler(@NonNull BackAnimationController backAnimationController) {
|
||||
mBackAnimationController = backAnimationController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||
if (mDepartingWindowContainerToken != null) {
|
||||
final TransitionInfo.Change change = info.getChange(mDepartingWindowContainerToken);
|
||||
if (change == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
startTransaction.hide(change.getLeash());
|
||||
startTransaction.apply();
|
||||
mDepartingWindowContainerToken = null;
|
||||
mBackAnimationController.finishTransition(finishCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@NonNull TransitionRequestInfo request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
|
||||
@NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||
}
|
||||
|
||||
void setDepartingWindowContainerToken(
|
||||
@Nullable WindowContainerToken departingWindowContainerToken) {
|
||||
mDepartingWindowContainerToken = departingWindowContainerToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,13 +260,12 @@ public abstract class WMShellBaseModule {
|
||||
ShellInit shellInit,
|
||||
ShellController shellController,
|
||||
@ShellMainThread ShellExecutor shellExecutor,
|
||||
@ShellBackgroundThread Handler backgroundHandler,
|
||||
Transitions transitions
|
||||
@ShellBackgroundThread Handler backgroundHandler
|
||||
) {
|
||||
if (BackAnimationController.IS_ENABLED) {
|
||||
return Optional.of(
|
||||
new BackAnimationController(shellInit, shellController, shellExecutor,
|
||||
backgroundHandler, context, transitions));
|
||||
backgroundHandler, context));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ 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 android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
|
||||
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL;
|
||||
import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
|
||||
import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
|
||||
@@ -395,6 +396,11 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// The back gesture has animated this change before transition happen, so here we don't
|
||||
// play the animation again.
|
||||
if (change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) {
|
||||
continue;
|
||||
}
|
||||
// Don't animate anything that isn't independent.
|
||||
if (!TransitionInfo.isIndependent(change, info)) continue;
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ import com.android.wm.shell.TestShellExecutor;
|
||||
import com.android.wm.shell.sysui.ShellController;
|
||||
import com.android.wm.shell.sysui.ShellInit;
|
||||
import com.android.wm.shell.sysui.ShellSharedConstants;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -102,9 +101,6 @@ public class BackAnimationControllerTest extends ShellTestCase {
|
||||
@Mock
|
||||
private IRemoteAnimationRunner mBackAnimationRunner;
|
||||
|
||||
@Mock
|
||||
private Transitions mTransitions;
|
||||
|
||||
@Mock
|
||||
private ShellController mShellController;
|
||||
|
||||
@@ -127,7 +123,7 @@ public class BackAnimationControllerTest extends ShellTestCase {
|
||||
mController = new BackAnimationController(mShellInit, mShellController,
|
||||
mShellExecutor, new Handler(mTestableLooper.getLooper()),
|
||||
mActivityTaskManager, mContext,
|
||||
mContentResolver, mTransitions);
|
||||
mContentResolver);
|
||||
mController.setEnableUAnimation(true);
|
||||
mShellInit.init();
|
||||
mEventTime = 0;
|
||||
@@ -225,7 +221,7 @@ public class BackAnimationControllerTest extends ShellTestCase {
|
||||
mController = new BackAnimationController(shellInit, mShellController,
|
||||
mShellExecutor, new Handler(mTestableLooper.getLooper()),
|
||||
mActivityTaskManager, mContext,
|
||||
mContentResolver, mTransitions);
|
||||
mContentResolver);
|
||||
shellInit.init();
|
||||
mController.setBackToLauncherCallback(mIOnBackInvokedCallback, mBackAnimationRunner);
|
||||
|
||||
|
||||
@@ -215,9 +215,20 @@ public class AppTransitionController {
|
||||
mWallpaperControllerLocked.adjustWallpaperWindowsForAppTransitionIfNeeded(
|
||||
mDisplayContent.mOpeningApps);
|
||||
|
||||
ArraySet<ActivityRecord> tmpOpenApps = mDisplayContent.mOpeningApps;
|
||||
ArraySet<ActivityRecord> tmpCloseApps = mDisplayContent.mClosingApps;
|
||||
if (mDisplayContent.mAtmService.mBackNavigationController.isWaitBackTransition()) {
|
||||
tmpOpenApps = new ArraySet<>(mDisplayContent.mOpeningApps);
|
||||
tmpCloseApps = new ArraySet<>(mDisplayContent.mClosingApps);
|
||||
if (mDisplayContent.mAtmService.mBackNavigationController
|
||||
.removeIfContainsBackAnimationTargets(tmpOpenApps, tmpCloseApps)) {
|
||||
mDisplayContent.mAtmService.mBackNavigationController.clearBackAnimations(null);
|
||||
}
|
||||
}
|
||||
|
||||
@TransitionOldType final int transit = getTransitCompatType(
|
||||
mDisplayContent.mAppTransition, mDisplayContent.mOpeningApps,
|
||||
mDisplayContent.mClosingApps, mDisplayContent.mChangingContainers,
|
||||
mDisplayContent.mAppTransition, tmpOpenApps,
|
||||
tmpCloseApps, mDisplayContent.mChangingContainers,
|
||||
mWallpaperControllerLocked.getWallpaperTarget(), getOldWallpaper(),
|
||||
mDisplayContent.mSkipAppTransitionAnimation);
|
||||
mDisplayContent.mSkipAppTransitionAnimation = false;
|
||||
@@ -225,22 +236,21 @@ public class AppTransitionController {
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
|
||||
"handleAppTransitionReady: displayId=%d appTransition={%s}"
|
||||
+ " openingApps=[%s] closingApps=[%s] transit=%s",
|
||||
mDisplayContent.mDisplayId, appTransition.toString(), mDisplayContent.mOpeningApps,
|
||||
mDisplayContent.mClosingApps, AppTransition.appTransitionOldToString(transit));
|
||||
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(mDisplayContent.mOpeningApps,
|
||||
mDisplayContent.mClosingApps, mDisplayContent.mChangingContainers);
|
||||
final ArraySet<Integer> activityTypes = collectActivityTypes(tmpOpenApps,
|
||||
tmpCloseApps, mDisplayContent.mChangingContainers);
|
||||
final ActivityRecord animLpActivity = findAnimLayoutParamsToken(transit, activityTypes,
|
||||
mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps,
|
||||
mDisplayContent.mChangingContainers);
|
||||
tmpOpenApps, tmpCloseApps, mDisplayContent.mChangingContainers);
|
||||
final ActivityRecord topOpeningApp =
|
||||
getTopApp(mDisplayContent.mOpeningApps, false /* ignoreHidden */);
|
||||
getTopApp(tmpOpenApps, false /* ignoreHidden */);
|
||||
final ActivityRecord topClosingApp =
|
||||
getTopApp(mDisplayContent.mClosingApps, false /* ignoreHidden */);
|
||||
getTopApp(tmpCloseApps, false /* ignoreHidden */);
|
||||
final ActivityRecord topChangingApp =
|
||||
getTopApp(mDisplayContent.mChangingContainers, false /* ignoreHidden */);
|
||||
final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);
|
||||
@@ -258,8 +268,7 @@ public class AppTransitionController {
|
||||
final int layoutRedo;
|
||||
mService.mSurfaceAnimationRunner.deferStartingAnimations();
|
||||
try {
|
||||
applyAnimations(mDisplayContent.mOpeningApps, mDisplayContent.mClosingApps, transit,
|
||||
animLp, voiceInteraction);
|
||||
applyAnimations(tmpOpenApps, tmpCloseApps, transit, animLp, voiceInteraction);
|
||||
handleClosingApps();
|
||||
handleOpeningApps();
|
||||
handleChangingApps(transit);
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.server.wm;
|
||||
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
|
||||
import static android.view.RemoteAnimationTarget.MODE_OPENING;
|
||||
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
|
||||
|
||||
@@ -32,6 +34,7 @@ import android.os.IBinder;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
@@ -41,7 +44,6 @@ import android.window.BackNavigationInfo;
|
||||
import android.window.IBackAnimationFinishedCallback;
|
||||
import android.window.OnBackInvokedCallbackInfo;
|
||||
import android.window.TaskSnapshot;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
@@ -60,9 +62,9 @@ class BackNavigationController {
|
||||
private boolean mShowWallpaper;
|
||||
private Runnable mPendingAnimation;
|
||||
|
||||
// TODO (b/241808055) Find a appropriate time to remove during refactor
|
||||
// Execute back animation with legacy transition system. Temporary flag for easier debugging.
|
||||
static final boolean ENABLE_SHELL_TRANSITIONS = WindowManagerService.sEnableShellTransitions;
|
||||
private final AnimationTargets mAnimationTargets = new AnimationTargets();
|
||||
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
|
||||
private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* true if the back predictability feature is enabled
|
||||
@@ -284,7 +286,6 @@ class BackNavigationController {
|
||||
}
|
||||
|
||||
if (prepareAnimation) {
|
||||
infoBuilder.setDepartingWCT(toWindowContainerToken(currentTask));
|
||||
prepareAnimationIfNeeded(currentTask, prevTask, prevActivity,
|
||||
removedWindowContainer, backType, adapter);
|
||||
}
|
||||
@@ -303,11 +304,233 @@ class BackNavigationController {
|
||||
return infoBuilder.build();
|
||||
}
|
||||
|
||||
private static WindowContainerToken toWindowContainerToken(WindowContainer<?> windowContainer) {
|
||||
if (windowContainer == null || windowContainer.mRemoteToken == null) {
|
||||
return null;
|
||||
boolean isWaitBackTransition() {
|
||||
return mAnimationTargets.mComposed && mAnimationTargets.mWaitTransition;
|
||||
}
|
||||
|
||||
// For legacy transition.
|
||||
/**
|
||||
* Once we find the transition targets match back animation targets, remove the target from
|
||||
* list, so that transition won't count them in since the close animation was finished.
|
||||
*
|
||||
* @return {@code true} if the participants of this transition was animated by back gesture
|
||||
* animations, and shouldn't join next transition.
|
||||
*/
|
||||
boolean removeIfContainsBackAnimationTargets(ArraySet<ActivityRecord> openApps,
|
||||
ArraySet<ActivityRecord> closeApps) {
|
||||
if (!isWaitBackTransition()) {
|
||||
return false;
|
||||
}
|
||||
mTmpCloseApps.addAll(closeApps);
|
||||
boolean result = false;
|
||||
// Note: TmpOpenApps is empty. Unlike shell transition, the open apps will be removed from
|
||||
// mOpeningApps if there is no visibility change.
|
||||
if (mAnimationTargets.containsBackAnimationTargets(mTmpOpenApps, mTmpCloseApps)) {
|
||||
// remove close target from close list, open target from open list;
|
||||
// but the open target can be in close list.
|
||||
for (int i = openApps.size() - 1; i >= 0; --i) {
|
||||
final ActivityRecord ar = openApps.valueAt(i);
|
||||
if (mAnimationTargets.isTarget(ar, true /* open */)) {
|
||||
openApps.removeAt(i);
|
||||
}
|
||||
}
|
||||
for (int i = closeApps.size() - 1; i >= 0; --i) {
|
||||
final ActivityRecord ar = closeApps.valueAt(i);
|
||||
if (mAnimationTargets.isTarget(ar, false /* open */)) {
|
||||
closeApps.removeAt(i);
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
mTmpCloseApps.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
// For shell transition
|
||||
/**
|
||||
* Check whether the transition targets was animated by back gesture animation.
|
||||
* Because the opening target could request to do other stuff at onResume, so it could become
|
||||
* close target for a transition. So the condition here is
|
||||
* The closing target should only exist in close list, but the opening target can be either in
|
||||
* open or close list.
|
||||
* @return {@code true} if the participants of this transition was animated by back gesture
|
||||
* animations, and shouldn't join next transition.
|
||||
*/
|
||||
boolean containsBackAnimationTargets(Transition transition) {
|
||||
if (!mAnimationTargets.mComposed
|
||||
|| (transition.mType != TRANSIT_CLOSE && transition.mType != TRANSIT_TO_BACK)) {
|
||||
return false;
|
||||
}
|
||||
final ArraySet<WindowContainer> targets = transition.mParticipants;
|
||||
for (int i = targets.size() - 1; i >= 0; --i) {
|
||||
final WindowContainer wc = targets.valueAt(i);
|
||||
if (wc.asActivityRecord() == null && wc.asTask() == null) {
|
||||
continue;
|
||||
}
|
||||
// WC can be visible due to setLaunchBehind
|
||||
if (wc.isVisibleRequested()) {
|
||||
mTmpOpenApps.add(wc);
|
||||
} else {
|
||||
mTmpCloseApps.add(wc);
|
||||
}
|
||||
}
|
||||
final boolean result = mAnimationTargets.containsBackAnimationTargets(
|
||||
mTmpOpenApps, mTmpCloseApps);
|
||||
mTmpOpenApps.clear();
|
||||
mTmpCloseApps.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isMonitorTransitionTarget(WindowContainer wc) {
|
||||
if (!mAnimationTargets.mComposed || !mAnimationTargets.mWaitTransition) {
|
||||
return false;
|
||||
}
|
||||
return mAnimationTargets.isTarget(wc, wc.isVisibleRequested() /* open */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup animation, this can either happen when transition ready or finish.
|
||||
* @param cleanupTransaction The transaction which the caller want to apply the internal
|
||||
* cleanup together.
|
||||
*/
|
||||
void clearBackAnimations(SurfaceControl.Transaction cleanupTransaction) {
|
||||
mAnimationTargets.clearBackAnimateTarget(cleanupTransaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Animation composer
|
||||
* prepareAnimationIfNeeded will become too complicated in order to support
|
||||
* ActivityRecord/WindowState, using a factory class to create the RemoteAnimationTargets for
|
||||
* different scenario.
|
||||
*/
|
||||
private static class AnimationTargets {
|
||||
ActivityRecord mCloseTarget; // Must be activity
|
||||
WindowContainer mOpenTarget; // Can be activity or task if activity was removed
|
||||
private boolean mComposed;
|
||||
private boolean mWaitTransition;
|
||||
private int mSwitchType = UNKNOWN;
|
||||
private SurfaceControl.Transaction mFinishedTransaction;
|
||||
|
||||
private static final int UNKNOWN = 0;
|
||||
private static final int TASK_SWITCH = 1;
|
||||
private static final int ACTIVITY_SWITCH = 2;
|
||||
|
||||
void reset(@NonNull WindowContainer close, @NonNull WindowContainer open) {
|
||||
clearBackAnimateTarget(null);
|
||||
if (close.asActivityRecord() != null && open.asActivityRecord() != null
|
||||
&& (close.asActivityRecord().getTask() == open.asActivityRecord().getTask())) {
|
||||
mSwitchType = ACTIVITY_SWITCH;
|
||||
mCloseTarget = close.asActivityRecord();
|
||||
} else if (close.asTask() != null && open.asTask() != null
|
||||
&& close.asTask() != open.asTask()) {
|
||||
mSwitchType = TASK_SWITCH;
|
||||
mCloseTarget = close.asTask().getTopNonFinishingActivity();
|
||||
} else {
|
||||
mSwitchType = UNKNOWN;
|
||||
return;
|
||||
}
|
||||
|
||||
mOpenTarget = open;
|
||||
mComposed = false;
|
||||
mWaitTransition = false;
|
||||
}
|
||||
|
||||
void composeNewAnimations(@NonNull WindowContainer close, @NonNull WindowContainer open) {
|
||||
reset(close, open);
|
||||
if (mSwitchType == UNKNOWN || mComposed || mCloseTarget == mOpenTarget
|
||||
|| mCloseTarget == null || mOpenTarget == null) {
|
||||
return;
|
||||
}
|
||||
mComposed = true;
|
||||
mWaitTransition = false;
|
||||
}
|
||||
|
||||
boolean containTarget(ArrayList<WindowContainer> wcs, boolean open) {
|
||||
for (int i = wcs.size() - 1; i >= 0; --i) {
|
||||
if (isTarget(wcs.get(i), open)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return wcs.isEmpty();
|
||||
}
|
||||
|
||||
boolean isTarget(WindowContainer wc, boolean open) {
|
||||
if (open) {
|
||||
return wc == mOpenTarget || mOpenTarget.hasChild(wc);
|
||||
}
|
||||
if (mSwitchType == TASK_SWITCH) {
|
||||
return wc == mCloseTarget
|
||||
|| (wc.asTask() != null && wc.hasChild(mCloseTarget));
|
||||
} else if (mSwitchType == ACTIVITY_SWITCH) {
|
||||
return wc == mCloseTarget;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean setFinishTransaction(SurfaceControl.Transaction finishTransaction) {
|
||||
if (!mComposed) {
|
||||
return false;
|
||||
}
|
||||
mFinishedTransaction = finishTransaction;
|
||||
return true;
|
||||
}
|
||||
|
||||
void finishPresentAnimations(SurfaceControl.Transaction t) {
|
||||
if (!mComposed) {
|
||||
return;
|
||||
}
|
||||
final SurfaceControl.Transaction pt = t != null ? t
|
||||
: mOpenTarget.getPendingTransaction();
|
||||
if (mFinishedTransaction != null) {
|
||||
pt.merge(mFinishedTransaction);
|
||||
mFinishedTransaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
void clearBackAnimateTarget(SurfaceControl.Transaction cleanupTransaction) {
|
||||
finishPresentAnimations(cleanupTransaction);
|
||||
mCloseTarget = null;
|
||||
mOpenTarget = null;
|
||||
mComposed = false;
|
||||
mWaitTransition = false;
|
||||
mSwitchType = UNKNOWN;
|
||||
if (mFinishedTransaction != null) {
|
||||
Slog.w(TAG, "Clear back animation, found un-processed finished transaction");
|
||||
if (cleanupTransaction != null) {
|
||||
cleanupTransaction.merge(mFinishedTransaction);
|
||||
} else {
|
||||
mFinishedTransaction.apply();
|
||||
}
|
||||
mFinishedTransaction = null;
|
||||
}
|
||||
}
|
||||
|
||||
// The close target must in close list
|
||||
// The open target can either in close or open list
|
||||
boolean containsBackAnimationTargets(ArrayList<WindowContainer> openApps,
|
||||
ArrayList<WindowContainer> closeApps) {
|
||||
return containTarget(closeApps, false /* open */)
|
||||
&& (containTarget(openApps, true /* open */)
|
||||
|| containTarget(openApps, false /* open */));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("AnimationTargets{");
|
||||
sb.append(" mOpenTarget= ");
|
||||
sb.append(mOpenTarget);
|
||||
sb.append(" mCloseTarget= ");
|
||||
sb.append(mCloseTarget);
|
||||
sb.append(" mSwitchType= ");
|
||||
sb.append(mSwitchType);
|
||||
sb.append(" mComposed= ");
|
||||
sb.append(mComposed);
|
||||
sb.append(" mWaitTransition= ");
|
||||
sb.append(mWaitTransition);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
return windowContainer.mRemoteToken.toWindowContainerToken();
|
||||
}
|
||||
|
||||
private void prepareAnimationIfNeeded(Task currentTask,
|
||||
@@ -373,10 +596,6 @@ class BackNavigationController {
|
||||
leashes.add(screenshotSurface);
|
||||
}
|
||||
} else if (prevTask != null) {
|
||||
if (!ENABLE_SHELL_TRANSITIONS) {
|
||||
// Special handling for preventing next transition.
|
||||
currentTask.mBackGestureStarted = true;
|
||||
}
|
||||
prevActivity = prevTask.getTopNonFinishingActivity();
|
||||
if (prevActivity != null) {
|
||||
// Make previous task show from behind by marking its top activity as visible
|
||||
@@ -417,35 +636,36 @@ class BackNavigationController {
|
||||
for (SurfaceControl sc: leashes) {
|
||||
finishedTransaction.remove(sc);
|
||||
}
|
||||
|
||||
synchronized (mWindowManagerService.mGlobalLock) {
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
if (!triggerBack) {
|
||||
if (!needsScreenshot(backType)) {
|
||||
restoreLaunchBehind(finalPrevActivity);
|
||||
}
|
||||
if (triggerBack) {
|
||||
final SurfaceControl surfaceControl =
|
||||
removedWindowContainer.getSurfaceControl();
|
||||
if (surfaceControl != null && surfaceControl.isValid()) {
|
||||
// The animation is finish and start waiting for transition,
|
||||
// hide the task surface before it re-parented to avoid flicker.
|
||||
finishedTransaction.hide(surfaceControl);
|
||||
}
|
||||
} else if (!needsScreenshot(backType)) {
|
||||
restoreLaunchBehind(finalPrevActivity);
|
||||
}
|
||||
if (!mAnimationTargets.setFinishTransaction(finishedTransaction)) {
|
||||
finishedTransaction.apply();
|
||||
}
|
||||
if (!triggerBack) {
|
||||
mAnimationTargets.clearBackAnimateTarget(null);
|
||||
} else {
|
||||
if (triggerBack) {
|
||||
final SurfaceControl surfaceControl =
|
||||
removedWindowContainer.getSurfaceControl();
|
||||
if (surfaceControl != null && surfaceControl.isValid()) {
|
||||
// When going back to home, hide the task surface before it
|
||||
// re-parented to avoid flicker.
|
||||
finishedTransaction.hide(surfaceControl);
|
||||
}
|
||||
} else {
|
||||
currentTask.mBackGestureStarted = false;
|
||||
if (!needsScreenshot(backType)) {
|
||||
restoreLaunchBehind(finalPrevActivity);
|
||||
}
|
||||
}
|
||||
mAnimationTargets.mWaitTransition = true;
|
||||
}
|
||||
}
|
||||
finishedTransaction.apply();
|
||||
// TODO Add timeout monitor if transition didn't happen
|
||||
}
|
||||
};
|
||||
|
||||
if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
|
||||
mAnimationTargets.composeNewAnimations(removedWindowContainer, prevActivity);
|
||||
} else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|
||||
|| backType == BackNavigationInfo.TYPE_CROSS_TASK) {
|
||||
mAnimationTargets.composeNewAnimations(removedWindowContainer, prevTask);
|
||||
}
|
||||
scheduleAnimationLocked(backType, targets, adapter, callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
||||
@@ -607,12 +606,6 @@ class Task extends TaskFragment {
|
||||
|
||||
boolean mLastSurfaceShowing = true;
|
||||
|
||||
/**
|
||||
* Tracks if a back gesture is in progress.
|
||||
* Skips any system transition animations if this is set to {@code true}.
|
||||
*/
|
||||
boolean mBackGestureStarted = false;
|
||||
|
||||
private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
|
||||
Intent _affinityIntent, String _affinity, String _rootAffinity,
|
||||
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
|
||||
@@ -3331,14 +3324,6 @@ class Task extends TaskFragment {
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (mBackGestureStarted) {
|
||||
// Cancel playing transitions if a back navigation animation is in progress.
|
||||
// This bit is set by {@link BackNavigationController} when a back gesture is started.
|
||||
// It is used as a one-off transition overwrite that is cleared when the back gesture
|
||||
// is committed and triggers a transition, or when the gesture is cancelled.
|
||||
mBackGestureStarted = false;
|
||||
mDisplayContent.mSkipAppTransitionAnimation = true;
|
||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Skipping app transition animation. task=%s", this);
|
||||
} else {
|
||||
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
||||
}
|
||||
|
||||
@@ -928,10 +928,16 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
|
||||
}
|
||||
|
||||
// Check whether the participants were animated from back navigation.
|
||||
final boolean markBackAnimated = mController.mAtm.mBackNavigationController
|
||||
.containsBackAnimationTargets(this);
|
||||
// Resolve the animating targets from the participants
|
||||
mTargets = calculateTargets(mParticipants, mChanges);
|
||||
final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, mChanges,
|
||||
transaction);
|
||||
if (markBackAnimated) {
|
||||
mController.mAtm.mBackNavigationController.clearBackAnimations(mStartTransaction);
|
||||
}
|
||||
if (mOverrideOptions != null) {
|
||||
info.setAnimationOptions(mOverrideOptions);
|
||||
if (mOverrideOptions.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
|
||||
@@ -1935,9 +1941,20 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
final Task task = wc.asTask();
|
||||
if (task != null) {
|
||||
final ActivityRecord topActivity = task.getTopNonFinishingActivity();
|
||||
if (topActivity != null && topActivity.mStartingData != null
|
||||
&& topActivity.mStartingData.hasImeSurface()) {
|
||||
flags |= FLAG_WILL_IME_SHOWN;
|
||||
if (topActivity != null) {
|
||||
if (topActivity.mStartingData != null
|
||||
&& topActivity.mStartingData.hasImeSurface()) {
|
||||
flags |= FLAG_WILL_IME_SHOWN;
|
||||
}
|
||||
if (topActivity.mAtmService.mBackNavigationController
|
||||
.isMonitorTransitionTarget(topActivity)) {
|
||||
flags |= TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
|
||||
}
|
||||
} else {
|
||||
if (task.mAtmService.mBackNavigationController
|
||||
.isMonitorTransitionTarget(task)) {
|
||||
flags |= TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
|
||||
}
|
||||
}
|
||||
if (task.voiceSession != null) {
|
||||
flags |= FLAG_IS_VOICE_INTERACTION;
|
||||
@@ -1951,6 +1968,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe
|
||||
flags |= FLAG_IS_VOICE_INTERACTION;
|
||||
}
|
||||
flags |= record.mTransitionChangeFlags;
|
||||
if (record.mAtmService.mBackNavigationController
|
||||
.isMonitorTransitionTarget(record)) {
|
||||
flags |= TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
|
||||
}
|
||||
}
|
||||
final TaskFragment taskFragment = wc.asTaskFragment();
|
||||
if (taskFragment != null && task == null) {
|
||||
|
||||
Reference in New Issue
Block a user