|
|
|
|
@@ -19,7 +19,6 @@ package com.android.server.wm;
|
|
|
|
|
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
|
|
|
|
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.LayoutParams.TYPE_BASE_APPLICATION;
|
|
|
|
|
import static android.view.WindowManager.TRANSIT_CLOSE;
|
|
|
|
|
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
|
|
|
|
@@ -28,12 +27,12 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BACK_PREVIEW;
|
|
|
|
|
import static com.android.server.wm.BackNavigationProto.ANIMATION_IN_PROGRESS;
|
|
|
|
|
import static com.android.server.wm.BackNavigationProto.LAST_BACK_TYPE;
|
|
|
|
|
import static com.android.server.wm.BackNavigationProto.SHOW_WALLPAPER;
|
|
|
|
|
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_PREDICT_BACK;
|
|
|
|
|
|
|
|
|
|
import android.annotation.NonNull;
|
|
|
|
|
import android.annotation.Nullable;
|
|
|
|
|
import android.graphics.Point;
|
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.hardware.HardwareBuffer;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.os.IBinder;
|
|
|
|
|
import android.os.RemoteCallback;
|
|
|
|
|
@@ -45,6 +44,7 @@ import android.util.proto.ProtoOutputStream;
|
|
|
|
|
import android.view.IWindowFocusObserver;
|
|
|
|
|
import android.view.RemoteAnimationTarget;
|
|
|
|
|
import android.view.SurfaceControl;
|
|
|
|
|
import android.view.WindowInsets;
|
|
|
|
|
import android.window.BackAnimationAdapter;
|
|
|
|
|
import android.window.BackNavigationInfo;
|
|
|
|
|
import android.window.IBackAnimationFinishedCallback;
|
|
|
|
|
@@ -54,8 +54,11 @@ import android.window.TaskSnapshot;
|
|
|
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
|
|
|
import com.android.internal.protolog.common.ProtoLog;
|
|
|
|
|
import com.android.server.LocalServices;
|
|
|
|
|
import com.android.server.wm.utils.InsetUtils;
|
|
|
|
|
|
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.function.Consumer;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Controller to handle actions related to the back gesture on the server side.
|
|
|
|
|
@@ -69,7 +72,7 @@ class BackNavigationController {
|
|
|
|
|
private boolean mShowWallpaper;
|
|
|
|
|
private Runnable mPendingAnimation;
|
|
|
|
|
|
|
|
|
|
private final AnimationTargets mAnimationTargets = new AnimationTargets();
|
|
|
|
|
private AnimationHandler mAnimationHandler;
|
|
|
|
|
private final ArrayList<WindowContainer> mTmpOpenApps = new ArrayList<>();
|
|
|
|
|
private final ArrayList<WindowContainer> mTmpCloseApps = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
@@ -231,7 +234,6 @@ class BackNavigationController {
|
|
|
|
|
return infoBuilder.setType(backType).build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mBackAnimationInProgress = true;
|
|
|
|
|
// We don't have an application callback, let's find the destination of the back gesture
|
|
|
|
|
// The search logic should align with ActivityClientController#finishActivity
|
|
|
|
|
prevActivity = currentTask.topRunningActivity(currentActivity.token, INVALID_TASK_ID);
|
|
|
|
|
@@ -312,8 +314,17 @@ class BackNavigationController {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prepareAnimation) {
|
|
|
|
|
prepareAnimationIfNeeded(currentTask, prevTask, prevActivity,
|
|
|
|
|
removedWindowContainer, backType, adapter);
|
|
|
|
|
mPendingAnimation = mAnimationHandler.scheduleAnimation(backType, adapter,
|
|
|
|
|
currentTask, prevTask, currentActivity, prevActivity);
|
|
|
|
|
prepareAnimation = mPendingAnimation != null;
|
|
|
|
|
mBackAnimationInProgress = prepareAnimation;
|
|
|
|
|
if (prepareAnimation) {
|
|
|
|
|
mWindowManagerService.mWindowPlacerLocked.requestTraversal();
|
|
|
|
|
if (mShowWallpaper) {
|
|
|
|
|
currentTask.getDisplayContent().mWallpaperController
|
|
|
|
|
.adjustWallpaperWindows();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
infoBuilder.setPrepareRemoteAnimation(prepareAnimation);
|
|
|
|
|
} // Release wm Lock
|
|
|
|
|
@@ -331,7 +342,7 @@ class BackNavigationController {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isWaitBackTransition() {
|
|
|
|
|
return mAnimationTargets.mComposed && mAnimationTargets.mWaitTransition;
|
|
|
|
|
return mAnimationHandler.mComposed && mAnimationHandler.mWaitTransition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isKeyguardOccluded(WindowState focusWindow) {
|
|
|
|
|
@@ -357,18 +368,19 @@ class BackNavigationController {
|
|
|
|
|
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)) {
|
|
|
|
|
if (mAnimationHandler.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 */)) {
|
|
|
|
|
if (mAnimationHandler.isTarget(ar, true /* open */)) {
|
|
|
|
|
openApps.removeAt(i);
|
|
|
|
|
mAnimationHandler.mOpenTransitionTargetMatch = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int i = closeApps.size() - 1; i >= 0; --i) {
|
|
|
|
|
final ActivityRecord ar = closeApps.valueAt(i);
|
|
|
|
|
if (mAnimationTargets.isTarget(ar, false /* open */)) {
|
|
|
|
|
if (mAnimationHandler.isTarget(ar, false /* open */)) {
|
|
|
|
|
closeApps.removeAt(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -389,7 +401,7 @@ class BackNavigationController {
|
|
|
|
|
* animations, and shouldn't join next transition.
|
|
|
|
|
*/
|
|
|
|
|
boolean containsBackAnimationTargets(Transition transition) {
|
|
|
|
|
if (!mAnimationTargets.mComposed
|
|
|
|
|
if (!mAnimationHandler.mComposed
|
|
|
|
|
|| (transition.mType != TRANSIT_CLOSE && transition.mType != TRANSIT_TO_BACK)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@@ -406,18 +418,22 @@ class BackNavigationController {
|
|
|
|
|
mTmpCloseApps.add(wc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
final boolean result = mAnimationTargets.containsBackAnimationTargets(
|
|
|
|
|
final boolean result = mAnimationHandler.containsBackAnimationTargets(
|
|
|
|
|
mTmpOpenApps, mTmpCloseApps);
|
|
|
|
|
if (result) {
|
|
|
|
|
mAnimationHandler.mOpenTransitionTargetMatch =
|
|
|
|
|
mAnimationHandler.containTarget(mTmpOpenApps, true);
|
|
|
|
|
}
|
|
|
|
|
mTmpOpenApps.clear();
|
|
|
|
|
mTmpCloseApps.clear();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isMonitorTransitionTarget(WindowContainer wc) {
|
|
|
|
|
if (!mAnimationTargets.mComposed || !mAnimationTargets.mWaitTransition) {
|
|
|
|
|
if (!mAnimationHandler.mComposed || !mAnimationHandler.mWaitTransition) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return mAnimationTargets.isTarget(wc, wc.isVisibleRequested() /* open */);
|
|
|
|
|
return mAnimationHandler.isTarget(wc, wc.isVisibleRequested() /* open */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -426,60 +442,106 @@ class BackNavigationController {
|
|
|
|
|
* cleanup together.
|
|
|
|
|
*/
|
|
|
|
|
void clearBackAnimations(SurfaceControl.Transaction cleanupTransaction) {
|
|
|
|
|
mAnimationTargets.clearBackAnimateTarget(cleanupTransaction);
|
|
|
|
|
mAnimationHandler.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.
|
|
|
|
|
* Create and handling animations status for an open/close animation targets.
|
|
|
|
|
*/
|
|
|
|
|
private static class AnimationTargets {
|
|
|
|
|
ActivityRecord mCloseTarget; // Must be activity
|
|
|
|
|
WindowContainer mOpenTarget; // Can be activity or task if activity was removed
|
|
|
|
|
private static class AnimationHandler {
|
|
|
|
|
private final WindowManagerService mWindowManagerService;
|
|
|
|
|
private BackWindowAnimationAdaptor mCloseAdaptor;
|
|
|
|
|
private BackWindowAnimationAdaptor mOpenAdaptor;
|
|
|
|
|
private boolean mComposed;
|
|
|
|
|
private boolean mWaitTransition;
|
|
|
|
|
private int mSwitchType = UNKNOWN;
|
|
|
|
|
private SurfaceControl.Transaction mFinishedTransaction;
|
|
|
|
|
// This will be set before transition happen, to know whether the real opening target
|
|
|
|
|
// exactly match animating target. When target match, reparent the starting surface to
|
|
|
|
|
// the opening target like starting window do.
|
|
|
|
|
private boolean mOpenTransitionTargetMatch;
|
|
|
|
|
// The starting surface task Id. Used to clear the starting surface if the animation has
|
|
|
|
|
// request one during animating.
|
|
|
|
|
private int mRequestedStartingSurfaceTaskId;
|
|
|
|
|
private SurfaceControl mStartingSurface;
|
|
|
|
|
|
|
|
|
|
AnimationHandler(WindowManagerService wms) {
|
|
|
|
|
mWindowManagerService = wms;
|
|
|
|
|
}
|
|
|
|
|
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 == null || open == null) {
|
|
|
|
|
Slog.e(TAG, "reset animation with null target close: "
|
|
|
|
|
+ close + " open: " + open);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
private void initiate(WindowContainer close, WindowContainer open) {
|
|
|
|
|
WindowContainer closeTarget;
|
|
|
|
|
if (close.asActivityRecord() != null && open.asActivityRecord() != null
|
|
|
|
|
&& (close.asActivityRecord().getTask() == open.asActivityRecord().getTask())) {
|
|
|
|
|
mSwitchType = ACTIVITY_SWITCH;
|
|
|
|
|
mCloseTarget = close.asActivityRecord();
|
|
|
|
|
closeTarget = close.asActivityRecord();
|
|
|
|
|
} else if (close.asTask() != null && open.asTask() != null
|
|
|
|
|
&& close.asTask() != open.asTask()) {
|
|
|
|
|
mSwitchType = TASK_SWITCH;
|
|
|
|
|
mCloseTarget = close.asTask().getTopNonFinishingActivity();
|
|
|
|
|
closeTarget = close.asTask().getTopNonFinishingActivity();
|
|
|
|
|
} else {
|
|
|
|
|
mSwitchType = UNKNOWN;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mOpenTarget = open;
|
|
|
|
|
mComposed = false;
|
|
|
|
|
mWaitTransition = false;
|
|
|
|
|
mCloseAdaptor = createAdaptor(closeTarget, false /* isOpen */);
|
|
|
|
|
mOpenAdaptor = createAdaptor(open, true /* isOpen */);
|
|
|
|
|
|
|
|
|
|
if (mCloseAdaptor.mAnimationTarget == null || mOpenAdaptor.mAnimationTarget == null) {
|
|
|
|
|
Slog.w(TAG, "composeNewAnimations fail, skip");
|
|
|
|
|
clearBackAnimateTarget(null /* cleanupTransaction */);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void composeNewAnimations(@NonNull WindowContainer close, @NonNull WindowContainer open) {
|
|
|
|
|
reset(close, open);
|
|
|
|
|
if (mSwitchType == UNKNOWN || mComposed || mCloseTarget == mOpenTarget
|
|
|
|
|
|| mCloseTarget == null || mOpenTarget == null) {
|
|
|
|
|
return;
|
|
|
|
|
boolean composeAnimations(@NonNull WindowContainer close, @NonNull WindowContainer open) {
|
|
|
|
|
clearBackAnimateTarget(null /* cleanupTransaction */);
|
|
|
|
|
if (close == null || open == null) {
|
|
|
|
|
Slog.e(TAG, "reset animation with null target close: "
|
|
|
|
|
+ close + " open: " + open);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
initiate(close, open);
|
|
|
|
|
if (mSwitchType == UNKNOWN) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
mComposed = true;
|
|
|
|
|
mWaitTransition = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoteAnimationTarget[] getAnimationTargets() {
|
|
|
|
|
return mComposed ? new RemoteAnimationTarget[] {
|
|
|
|
|
mCloseAdaptor.mAnimationTarget, mOpenAdaptor.mAnimationTarget} : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isSupportWindowlessSurface() {
|
|
|
|
|
return mWindowManagerService.mAtmService.mTaskOrganizerController
|
|
|
|
|
.isSupportWindowlessStartingSurface();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void createStartingSurface(TaskSnapshot snapshot) {
|
|
|
|
|
if (!mComposed) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final ActivityRecord topActivity = getTopOpenActivity();
|
|
|
|
|
if (topActivity == null) {
|
|
|
|
|
Slog.e(TAG, "createStartingSurface fail, no open activity: " + this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// TODO (b/257857570) draw snapshot by starting surface.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ActivityRecord getTopOpenActivity() {
|
|
|
|
|
if (mSwitchType == ACTIVITY_SWITCH) {
|
|
|
|
|
return mOpenAdaptor.mTarget.asActivityRecord();
|
|
|
|
|
} else if (mSwitchType == TASK_SWITCH) {
|
|
|
|
|
return mOpenAdaptor.mTarget.asTask().getTopNonFinishingActivity();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean containTarget(ArrayList<WindowContainer> wcs, boolean open) {
|
|
|
|
|
@@ -493,13 +555,13 @@ class BackNavigationController {
|
|
|
|
|
|
|
|
|
|
boolean isTarget(WindowContainer wc, boolean open) {
|
|
|
|
|
if (open) {
|
|
|
|
|
return wc == mOpenTarget || mOpenTarget.hasChild(wc);
|
|
|
|
|
return wc == mOpenAdaptor.mTarget || mOpenAdaptor.mTarget.hasChild(wc);
|
|
|
|
|
}
|
|
|
|
|
if (mSwitchType == TASK_SWITCH) {
|
|
|
|
|
return wc == mCloseTarget
|
|
|
|
|
|| (wc.asTask() != null && wc.hasChild(mCloseTarget));
|
|
|
|
|
return wc == mCloseAdaptor.mTarget
|
|
|
|
|
|| (wc.asTask() != null && wc.hasChild(mCloseAdaptor.mTarget));
|
|
|
|
|
} else if (mSwitchType == ACTIVITY_SWITCH) {
|
|
|
|
|
return wc == mCloseTarget;
|
|
|
|
|
return wc == mCloseAdaptor.mTarget;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@@ -517,19 +579,53 @@ class BackNavigationController {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
final SurfaceControl.Transaction pt = t != null ? t
|
|
|
|
|
: mOpenTarget.getPendingTransaction();
|
|
|
|
|
: mOpenAdaptor.mTarget.getPendingTransaction();
|
|
|
|
|
if (mFinishedTransaction != null) {
|
|
|
|
|
pt.merge(mFinishedTransaction);
|
|
|
|
|
mFinishedTransaction = null;
|
|
|
|
|
}
|
|
|
|
|
cleanUpWindowlessSurface();
|
|
|
|
|
|
|
|
|
|
if (mCloseAdaptor != null) {
|
|
|
|
|
mCloseAdaptor.mTarget.cancelAnimation();
|
|
|
|
|
mCloseAdaptor = null;
|
|
|
|
|
}
|
|
|
|
|
if (mOpenAdaptor != null) {
|
|
|
|
|
mOpenAdaptor.mTarget.cancelAnimation();
|
|
|
|
|
mOpenAdaptor = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void cleanUpWindowlessSurface() {
|
|
|
|
|
final ActivityRecord ar = getTopOpenActivity();
|
|
|
|
|
if (ar == null) {
|
|
|
|
|
Slog.w(TAG, "finishPresentAnimations without top activity: " + this);
|
|
|
|
|
}
|
|
|
|
|
final SurfaceControl.Transaction pendingT = ar != null ? ar.getPendingTransaction()
|
|
|
|
|
: mOpenAdaptor.mTarget.getPendingTransaction();
|
|
|
|
|
// ensure open target is visible before cancel animation.
|
|
|
|
|
mOpenTransitionTargetMatch &= ar != null;
|
|
|
|
|
if (mOpenTransitionTargetMatch) {
|
|
|
|
|
pendingT.show(ar.getSurfaceControl());
|
|
|
|
|
}
|
|
|
|
|
if (mRequestedStartingSurfaceTaskId != 0) {
|
|
|
|
|
// If open target match, reparent to open activity
|
|
|
|
|
if (mStartingSurface != null && mOpenTransitionTargetMatch) {
|
|
|
|
|
pendingT.reparent(mStartingSurface, ar.getSurfaceControl());
|
|
|
|
|
}
|
|
|
|
|
// remove starting surface.
|
|
|
|
|
mStartingSurface = null;
|
|
|
|
|
// TODO (b/257857570) draw snapshot by starting surface.
|
|
|
|
|
mRequestedStartingSurfaceTaskId = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void clearBackAnimateTarget(SurfaceControl.Transaction cleanupTransaction) {
|
|
|
|
|
finishPresentAnimations(cleanupTransaction);
|
|
|
|
|
mCloseTarget = null;
|
|
|
|
|
mOpenTarget = null;
|
|
|
|
|
mComposed = false;
|
|
|
|
|
mWaitTransition = false;
|
|
|
|
|
mOpenTransitionTargetMatch = false;
|
|
|
|
|
mRequestedStartingSurfaceTaskId = 0;
|
|
|
|
|
mSwitchType = UNKNOWN;
|
|
|
|
|
if (mFinishedTransaction != null) {
|
|
|
|
|
Slog.w(TAG, "Clear back animation, found un-processed finished transaction");
|
|
|
|
|
@@ -553,211 +649,284 @@ class BackNavigationController {
|
|
|
|
|
|
|
|
|
|
@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 "AnimationTargets{"
|
|
|
|
|
+ " openTarget= "
|
|
|
|
|
+ mOpenAdaptor.mTarget
|
|
|
|
|
+ " closeTarget= "
|
|
|
|
|
+ mCloseAdaptor.mTarget
|
|
|
|
|
+ " mSwitchType= "
|
|
|
|
|
+ mSwitchType
|
|
|
|
|
+ " mComposed= "
|
|
|
|
|
+ mComposed
|
|
|
|
|
+ " mWaitTransition= "
|
|
|
|
|
+ mWaitTransition
|
|
|
|
|
+ '}';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void prepareAnimationIfNeeded(Task currentTask,
|
|
|
|
|
Task prevTask, ActivityRecord prevActivity, WindowContainer<?> removedWindowContainer,
|
|
|
|
|
int backType, BackAnimationAdapter adapter) {
|
|
|
|
|
final ArrayList<SurfaceControl> leashes = new ArrayList<>();
|
|
|
|
|
final SurfaceControl.Transaction startedTransaction = currentTask.getPendingTransaction();
|
|
|
|
|
final SurfaceControl.Transaction finishedTransaction = new SurfaceControl.Transaction();
|
|
|
|
|
// Prepare a leash to animate for the departing window
|
|
|
|
|
final SurfaceControl animLeash = currentTask.makeAnimationLeash()
|
|
|
|
|
.setName("BackPreview Leash for " + currentTask)
|
|
|
|
|
.setHidden(false)
|
|
|
|
|
.build();
|
|
|
|
|
removedWindowContainer.reparentSurfaceControl(startedTransaction, animLeash);
|
|
|
|
|
private static BackWindowAnimationAdaptor createAdaptor(
|
|
|
|
|
WindowContainer target, boolean isOpen) {
|
|
|
|
|
final BackWindowAnimationAdaptor adaptor =
|
|
|
|
|
new BackWindowAnimationAdaptor(target, isOpen);
|
|
|
|
|
target.startAnimation(target.getPendingTransaction(), adaptor, false /* hidden */,
|
|
|
|
|
ANIMATION_TYPE_PREDICT_BACK);
|
|
|
|
|
return adaptor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final RemoteAnimationTarget topAppTarget = createRemoteAnimationTargetLocked(
|
|
|
|
|
currentTask, animLeash, MODE_CLOSING);
|
|
|
|
|
private static class BackWindowAnimationAdaptor implements AnimationAdapter {
|
|
|
|
|
SurfaceControl mCapturedLeash;
|
|
|
|
|
private final Rect mBounds = new Rect();
|
|
|
|
|
private final WindowContainer mTarget;
|
|
|
|
|
private final boolean mIsOpen;
|
|
|
|
|
private RemoteAnimationTarget mAnimationTarget;
|
|
|
|
|
|
|
|
|
|
// reset leash after animation finished.
|
|
|
|
|
leashes.add(animLeash);
|
|
|
|
|
removedWindowContainer.reparentSurfaceControl(finishedTransaction,
|
|
|
|
|
removedWindowContainer.getParentSurfaceControl());
|
|
|
|
|
BackWindowAnimationAdaptor(WindowContainer closeTarget, boolean isOpen) {
|
|
|
|
|
mBounds.set(closeTarget.getBounds());
|
|
|
|
|
mTarget = closeTarget;
|
|
|
|
|
mIsOpen = isOpen;
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public boolean getShowWallpaper() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prepare a leash to animate for the entering window.
|
|
|
|
|
RemoteAnimationTarget behindAppTarget = null;
|
|
|
|
|
if (needsScreenshot(backType)) {
|
|
|
|
|
HardwareBuffer screenshotBuffer = null;
|
|
|
|
|
Task backTargetTask = prevTask;
|
|
|
|
|
switch(backType) {
|
|
|
|
|
case BackNavigationInfo.TYPE_CROSS_TASK:
|
|
|
|
|
int prevTaskId = prevTask != null ? prevTask.mTaskId : 0;
|
|
|
|
|
int prevUserId = prevTask != null ? prevTask.mUserId : 0;
|
|
|
|
|
screenshotBuffer = getTaskSnapshot(prevTaskId, prevUserId);
|
|
|
|
|
break;
|
|
|
|
|
@Override
|
|
|
|
|
public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
|
|
|
|
|
int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
|
|
|
|
|
mCapturedLeash = animationLeash;
|
|
|
|
|
createRemoteAnimationTarget(mIsOpen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationCancelled(SurfaceControl animationLeash) {
|
|
|
|
|
if (mCapturedLeash == animationLeash) {
|
|
|
|
|
mCapturedLeash = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public long getDurationHint() {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public long getStatusBarTransitionsStartTime() {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void dump(PrintWriter pw, String prefix) {
|
|
|
|
|
pw.print(prefix + "BackWindowAnimationAdaptor mCapturedLeash=");
|
|
|
|
|
pw.print(mCapturedLeash);
|
|
|
|
|
pw.println();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void dumpDebug(ProtoOutputStream proto) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemoteAnimationTarget createRemoteAnimationTarget(boolean isOpen) {
|
|
|
|
|
if (mAnimationTarget != null) {
|
|
|
|
|
return mAnimationTarget;
|
|
|
|
|
}
|
|
|
|
|
Task t = mTarget.asTask();
|
|
|
|
|
final ActivityRecord r = t != null ? t.getTopNonFinishingActivity()
|
|
|
|
|
: mTarget.asActivityRecord();
|
|
|
|
|
if (t == null && r != null) {
|
|
|
|
|
t = r.getTask();
|
|
|
|
|
}
|
|
|
|
|
if (t == null || r == null) {
|
|
|
|
|
Slog.e(TAG, "createRemoteAnimationTarget fail " + mTarget);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
final WindowState mainWindow = r.findMainWindow();
|
|
|
|
|
Rect insets;
|
|
|
|
|
if (mainWindow != null) {
|
|
|
|
|
insets = mainWindow.getInsetsStateWithVisibilityOverride().calculateInsets(
|
|
|
|
|
mBounds, WindowInsets.Type.systemBars(),
|
|
|
|
|
false /* ignoreVisibility */).toRect();
|
|
|
|
|
InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets());
|
|
|
|
|
} else {
|
|
|
|
|
insets = new Rect();
|
|
|
|
|
}
|
|
|
|
|
final int mode = isOpen ? MODE_OPENING : MODE_CLOSING;
|
|
|
|
|
mAnimationTarget = new RemoteAnimationTarget(t.mTaskId, mode, mCapturedLeash,
|
|
|
|
|
!r.fillsParent(), new Rect(),
|
|
|
|
|
insets, r.getPrefixOrderIndex(), new Point(mBounds.left, mBounds.top),
|
|
|
|
|
mBounds, mBounds, t.getWindowConfiguration(),
|
|
|
|
|
true /* isNotInRecents */, null, null, t.getTaskInfo(),
|
|
|
|
|
r.checkEnterPictureInPictureAppOpsState());
|
|
|
|
|
return mAnimationTarget;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Runnable scheduleAnimation(int backType, BackAnimationAdapter adapter,
|
|
|
|
|
Task currentTask, Task previousTask, ActivityRecord currentActivity,
|
|
|
|
|
ActivityRecord previousActivity) {
|
|
|
|
|
switch (backType) {
|
|
|
|
|
case BackNavigationInfo.TYPE_RETURN_TO_HOME:
|
|
|
|
|
return new ScheduleAnimationBuilder(backType, adapter)
|
|
|
|
|
.setIsLaunchBehind(true)
|
|
|
|
|
.setComposeTarget(currentTask, previousTask)
|
|
|
|
|
.build();
|
|
|
|
|
case BackNavigationInfo.TYPE_CROSS_ACTIVITY:
|
|
|
|
|
if (prevActivity != null && prevActivity.mActivityComponent != null) {
|
|
|
|
|
screenshotBuffer = getActivitySnapshot(currentTask, prevActivity);
|
|
|
|
|
return new ScheduleAnimationBuilder(backType, adapter)
|
|
|
|
|
.setComposeTarget(currentActivity, previousActivity)
|
|
|
|
|
.setOpeningSnapshot(getActivitySnapshot(previousActivity)).build();
|
|
|
|
|
case BackNavigationInfo.TYPE_CROSS_TASK:
|
|
|
|
|
return new ScheduleAnimationBuilder(backType, adapter)
|
|
|
|
|
.setComposeTarget(currentTask, previousTask)
|
|
|
|
|
.setOpeningSnapshot(getTaskSnapshot(previousTask)).build();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class ScheduleAnimationBuilder {
|
|
|
|
|
final int mType;
|
|
|
|
|
final BackAnimationAdapter mBackAnimationAdapter;
|
|
|
|
|
WindowContainer mCloseTarget;
|
|
|
|
|
WindowContainer mOpenTarget;
|
|
|
|
|
TaskSnapshot mOpenSnapshot;
|
|
|
|
|
boolean mIsLaunchBehind;
|
|
|
|
|
|
|
|
|
|
ScheduleAnimationBuilder(int type, BackAnimationAdapter backAnimationAdapter) {
|
|
|
|
|
mType = type;
|
|
|
|
|
mBackAnimationAdapter = backAnimationAdapter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScheduleAnimationBuilder setComposeTarget(WindowContainer close, WindowContainer open) {
|
|
|
|
|
mCloseTarget = close;
|
|
|
|
|
mOpenTarget = open;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScheduleAnimationBuilder setOpeningSnapshot(TaskSnapshot snapshot) {
|
|
|
|
|
mOpenSnapshot = snapshot;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ScheduleAnimationBuilder setIsLaunchBehind(boolean launchBehind) {
|
|
|
|
|
mIsLaunchBehind = launchBehind;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Runnable build() {
|
|
|
|
|
if (mOpenTarget == null || mCloseTarget == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
final boolean shouldLaunchBehind = mIsLaunchBehind || !isSupportWindowlessSurface();
|
|
|
|
|
final ActivityRecord launchBehindActivity = !shouldLaunchBehind ? null
|
|
|
|
|
: mOpenTarget.asTask() != null
|
|
|
|
|
? mOpenTarget.asTask().getTopNonFinishingActivity()
|
|
|
|
|
: mOpenTarget.asActivityRecord() != null
|
|
|
|
|
? mOpenTarget.asActivityRecord() : null;
|
|
|
|
|
if (shouldLaunchBehind && launchBehindActivity == null) {
|
|
|
|
|
Slog.e(TAG, "No opening activity");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!composeAnimations(mCloseTarget, mOpenTarget)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if (launchBehindActivity != null) {
|
|
|
|
|
setLaunchBehind(launchBehindActivity);
|
|
|
|
|
} else {
|
|
|
|
|
createStartingSurface(mOpenSnapshot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final IBackAnimationFinishedCallback callback = makeAnimationFinishedCallback(
|
|
|
|
|
launchBehindActivity != null ? triggerBack -> {
|
|
|
|
|
if (!triggerBack) {
|
|
|
|
|
restoreLaunchBehind(launchBehindActivity);
|
|
|
|
|
}
|
|
|
|
|
} : null,
|
|
|
|
|
mCloseTarget);
|
|
|
|
|
final RemoteAnimationTarget[] targets = getAnimationTargets();
|
|
|
|
|
|
|
|
|
|
return () -> {
|
|
|
|
|
try {
|
|
|
|
|
mBackAnimationAdapter.getRunner().onAnimationStart(mType,
|
|
|
|
|
targets, null, null, callback);
|
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
backTargetTask = currentTask;
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find a screenshot of the previous activity if we actually have an animation
|
|
|
|
|
SurfaceControl animationLeashParent = removedWindowContainer.getAnimationLeashParent();
|
|
|
|
|
if (screenshotBuffer != null) {
|
|
|
|
|
final SurfaceControl screenshotSurface = new SurfaceControl.Builder()
|
|
|
|
|
.setName("BackPreview Screenshot for " + prevActivity)
|
|
|
|
|
.setHidden(false)
|
|
|
|
|
.setParent(animationLeashParent)
|
|
|
|
|
.setBLASTLayer()
|
|
|
|
|
.build();
|
|
|
|
|
startedTransaction.setBuffer(screenshotSurface, screenshotBuffer);
|
|
|
|
|
|
|
|
|
|
// The Animation leash needs to be above the screenshot surface, but the animation
|
|
|
|
|
// leash needs to be added before to be in the synchronized block.
|
|
|
|
|
startedTransaction.setLayer(topAppTarget.leash, 1);
|
|
|
|
|
|
|
|
|
|
behindAppTarget =
|
|
|
|
|
createRemoteAnimationTargetLocked(
|
|
|
|
|
backTargetTask, screenshotSurface, MODE_OPENING);
|
|
|
|
|
|
|
|
|
|
// reset leash after animation finished.
|
|
|
|
|
leashes.add(screenshotSurface);
|
|
|
|
|
}
|
|
|
|
|
} else if (prevTask != null && prevActivity != null) {
|
|
|
|
|
// Make previous task show from behind by marking its top activity as visible
|
|
|
|
|
// and launch-behind to bump its visibility for the duration of the back gesture.
|
|
|
|
|
setLaunchBehind(prevActivity);
|
|
|
|
|
|
|
|
|
|
final SurfaceControl leash = prevActivity.makeAnimationLeash()
|
|
|
|
|
.setName("BackPreview Leash for " + prevActivity)
|
|
|
|
|
.setHidden(false)
|
|
|
|
|
.build();
|
|
|
|
|
prevActivity.reparentSurfaceControl(startedTransaction, leash);
|
|
|
|
|
behindAppTarget = createRemoteAnimationTargetLocked(
|
|
|
|
|
prevTask, leash, MODE_OPENING);
|
|
|
|
|
|
|
|
|
|
// reset leash after animation finished.
|
|
|
|
|
leashes.add(leash);
|
|
|
|
|
prevActivity.reparentSurfaceControl(finishedTransaction,
|
|
|
|
|
prevActivity.getParentSurfaceControl());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mShowWallpaper) {
|
|
|
|
|
currentTask.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
|
|
|
|
|
// TODO(b/241808055): If the current animation need to show wallpaper and animate the
|
|
|
|
|
// wallpaper, start the wallpaper animation to collect wallpaper target and deliver it
|
|
|
|
|
// to the back animation controller.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final RemoteAnimationTarget[] targets = (behindAppTarget == null)
|
|
|
|
|
? new RemoteAnimationTarget[] {topAppTarget}
|
|
|
|
|
: new RemoteAnimationTarget[] {topAppTarget, behindAppTarget};
|
|
|
|
|
|
|
|
|
|
final ActivityRecord finalPrevActivity = prevActivity;
|
|
|
|
|
final IBackAnimationFinishedCallback callback =
|
|
|
|
|
new IBackAnimationFinishedCallback.Stub() {
|
|
|
|
|
private IBackAnimationFinishedCallback makeAnimationFinishedCallback(
|
|
|
|
|
Consumer<Boolean> b, WindowContainer closeTarget) {
|
|
|
|
|
return new IBackAnimationFinishedCallback.Stub() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationFinished(boolean triggerBack) {
|
|
|
|
|
for (SurfaceControl sc: leashes) {
|
|
|
|
|
finishedTransaction.remove(sc);
|
|
|
|
|
}
|
|
|
|
|
final SurfaceControl.Transaction finishedTransaction =
|
|
|
|
|
new SurfaceControl.Transaction();
|
|
|
|
|
synchronized (mWindowManagerService.mGlobalLock) {
|
|
|
|
|
if (b != null) {
|
|
|
|
|
b.accept(triggerBack);
|
|
|
|
|
}
|
|
|
|
|
if (triggerBack) {
|
|
|
|
|
final SurfaceControl surfaceControl =
|
|
|
|
|
removedWindowContainer.getSurfaceControl();
|
|
|
|
|
closeTarget.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.
|
|
|
|
|
// Hide the close target surface when transition start.
|
|
|
|
|
finishedTransaction.hide(surfaceControl);
|
|
|
|
|
}
|
|
|
|
|
} else if (!needsScreenshot(backType)) {
|
|
|
|
|
restoreLaunchBehind(finalPrevActivity);
|
|
|
|
|
}
|
|
|
|
|
if (!mAnimationTargets.setFinishTransaction(finishedTransaction)) {
|
|
|
|
|
if (!setFinishTransaction(finishedTransaction)) {
|
|
|
|
|
finishedTransaction.apply();
|
|
|
|
|
}
|
|
|
|
|
if (!triggerBack) {
|
|
|
|
|
mAnimationTargets.clearBackAnimateTarget(null);
|
|
|
|
|
clearBackAnimateTarget(
|
|
|
|
|
null /* cleanupTransaction */);
|
|
|
|
|
} else {
|
|
|
|
|
mAnimationTargets.mWaitTransition = true;
|
|
|
|
|
mWaitTransition = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@NonNull
|
|
|
|
|
private static RemoteAnimationTarget createRemoteAnimationTargetLocked(
|
|
|
|
|
Task task, SurfaceControl animLeash, int mode) {
|
|
|
|
|
ActivityRecord topApp = task.getTopRealVisibleActivity();
|
|
|
|
|
if (topApp == null) {
|
|
|
|
|
topApp = task.getTopNonFinishingActivity();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final WindowState mainWindow = topApp != null
|
|
|
|
|
? topApp.findMainWindow()
|
|
|
|
|
: null;
|
|
|
|
|
int windowType = INVALID_WINDOW_TYPE;
|
|
|
|
|
if (mainWindow != null) {
|
|
|
|
|
windowType = mainWindow.getWindowType();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Rect bounds = new Rect(task.getBounds());
|
|
|
|
|
Rect localBounds = new Rect(bounds);
|
|
|
|
|
Point tmpPos = new Point();
|
|
|
|
|
task.getRelativePosition(tmpPos);
|
|
|
|
|
localBounds.offsetTo(tmpPos.x, tmpPos.y);
|
|
|
|
|
|
|
|
|
|
return new RemoteAnimationTarget(
|
|
|
|
|
task.mTaskId,
|
|
|
|
|
mode,
|
|
|
|
|
animLeash,
|
|
|
|
|
false /* isTransluscent */,
|
|
|
|
|
new Rect() /* clipRect */,
|
|
|
|
|
new Rect() /* contentInsets */,
|
|
|
|
|
task.getPrefixOrderIndex(),
|
|
|
|
|
tmpPos /* position */,
|
|
|
|
|
localBounds /* localBounds */,
|
|
|
|
|
bounds /* screenSpaceBounds */,
|
|
|
|
|
task.getWindowConfiguration(),
|
|
|
|
|
true /* isNotInRecent */,
|
|
|
|
|
null,
|
|
|
|
|
null,
|
|
|
|
|
task.getTaskInfo(),
|
|
|
|
|
false,
|
|
|
|
|
windowType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@VisibleForTesting
|
|
|
|
|
void scheduleAnimationLocked(@BackNavigationInfo.BackTargetType int type,
|
|
|
|
|
RemoteAnimationTarget[] targets, BackAnimationAdapter backAnimationAdapter,
|
|
|
|
|
IBackAnimationFinishedCallback callback) {
|
|
|
|
|
mPendingAnimation = () -> {
|
|
|
|
|
try {
|
|
|
|
|
backAnimationAdapter.getRunner().onAnimationStart(type,
|
|
|
|
|
targets, null, null, callback);
|
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
mWindowManagerService.mWindowPlacerLocked.requestTraversal();
|
|
|
|
|
|
|
|
|
|
private void setLaunchBehind(ActivityRecord activity) {
|
|
|
|
|
if (activity == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!activity.isVisibleRequested()) {
|
|
|
|
|
activity.setVisibility(true);
|
|
|
|
|
}
|
|
|
|
|
activity.mLaunchTaskBehind = true;
|
|
|
|
|
|
|
|
|
|
// Handle fixed rotation launching app.
|
|
|
|
|
final DisplayContent dc = activity.mDisplayContent;
|
|
|
|
|
dc.rotateInDifferentOrientationIfNeeded(activity);
|
|
|
|
|
if (activity.hasFixedRotationTransform()) {
|
|
|
|
|
// Set the record so we can recognize it to continue to update display
|
|
|
|
|
// orientation if the previous activity becomes the top later.
|
|
|
|
|
dc.setFixedRotationLaunchingApp(activity,
|
|
|
|
|
activity.getWindowConfiguration().getRotation());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
|
|
|
|
|
"Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
|
|
|
|
|
activity.mTaskSupervisor.mStoppingActivities.remove(activity);
|
|
|
|
|
activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
|
|
|
|
|
0 /* configChanges */, false /* preserveWindows */, true);
|
|
|
|
|
}
|
|
|
|
|
private void restoreLaunchBehind(ActivityRecord activity) {
|
|
|
|
|
if (activity == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
|
|
|
|
|
|
|
|
|
|
// Restore the launch-behind state.
|
|
|
|
|
activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
|
|
|
|
|
activity.mLaunchTaskBehind = false;
|
|
|
|
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
|
|
|
|
|
"Setting Activity.mLauncherTaskBehind to false. Activity=%s",
|
|
|
|
|
activity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void checkAnimationReady(WallpaperController wallpaperController) {
|
|
|
|
|
@@ -794,80 +963,36 @@ class BackNavigationController {
|
|
|
|
|
mShowWallpaper = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private HardwareBuffer getActivitySnapshot(@NonNull Task task, ActivityRecord r) {
|
|
|
|
|
return task.getSnapshotForActivityRecord(r);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private HardwareBuffer getTaskSnapshot(int taskId, int userId) {
|
|
|
|
|
if (mWindowManagerService.mTaskSnapshotController == null) {
|
|
|
|
|
private static TaskSnapshot getActivitySnapshot(@NonNull ActivityRecord r) {
|
|
|
|
|
if (!isScreenshotEnabled()) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
TaskSnapshot snapshot = mWindowManagerService.mTaskSnapshotController.getSnapshot(taskId,
|
|
|
|
|
userId, true /* restoreFromDisk */, false /* isLowResolution */);
|
|
|
|
|
return snapshot != null ? snapshot.getHardwareBuffer() : null;
|
|
|
|
|
// Check if we have a screenshot of the previous activity, indexed by its
|
|
|
|
|
// component name.
|
|
|
|
|
// TODO return TaskSnapshot when feature complete.
|
|
|
|
|
// final HardwareBuffer hw = r.getTask().getSnapshotForActivityRecord(r);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean needsScreenshot(int backType) {
|
|
|
|
|
private static TaskSnapshot getTaskSnapshot(Task task) {
|
|
|
|
|
if (!isScreenshotEnabled()) {
|
|
|
|
|
return false;
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
switch (backType) {
|
|
|
|
|
case BackNavigationInfo.TYPE_RETURN_TO_HOME:
|
|
|
|
|
case BackNavigationInfo.TYPE_DIALOG_CLOSE:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
// Don't read from disk!!
|
|
|
|
|
return task.mRootWindowContainer.mWindowManager.mTaskSnapshotController.getSnapshot(
|
|
|
|
|
task.mTaskId, task.mUserId, false /* restoreFromDisk */,
|
|
|
|
|
false /* isLowResolution */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setWindowManager(WindowManagerService wm) {
|
|
|
|
|
mWindowManagerService = wm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setLaunchBehind(ActivityRecord activity) {
|
|
|
|
|
if (activity == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!activity.isVisibleRequested()) {
|
|
|
|
|
activity.setVisibility(true);
|
|
|
|
|
}
|
|
|
|
|
activity.mLaunchTaskBehind = true;
|
|
|
|
|
|
|
|
|
|
// Handle fixed rotation launching app.
|
|
|
|
|
final DisplayContent dc = activity.mDisplayContent;
|
|
|
|
|
dc.rotateInDifferentOrientationIfNeeded(activity);
|
|
|
|
|
if (activity.hasFixedRotationTransform()) {
|
|
|
|
|
// Set the record so we can recognize it to continue to update display orientation
|
|
|
|
|
// if the previous activity becomes the top later.
|
|
|
|
|
dc.setFixedRotationLaunchingApp(activity,
|
|
|
|
|
activity.getWindowConfiguration().getRotation());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
|
|
|
|
|
"Setting Activity.mLauncherTaskBehind to true. Activity=%s", activity);
|
|
|
|
|
activity.mTaskSupervisor.mStoppingActivities.remove(activity);
|
|
|
|
|
activity.getDisplayContent().ensureActivitiesVisible(null /* starting */,
|
|
|
|
|
0 /* configChanges */, false /* preserveWindows */, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void restoreLaunchBehind(ActivityRecord activity) {
|
|
|
|
|
if (activity == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
activity.mDisplayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
|
|
|
|
|
|
|
|
|
|
// Restore the launch-behind state.
|
|
|
|
|
activity.mTaskSupervisor.scheduleLaunchTaskBehindComplete(activity.token);
|
|
|
|
|
activity.mLaunchTaskBehind = false;
|
|
|
|
|
ProtoLog.d(WM_DEBUG_BACK_PREVIEW,
|
|
|
|
|
"Setting Activity.mLauncherTaskBehind to false. Activity=%s",
|
|
|
|
|
activity);
|
|
|
|
|
mAnimationHandler = new AnimationHandler(wm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean isWallpaperVisible(WindowState w) {
|
|
|
|
|
return mAnimationTargets.mComposed && mShowWallpaper
|
|
|
|
|
return mAnimationHandler.mComposed && mShowWallpaper
|
|
|
|
|
&& w.mAttrs.type == TYPE_BASE_APPLICATION && w.mActivityRecord != null
|
|
|
|
|
&& mAnimationTargets.isTarget(w.mActivityRecord, true /* open */);
|
|
|
|
|
&& mAnimationHandler.isTarget(w.mActivityRecord, true /* open */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Called from WindowManagerService to write to a protocol buffer output stream.
|
|
|
|
|
|