Merge "Invoke callbacks based on back navigation type."
This commit is contained in:
@@ -337,8 +337,10 @@ interface IWindowSession {
|
||||
*
|
||||
* @param window The token for the window to set the callback to.
|
||||
* @param callback The {@link IOnBackInvokedCallback} to set.
|
||||
* @param priority The priority of the callback.
|
||||
*/
|
||||
oneway void setOnBackInvokedCallback(IWindow window, IOnBackInvokedCallback callback);
|
||||
oneway void setOnBackInvokedCallback(
|
||||
IWindow window, IOnBackInvokedCallback callback, int priority);
|
||||
|
||||
/**
|
||||
* Clears a touchable region set by {@link #setInsets}.
|
||||
|
||||
@@ -27,8 +27,6 @@ import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.MergedConfiguration;
|
||||
import android.view.InsetsState;
|
||||
import android.view.IWindow;
|
||||
import android.window.ClientWindowFrames;
|
||||
import android.window.IOnBackInvokedCallback;
|
||||
|
||||
@@ -511,7 +509,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
|
||||
@Override
|
||||
public void setOnBackInvokedCallback(IWindow iWindow,
|
||||
IOnBackInvokedCallback iOnBackInvokedCallback) throws RemoteException { }
|
||||
IOnBackInvokedCallback iOnBackInvokedCallback, int priority) throws RemoteException { }
|
||||
|
||||
@Override
|
||||
public boolean dropForAccessibility(IWindow window, int x, int y) {
|
||||
|
||||
@@ -21,9 +21,11 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteCallback;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
/**
|
||||
@@ -64,6 +66,12 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
*/
|
||||
public static final int TYPE_CALLBACK = 4;
|
||||
|
||||
/**
|
||||
* Key to access the boolean value passed in {#mOnBackNavigationDone} result bundle
|
||||
* that represents if back navigation has been triggered.
|
||||
*/
|
||||
public static final String KEY_TRIGGER_BACK = "TriggerBack";
|
||||
|
||||
/**
|
||||
* Defines the type of back destinations a back even can lead to. This is used to define the
|
||||
* type of animation that need to be run on SystemUI.
|
||||
@@ -79,13 +87,13 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
|
||||
private final int mType;
|
||||
@Nullable
|
||||
private final SurfaceControl mDepartingWindowContainer;
|
||||
private final RemoteAnimationTarget mDepartingAnimationTarget;
|
||||
@Nullable
|
||||
private final SurfaceControl mScreenshotSurface;
|
||||
@Nullable
|
||||
private final HardwareBuffer mScreenshotBuffer;
|
||||
@Nullable
|
||||
private final RemoteCallback mRemoteCallback;
|
||||
private final RemoteCallback mOnBackNavigationDone;
|
||||
@Nullable
|
||||
private final WindowConfiguration mTaskWindowConfiguration;
|
||||
@Nullable
|
||||
@@ -96,8 +104,9 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
*
|
||||
* @param type The {@link BackTargetType} of the destination (what will be
|
||||
* displayed after the back action).
|
||||
* @param topWindowLeash The leash to animate away the current topWindow. The consumer
|
||||
* of the leash is responsible for removing it.
|
||||
* @param departingAnimationTarget The remote animation target, containing a leash to animate
|
||||
* away the departing window. The consumer of the leash is
|
||||
* responsible for removing it.
|
||||
* @param screenshotSurface The screenshot of the previous activity to be displayed.
|
||||
* @param screenshotBuffer A buffer containing a screenshot used to display the activity.
|
||||
* See {@link #getScreenshotHardwareBuffer()} for information
|
||||
@@ -108,39 +117,39 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
* @param onBackInvokedCallback The back callback registered by the current top level window.
|
||||
*/
|
||||
public BackNavigationInfo(@BackTargetType int type,
|
||||
@Nullable SurfaceControl topWindowLeash,
|
||||
@Nullable RemoteAnimationTarget departingAnimationTarget,
|
||||
@Nullable SurfaceControl screenshotSurface,
|
||||
@Nullable HardwareBuffer screenshotBuffer,
|
||||
@Nullable WindowConfiguration taskWindowConfiguration,
|
||||
@Nullable RemoteCallback onBackNavigationDone,
|
||||
@Nullable IOnBackInvokedCallback onBackInvokedCallback) {
|
||||
@NonNull RemoteCallback onBackNavigationDone,
|
||||
@NonNull IOnBackInvokedCallback onBackInvokedCallback) {
|
||||
mType = type;
|
||||
mDepartingWindowContainer = topWindowLeash;
|
||||
mDepartingAnimationTarget = departingAnimationTarget;
|
||||
mScreenshotSurface = screenshotSurface;
|
||||
mScreenshotBuffer = screenshotBuffer;
|
||||
mTaskWindowConfiguration = taskWindowConfiguration;
|
||||
mRemoteCallback = onBackNavigationDone;
|
||||
mOnBackNavigationDone = onBackNavigationDone;
|
||||
mOnBackInvokedCallback = onBackInvokedCallback;
|
||||
}
|
||||
|
||||
private BackNavigationInfo(@NonNull Parcel in) {
|
||||
mType = in.readInt();
|
||||
mDepartingWindowContainer = in.readTypedObject(SurfaceControl.CREATOR);
|
||||
mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR);
|
||||
mScreenshotSurface = in.readTypedObject(SurfaceControl.CREATOR);
|
||||
mScreenshotBuffer = in.readTypedObject(HardwareBuffer.CREATOR);
|
||||
mTaskWindowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR);
|
||||
mRemoteCallback = in.readTypedObject(RemoteCallback.CREATOR);
|
||||
mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
|
||||
mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mType);
|
||||
dest.writeTypedObject(mDepartingWindowContainer, flags);
|
||||
dest.writeTypedObject(mDepartingAnimationTarget, flags);
|
||||
dest.writeTypedObject(mScreenshotSurface, flags);
|
||||
dest.writeTypedObject(mScreenshotBuffer, flags);
|
||||
dest.writeTypedObject(mTaskWindowConfiguration, flags);
|
||||
dest.writeTypedObject(mRemoteCallback, flags);
|
||||
dest.writeTypedObject(mOnBackNavigationDone, flags);
|
||||
dest.writeStrongInterface(mOnBackInvokedCallback);
|
||||
}
|
||||
|
||||
@@ -154,12 +163,13 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a leash to the top window container that needs to be animated. This can be null if
|
||||
* the back animation is controlled by the application.
|
||||
* Returns a {@link RemoteAnimationTarget}, containing a leash to the top window container
|
||||
* that needs to be animated. This can be null if the back animation is controlled by
|
||||
* the application.
|
||||
*/
|
||||
@Nullable
|
||||
public SurfaceControl getDepartingWindowContainer() {
|
||||
return mDepartingWindowContainer;
|
||||
public RemoteAnimationTarget getDepartingAnimationTarget() {
|
||||
return mDepartingAnimationTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,10 +222,14 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param triggerBack Boolean indicating if back navigation has been triggered.
|
||||
*/
|
||||
public void onBackNavigationFinished() {
|
||||
if (mRemoteCallback != null) {
|
||||
mRemoteCallback.sendResult(null);
|
||||
public void onBackNavigationFinished(boolean triggerBack) {
|
||||
if (mOnBackNavigationDone != null) {
|
||||
Bundle result = new Bundle();
|
||||
result.putBoolean(KEY_TRIGGER_BACK, triggerBack);
|
||||
mOnBackNavigationDone.sendResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,11 +254,11 @@ public final class BackNavigationInfo implements Parcelable {
|
||||
public String toString() {
|
||||
return "BackNavigationInfo{"
|
||||
+ "mType=" + typeToString(mType) + " (" + mType + ")"
|
||||
+ ", mDepartingWindowContainer=" + mDepartingWindowContainer
|
||||
+ ", mDepartingAnimationTarget=" + mDepartingAnimationTarget
|
||||
+ ", mScreenshotSurface=" + mScreenshotSurface
|
||||
+ ", mTaskWindowConfiguration= " + mTaskWindowConfiguration
|
||||
+ ", mScreenshotBuffer=" + mScreenshotBuffer
|
||||
+ ", mRemoteCallback=" + mRemoteCallback
|
||||
+ ", mOnBackNavigationDone=" + mOnBackNavigationDone
|
||||
+ ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
|
||||
+ '}';
|
||||
}
|
||||
|
||||
@@ -160,11 +160,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
}
|
||||
try {
|
||||
if (callback == null) {
|
||||
mWindowSession.setOnBackInvokedCallback(mWindow, null);
|
||||
mWindowSession.setOnBackInvokedCallback(mWindow, null, PRIORITY_DEFAULT);
|
||||
} else {
|
||||
int priority = mAllCallbacks.get(callback);
|
||||
mWindowSession.setOnBackInvokedCallback(
|
||||
mWindow, new OnBackInvokedCallbackWrapper(callback, priority));
|
||||
mWindow, new OnBackInvokedCallbackWrapper(callback, priority), priority);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to set OnBackInvokedCallback to WM. Error: " + e);
|
||||
|
||||
@@ -83,8 +83,10 @@ public class WindowOnBackInvokedDispatcherTest {
|
||||
mDispatcher.registerOnBackInvokedCallback(
|
||||
mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
|
||||
|
||||
verify(mWindowSession, times(2))
|
||||
.setOnBackInvokedCallback(Mockito.eq(mWindow), captor.capture());
|
||||
verify(mWindowSession, times(2)).setOnBackInvokedCallback(
|
||||
Mockito.eq(mWindow),
|
||||
captor.capture(),
|
||||
Mockito.eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT));
|
||||
captor.getAllValues().get(0).onBackStarted();
|
||||
waitForIdle();
|
||||
verify(mCallback1).onBackStarted();
|
||||
@@ -106,8 +108,9 @@ public class WindowOnBackInvokedDispatcherTest {
|
||||
mDispatcher.registerOnBackInvokedCallback(
|
||||
mCallback2, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
|
||||
|
||||
verify(mWindowSession)
|
||||
.setOnBackInvokedCallback(Mockito.eq(mWindow), captor.capture());
|
||||
verify(mWindowSession).setOnBackInvokedCallback(
|
||||
Mockito.eq(mWindow), captor.capture(),
|
||||
Mockito.eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY));
|
||||
verifyNoMoreInteractions(mWindowSession);
|
||||
captor.getValue().onBackStarted();
|
||||
waitForIdle();
|
||||
@@ -126,7 +129,10 @@ public class WindowOnBackInvokedDispatcherTest {
|
||||
verifyZeroInteractions(mWindowSession);
|
||||
|
||||
mDispatcher.unregisterOnBackInvokedCallback(mCallback2);
|
||||
verify(mWindowSession).setOnBackInvokedCallback(Mockito.eq(mWindow), isNull());
|
||||
verify(mWindowSession).setOnBackInvokedCallback(
|
||||
Mockito.eq(mWindow),
|
||||
isNull(),
|
||||
Mockito.eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
@@ -145,8 +151,10 @@ public class WindowOnBackInvokedDispatcherTest {
|
||||
reset(mWindowSession);
|
||||
mDispatcher.registerOnBackInvokedCallback(
|
||||
mCallback2, OnBackInvokedDispatcher.PRIORITY_OVERLAY);
|
||||
verify(mWindowSession)
|
||||
.setOnBackInvokedCallback(Mockito.eq(mWindow), captor.capture());
|
||||
verify(mWindowSession).setOnBackInvokedCallback(
|
||||
Mockito.eq(mWindow),
|
||||
captor.capture(),
|
||||
Mockito.eq(OnBackInvokedDispatcher.PRIORITY_OVERLAY));
|
||||
captor.getValue().onBackStarted();
|
||||
waitForIdle();
|
||||
verify(mCallback2).onBackStarted();
|
||||
|
||||
@@ -1567,6 +1567,12 @@
|
||||
"group": "WM_DEBUG_STATES",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"-432881038": {
|
||||
"message": "startBackNavigation task=%s, topRunningActivity=%s, applicationBackCallback=%s, systemBackCallback=%s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_BACK_PREVIEW",
|
||||
"at": "com\/android\/server\/wm\/BackNavigationController.java"
|
||||
},
|
||||
"-415865166": {
|
||||
"message": "findFocusedWindow: Found new focus @ %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -3691,12 +3697,6 @@
|
||||
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
|
||||
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
|
||||
},
|
||||
"1898905572": {
|
||||
"message": "startBackNavigation task=%s, topRunningActivity=%s, topWindow=%s backCallback=%s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_BACK_PREVIEW",
|
||||
"at": "com\/android\/server\/wm\/BackNavigationController.java"
|
||||
},
|
||||
"1903353011": {
|
||||
"message": "notifyAppStopped: %s",
|
||||
"level": "VERBOSE",
|
||||
|
||||
@@ -43,4 +43,11 @@ public interface BackAnimation {
|
||||
default IBackAnimation createExternalInterface() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the threshold values that defining edge swipe behavior.
|
||||
* @param triggerThreshold the min threshold to trigger back.
|
||||
* @param progressThreshold the max threshold to keep progressing back animation.
|
||||
*/
|
||||
void setSwipeThresholds(float triggerThreshold, float progressThreshold);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.BackEvent;
|
||||
import android.window.BackNavigationInfo;
|
||||
@@ -54,6 +55,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
|
||||
public static final boolean IS_ENABLED = SystemProperties
|
||||
.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
|
||||
private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
|
||||
"persist.debug.back_predictability_progress_threshold";
|
||||
private static final int PROGRESS_THRESHOLD = SystemProperties
|
||||
.getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
|
||||
private static final String TAG = "BackAnimationController";
|
||||
|
||||
/**
|
||||
@@ -80,6 +85,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
private final Context mContext;
|
||||
@Nullable
|
||||
private IOnBackInvokedCallback mBackToLauncherCallback;
|
||||
private float mTriggerThreshold;
|
||||
private float mProgressThreshold;
|
||||
|
||||
public BackAnimationController(
|
||||
@ShellMainThread ShellExecutor shellExecutor,
|
||||
@@ -136,6 +143,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
public void setTriggerBack(boolean triggerBack) {
|
||||
mShellExecutor.execute(() -> BackAnimationController.this.setTriggerBack(triggerBack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSwipeThresholds(float triggerThreshold, float progressThreshold) {
|
||||
mShellExecutor.execute(() -> BackAnimationController.this.setSwipeThresholds(
|
||||
triggerThreshold, progressThreshold));
|
||||
}
|
||||
}
|
||||
|
||||
private static class IBackAnimationImpl extends IBackAnimation.Stub {
|
||||
@@ -168,7 +181,8 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
}
|
||||
}
|
||||
|
||||
private void setBackToLauncherCallback(IOnBackInvokedCallback callback) {
|
||||
@VisibleForTesting
|
||||
void setBackToLauncherCallback(IOnBackInvokedCallback callback) {
|
||||
mBackToLauncherCallback = callback;
|
||||
}
|
||||
|
||||
@@ -177,6 +191,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
}
|
||||
|
||||
private void onBackToLauncherAnimationFinished() {
|
||||
if (mBackNavigationInfo != null) {
|
||||
IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
if (mTriggerBack) {
|
||||
dispatchOnBackInvoked(callback);
|
||||
} else {
|
||||
dispatchOnBackCancelled(callback);
|
||||
}
|
||||
}
|
||||
finishAnimation();
|
||||
}
|
||||
|
||||
@@ -218,19 +240,27 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
}
|
||||
|
||||
private void onBackNavigationInfoReceived(@Nullable BackNavigationInfo backNavigationInfo) {
|
||||
if (backNavigationInfo == null
|
||||
|| backNavigationInfo.getDepartingWindowContainer() == null) {
|
||||
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Received backNavigationInfo:%s", backNavigationInfo);
|
||||
if (backNavigationInfo == null) {
|
||||
Log.e(TAG, "Received BackNavigationInfo is null.");
|
||||
finishAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
HardwareBuffer hardwareBuffer = backNavigationInfo.getScreenshotHardwareBuffer();
|
||||
if (hardwareBuffer != null) {
|
||||
displayTargetScreenshot(hardwareBuffer,
|
||||
backNavigationInfo.getTaskWindowConfiguration());
|
||||
int backType = backNavigationInfo.getType();
|
||||
IOnBackInvokedCallback targetCallback = null;
|
||||
if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
|
||||
HardwareBuffer hardwareBuffer = backNavigationInfo.getScreenshotHardwareBuffer();
|
||||
if (hardwareBuffer != null) {
|
||||
displayTargetScreenshot(hardwareBuffer,
|
||||
backNavigationInfo.getTaskWindowConfiguration());
|
||||
}
|
||||
mTransaction.apply();
|
||||
} else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
|
||||
targetCallback = mBackToLauncherCallback;
|
||||
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
|
||||
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
}
|
||||
mTransaction.apply();
|
||||
dispatchOnBackStarted(targetCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,23 +302,103 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
int deltaX = Math.round(event.getX() - mInitTouchLocation.x);
|
||||
int deltaY = Math.round(event.getY() - mInitTouchLocation.y);
|
||||
ProtoLog.v(WM_SHELL_BACK_PREVIEW, "Runner move: %d %d", deltaX, deltaY);
|
||||
SurfaceControl topWindowLeash = mBackNavigationInfo.getDepartingWindowContainer();
|
||||
mTransaction.setPosition(topWindowLeash, deltaX, deltaY);
|
||||
mTouchEventDelta.set(deltaX, deltaY);
|
||||
mTransaction.apply();
|
||||
float progressThreshold = PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold;
|
||||
float progress = Math.min(Math.max(Math.abs(deltaX) / progressThreshold, 0), 1);
|
||||
int backType = mBackNavigationInfo.getType();
|
||||
RemoteAnimationTarget animationTarget = mBackNavigationInfo.getDepartingAnimationTarget();
|
||||
|
||||
BackEvent backEvent = new BackEvent(0, 0, progress, swipeEdge, animationTarget);
|
||||
IOnBackInvokedCallback targetCallback = null;
|
||||
if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME) {
|
||||
targetCallback = mBackToLauncherCallback;
|
||||
} else if (backType == BackNavigationInfo.TYPE_CROSS_TASK
|
||||
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY) {
|
||||
if (animationTarget != null) {
|
||||
mTransaction.setPosition(animationTarget.leash, deltaX, deltaY);
|
||||
mTouchEventDelta.set(deltaX, deltaY);
|
||||
mTransaction.apply();
|
||||
}
|
||||
} else if (backType == BackNavigationInfo.TYPE_CALLBACK) {
|
||||
targetCallback = mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
}
|
||||
dispatchOnBackProgressed(targetCallback, backEvent);
|
||||
}
|
||||
|
||||
private void onGestureFinished() {
|
||||
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", mTriggerBack);
|
||||
if (mBackGestureStarted) {
|
||||
if (!mBackGestureStarted || mBackNavigationInfo == null) {
|
||||
return;
|
||||
}
|
||||
int backType = mBackNavigationInfo.getType();
|
||||
boolean shouldDispatchToLauncher = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|
||||
&& mBackToLauncherCallback != null;
|
||||
IOnBackInvokedCallback targetCallback = shouldDispatchToLauncher
|
||||
? mBackToLauncherCallback
|
||||
: mBackNavigationInfo.getOnBackInvokedCallback();
|
||||
if (mTriggerBack) {
|
||||
dispatchOnBackInvoked(targetCallback);
|
||||
} else {
|
||||
dispatchOnBackCancelled(targetCallback);
|
||||
}
|
||||
if (backType == BackNavigationInfo.TYPE_CALLBACK) {
|
||||
finishAnimation();
|
||||
} else if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|
||||
&& !shouldDispatchToLauncher) {
|
||||
// Launcher callback missing. Simply finish animation.
|
||||
finishAnimation();
|
||||
} else if (backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY
|
||||
|| backType == BackNavigationInfo.TYPE_CROSS_TASK) {
|
||||
if (mTriggerBack) {
|
||||
prepareTransition();
|
||||
} else {
|
||||
resetPositionAnimated();
|
||||
}
|
||||
}
|
||||
mBackGestureStarted = false;
|
||||
mTriggerBack = false;
|
||||
}
|
||||
|
||||
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
callback.onBackStarted();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchOnBackStarted error: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dispatchOnBackInvoked(IOnBackInvokedCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
callback.onBackInvoked();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchOnBackInvoked error: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dispatchOnBackCancelled(IOnBackInvokedCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
callback.onBackCancelled();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchOnBackCancelled error: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dispatchOnBackProgressed(
|
||||
IOnBackInvokedCallback callback, BackEvent backEvent) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
callback.onBackProgressed(backEvent);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "dispatchOnBackProgressed error: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,9 +419,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
float fraction = animation1.getAnimatedFraction();
|
||||
int deltaX = Math.round(mTouchEventDelta.x - (mTouchEventDelta.x * fraction));
|
||||
int deltaY = Math.round(mTouchEventDelta.y - (mTouchEventDelta.y * fraction));
|
||||
mTransaction.setPosition(mBackNavigationInfo.getDepartingWindowContainer(),
|
||||
deltaX, deltaY);
|
||||
mTransaction.apply();
|
||||
RemoteAnimationTarget animationTarget =
|
||||
mBackNavigationInfo.getDepartingAnimationTarget();
|
||||
if (animationTarget != null) {
|
||||
mTransaction.setPosition(animationTarget.leash, deltaX, deltaY);
|
||||
mTransaction.apply();
|
||||
}
|
||||
});
|
||||
|
||||
animation.addListener(new AnimatorListenerAdapter() {
|
||||
@@ -337,25 +450,34 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
|
||||
mTriggerBack = triggerBack;
|
||||
}
|
||||
|
||||
private void setSwipeThresholds(float triggerThreshold, float progressThreshold) {
|
||||
mProgressThreshold = progressThreshold;
|
||||
mTriggerThreshold = triggerThreshold;
|
||||
}
|
||||
|
||||
private void finishAnimation() {
|
||||
ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: finishAnimation()");
|
||||
mBackGestureStarted = false;
|
||||
mTouchEventDelta.set(0, 0);
|
||||
mInitTouchLocation.set(0, 0);
|
||||
BackNavigationInfo backNavigationInfo = mBackNavigationInfo;
|
||||
boolean triggerBack = mTriggerBack;
|
||||
mBackNavigationInfo = null;
|
||||
mTriggerBack = false;
|
||||
if (backNavigationInfo == null) {
|
||||
return;
|
||||
}
|
||||
SurfaceControl topWindowLeash = backNavigationInfo.getDepartingWindowContainer();
|
||||
if (topWindowLeash != null && topWindowLeash.isValid()) {
|
||||
mTransaction.remove(topWindowLeash);
|
||||
RemoteAnimationTarget animationTarget = backNavigationInfo.getDepartingAnimationTarget();
|
||||
if (animationTarget != null && mTriggerBack) {
|
||||
if (animationTarget.leash != null && animationTarget.leash.isValid()) {
|
||||
mTransaction.remove(animationTarget.leash);
|
||||
}
|
||||
}
|
||||
SurfaceControl screenshotSurface = backNavigationInfo.getScreenshotSurface();
|
||||
if (screenshotSurface != null && screenshotSurface.isValid()) {
|
||||
mTransaction.remove(screenshotSurface);
|
||||
}
|
||||
mTransaction.apply();
|
||||
backNavigationInfo.onBackNavigationFinished();
|
||||
backNavigationInfo.onBackNavigationFinished(triggerBack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.wm.shell.back;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -24,14 +25,18 @@ import static org.mockito.Mockito.verify;
|
||||
import android.app.IActivityTaskManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.BackEvent;
|
||||
import android.window.BackNavigationInfo;
|
||||
import android.window.IOnBackInvokedCallback;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -41,6 +46,7 @@ import com.android.wm.shell.common.ShellExecutor;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@@ -62,6 +68,9 @@ public class BackAnimationControllerTest {
|
||||
@Mock
|
||||
private IActivityTaskManager mActivityTaskManager;
|
||||
|
||||
@Mock
|
||||
private IOnBackInvokedCallback mIOnBackInvokedCallback;
|
||||
|
||||
private BackAnimationController mController;
|
||||
|
||||
@Before
|
||||
@@ -71,12 +80,13 @@ public class BackAnimationControllerTest {
|
||||
mShellExecutor, mTransaction, mActivityTaskManager, mContext);
|
||||
}
|
||||
|
||||
private void createNavigationInfo(SurfaceControl topWindowLeash,
|
||||
private void createNavigationInfo(RemoteAnimationTarget topAnimationTarget,
|
||||
SurfaceControl screenshotSurface,
|
||||
HardwareBuffer hardwareBuffer) {
|
||||
HardwareBuffer hardwareBuffer,
|
||||
int backType) {
|
||||
BackNavigationInfo navigationInfo = new BackNavigationInfo(
|
||||
BackNavigationInfo.TYPE_RETURN_TO_HOME,
|
||||
topWindowLeash,
|
||||
backType,
|
||||
topAnimationTarget,
|
||||
screenshotSurface,
|
||||
hardwareBuffer,
|
||||
new WindowConfiguration(),
|
||||
@@ -89,12 +99,20 @@ public class BackAnimationControllerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void screenshotAttachedAndVisible() {
|
||||
RemoteAnimationTarget createAnimationTarget() {
|
||||
SurfaceControl topWindowLeash = new SurfaceControl();
|
||||
return new RemoteAnimationTarget(-1, RemoteAnimationTarget.MODE_CLOSING, topWindowLeash,
|
||||
false, new Rect(), new Rect(), -1,
|
||||
new Point(0, 0), new Rect(), new Rect(), new WindowConfiguration(),
|
||||
true, null, null, null, false, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void crossActivity_screenshotAttachedAndVisible() {
|
||||
SurfaceControl screenshotSurface = new SurfaceControl();
|
||||
HardwareBuffer hardwareBuffer = mock(HardwareBuffer.class);
|
||||
createNavigationInfo(topWindowLeash, screenshotSurface, hardwareBuffer);
|
||||
createNavigationInfo(createAnimationTarget(), screenshotSurface, hardwareBuffer,
|
||||
BackNavigationInfo.TYPE_CROSS_ACTIVITY);
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
@@ -104,18 +122,48 @@ public class BackAnimationControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void surfaceMovesWithGesture() {
|
||||
SurfaceControl topWindowLeash = new SurfaceControl();
|
||||
public void crossActivity_surfaceMovesWithGesture() {
|
||||
SurfaceControl screenshotSurface = new SurfaceControl();
|
||||
HardwareBuffer hardwareBuffer = mock(HardwareBuffer.class);
|
||||
createNavigationInfo(topWindowLeash, screenshotSurface, hardwareBuffer);
|
||||
RemoteAnimationTarget animationTarget = createAnimationTarget();
|
||||
createNavigationInfo(animationTarget, screenshotSurface, hardwareBuffer,
|
||||
BackNavigationInfo.TYPE_CROSS_ACTIVITY);
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
verify(mTransaction).setPosition(topWindowLeash, 100, 100);
|
||||
verify(mTransaction).setPosition(animationTarget.leash, 100, 100);
|
||||
verify(mTransaction, atLeastOnce()).apply();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backToHome_dispatchesEvents() throws RemoteException {
|
||||
mController.setBackToLauncherCallback(mIOnBackInvokedCallback);
|
||||
RemoteAnimationTarget animationTarget = createAnimationTarget();
|
||||
createNavigationInfo(animationTarget, null, null,
|
||||
BackNavigationInfo.TYPE_RETURN_TO_HOME);
|
||||
|
||||
// Check that back start is dispatched.
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
verify(mIOnBackInvokedCallback).onBackStarted();
|
||||
|
||||
// Check that back progress is dispatched.
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class);
|
||||
verify(mIOnBackInvokedCallback).onBackProgressed(backEventCaptor.capture());
|
||||
assertEquals(animationTarget, backEventCaptor.getValue().getDepartingAnimationTarget());
|
||||
|
||||
// Check that back invocation is dispatched.
|
||||
mController.setTriggerBack(true); // Fake trigger back
|
||||
mController.onMotionEvent(
|
||||
MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0),
|
||||
BackEvent.EDGE_LEFT);
|
||||
verify(mIOnBackInvokedCallback).onBackInvoked();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
<dimen name="navigation_edge_panel_height">96dp</dimen>
|
||||
<!-- The threshold to drag to trigger the edge action -->
|
||||
<dimen name="navigation_edge_action_drag_threshold">16dp</dimen>
|
||||
<!-- The threshold to progress back animation for edge swipe -->
|
||||
<dimen name="navigation_edge_action_progress_threshold">400dp</dimen>
|
||||
<!-- The minimum display position of the arrow on the screen -->
|
||||
<dimen name="navigation_edge_arrow_min_y">64dp</dimen>
|
||||
<!-- The amount by which the arrow is shifted to avoid the finger-->
|
||||
|
||||
@@ -162,7 +162,8 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
|
||||
// The amount the arrow is shifted to avoid the finger.
|
||||
private int mFingerOffset;
|
||||
|
||||
private final float mSwipeThreshold;
|
||||
private final float mSwipeTriggerThreshold;
|
||||
private final float mSwipeProgressThreshold;
|
||||
private final Path mArrowPath = new Path();
|
||||
private final Point mDisplaySize = new Point();
|
||||
|
||||
@@ -352,10 +353,15 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
|
||||
loadColors(context);
|
||||
updateArrowDirection();
|
||||
|
||||
mSwipeThreshold = context.getResources()
|
||||
mSwipeTriggerThreshold = context.getResources()
|
||||
.getDimension(R.dimen.navigation_edge_action_drag_threshold);
|
||||
setVisibility(GONE);
|
||||
mSwipeProgressThreshold = context.getResources()
|
||||
.getDimension(R.dimen.navigation_edge_action_progress_threshold);
|
||||
if (mBackAnimation != null) {
|
||||
mBackAnimation.setSwipeThresholds(mSwipeTriggerThreshold, mSwipeProgressThreshold);
|
||||
}
|
||||
|
||||
setVisibility(GONE);
|
||||
Executor backgroundExecutor = Dependency.get(Dependency.BACKGROUND_EXECUTOR);
|
||||
boolean isPrimaryDisplay = mContext.getDisplayId() == DEFAULT_DISPLAY;
|
||||
mRegionSamplingHelper = new RegionSamplingHelper(this,
|
||||
@@ -730,7 +736,7 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
|
||||
mPreviousTouchTranslation = touchTranslation;
|
||||
|
||||
// Apply a haptic on drag slop passed
|
||||
if (!mDragSlopPassed && touchTranslation > mSwipeThreshold) {
|
||||
if (!mDragSlopPassed && touchTranslation > mSwipeTriggerThreshold) {
|
||||
mDragSlopPassed = true;
|
||||
mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
|
||||
mVibrationTime = SystemClock.uptimeMillis();
|
||||
|
||||
@@ -22,11 +22,14 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.RemoteCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Slog;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.BackNavigationInfo;
|
||||
import android.window.IOnBackInvokedCallback;
|
||||
@@ -88,34 +91,39 @@ class BackNavigationController {
|
||||
ActivityRecord activityRecord;
|
||||
SurfaceControl animationLeashParent;
|
||||
WindowConfiguration taskWindowConfiguration;
|
||||
SurfaceControl animLeash;
|
||||
HardwareBuffer screenshotBuffer = null;
|
||||
int prevTaskId;
|
||||
int prevUserId;
|
||||
IOnBackInvokedCallback callback;
|
||||
IOnBackInvokedCallback applicationCallback = null;
|
||||
IOnBackInvokedCallback systemCallback = null;
|
||||
RemoteAnimationTarget topAppTarget;
|
||||
SurfaceControl animLeash;
|
||||
|
||||
synchronized (task.mWmService.mGlobalLock) {
|
||||
activityRecord = task.topRunningActivity();
|
||||
removedWindowContainer = activityRecord;
|
||||
taskWindowConfiguration = task.getTaskInfo().configuration.windowConfiguration;
|
||||
|
||||
WindowState topChild = activityRecord.getTopChild();
|
||||
callback = topChild.getOnBackInvokedCallback();
|
||||
WindowState window = task.getWindow(WindowState::isFocused);
|
||||
if (window != null) {
|
||||
applicationCallback = window.getApplicationOnBackInvokedCallback();
|
||||
systemCallback = window.getSystemOnBackInvokedCallback();
|
||||
}
|
||||
|
||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, "
|
||||
+ "topRunningActivity=%s, topWindow=%s backCallback=%s",
|
||||
task, activityRecord, topChild,
|
||||
callback != null ? callback.getClass().getSimpleName() : null);
|
||||
+ "topRunningActivity=%s, applicationBackCallback=%s, "
|
||||
+ "systemBackCallback=%s",
|
||||
task, activityRecord, applicationCallback, systemCallback);
|
||||
|
||||
// For IME and Home, either a callback is registered, or we do nothing. In both cases,
|
||||
// we don't need to pass the leashes below.
|
||||
if (task.getDisplayContent().getImeContainer().isVisible()
|
||||
|| activityRecord.isActivityTypeHome()) {
|
||||
if (callback != null) {
|
||||
if (applicationCallback != null) {
|
||||
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
||||
null /* topWindowLeash */, null /* screenshotSurface */,
|
||||
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
||||
null /* onBackNavigationDone */, callback /* onBackInvokedCallback */);
|
||||
null /* onBackNavigationDone */,
|
||||
applicationCallback /* onBackInvokedCallback */);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -124,8 +132,12 @@ class BackNavigationController {
|
||||
prev = task.getActivity(
|
||||
(r) -> !r.finishing && r.getTask() == task && !r.isTopRunningActivity());
|
||||
|
||||
if (callback != null) {
|
||||
backType = BackNavigationInfo.TYPE_CALLBACK;
|
||||
if (applicationCallback != null) {
|
||||
return new BackNavigationInfo(BackNavigationInfo.TYPE_CALLBACK,
|
||||
null /* topWindowLeash */, null /* screenshotSurface */,
|
||||
null /* screenshotBuffer */, null /* taskWindowConfiguration */,
|
||||
null /* onBackNavigationDone */,
|
||||
applicationCallback /* onBackInvokedCallback */);
|
||||
} else if (prev != null) {
|
||||
backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
|
||||
} else if (task.returnsToHomeRootTask()) {
|
||||
@@ -159,6 +171,11 @@ class BackNavigationController {
|
||||
screenshotBuffer = getActivitySnapshot(task, prev.mActivityComponent);
|
||||
}
|
||||
|
||||
// Only create a new leash if no leash has been created.
|
||||
// Otherwise return null for animation target to avoid conflict.
|
||||
if (removedWindowContainer.hasCommittedReparentToAnimationLeash()) {
|
||||
return null;
|
||||
}
|
||||
// Prepare a leash to animate the current top window
|
||||
animLeash = removedWindowContainer.makeAnimationLeash()
|
||||
.setName("BackPreview Leash for " + removedWindowContainer)
|
||||
@@ -166,8 +183,25 @@ class BackNavigationController {
|
||||
.setBLASTLayer()
|
||||
.build();
|
||||
removedWindowContainer.reparentSurfaceControl(tx, animLeash);
|
||||
|
||||
animationLeashParent = removedWindowContainer.getAnimationLeashParent();
|
||||
topAppTarget = new RemoteAnimationTarget(
|
||||
task.mTaskId,
|
||||
RemoteAnimationTarget.MODE_CLOSING,
|
||||
animLeash,
|
||||
false /* isTransluscent */,
|
||||
new Rect() /* clipRect */,
|
||||
new Rect() /* contentInsets */,
|
||||
activityRecord.getPrefixOrderIndex(),
|
||||
new Point(0, 0) /* position */,
|
||||
new Rect() /* localBounds */,
|
||||
new Rect() /* screenSpaceBounds */,
|
||||
removedWindowContainer.getWindowConfiguration(),
|
||||
true /* isNotInRecent */,
|
||||
null,
|
||||
null,
|
||||
task.getTaskInfo(),
|
||||
false,
|
||||
activityRecord.windowType);
|
||||
}
|
||||
|
||||
SurfaceControl.Builder builder = new SurfaceControl.Builder()
|
||||
@@ -187,7 +221,7 @@ class BackNavigationController {
|
||||
|
||||
// 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.
|
||||
tx.setLayer(animLeash, 1);
|
||||
tx.setLayer(topAppTarget.leash, 1);
|
||||
tx.apply();
|
||||
|
||||
WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer;
|
||||
@@ -200,11 +234,13 @@ class BackNavigationController {
|
||||
return null;
|
||||
}
|
||||
|
||||
final IOnBackInvokedCallback callback =
|
||||
applicationCallback != null ? applicationCallback : systemCallback;
|
||||
RemoteCallback onBackNavigationDone = new RemoteCallback(
|
||||
result -> resetSurfaces(finalRemovedWindowContainer
|
||||
));
|
||||
return new BackNavigationInfo(backType,
|
||||
animLeash,
|
||||
topAppTarget,
|
||||
screenshotSurface,
|
||||
screenshotBuffer,
|
||||
taskWindowConfiguration,
|
||||
|
||||
@@ -69,6 +69,7 @@ import android.view.InputChannel;
|
||||
import android.view.InsetsSourceControl;
|
||||
import android.view.InsetsState;
|
||||
import android.view.InsetsVisibilities;
|
||||
import android.view.OnBackInvokedDispatcher;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceSession;
|
||||
import android.view.View;
|
||||
@@ -905,15 +906,17 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnBackInvokedCallback(IWindow window,
|
||||
IOnBackInvokedCallback onBackInvokedCallback) throws RemoteException {
|
||||
public void setOnBackInvokedCallback(
|
||||
IWindow window,
|
||||
IOnBackInvokedCallback onBackInvokedCallback,
|
||||
@OnBackInvokedDispatcher.Priority int priority) throws RemoteException {
|
||||
synchronized (mService.mGlobalLock) {
|
||||
WindowState windowState = mService.windowForClientLocked(this, window, false);
|
||||
if (windowState == null) {
|
||||
Slog.e(TAG_WM,
|
||||
"setOnBackInvokedCallback(): Can't find window state for window:" + window);
|
||||
} else {
|
||||
windowState.setOnBackInvokedCallback(onBackInvokedCallback);
|
||||
windowState.setOnBackInvokedCallback(onBackInvokedCallback, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,7 +850,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
/**
|
||||
* @see #setOnBackInvokedCallback(IOnBackInvokedCallback)
|
||||
*/
|
||||
private IOnBackInvokedCallback mOnBackInvokedCallback;
|
||||
private IOnBackInvokedCallback mApplicationOnBackInvokedCallback;
|
||||
private IOnBackInvokedCallback mSystemOnBackInvokedCallback;
|
||||
|
||||
@Override
|
||||
WindowState asWindowState() {
|
||||
@@ -1073,15 +1074,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* called when a back navigation action is initiated.
|
||||
* @see BackNavigationController
|
||||
*/
|
||||
void setOnBackInvokedCallback(@Nullable IOnBackInvokedCallback onBackInvokedCallback) {
|
||||
void setOnBackInvokedCallback(
|
||||
@Nullable IOnBackInvokedCallback onBackInvokedCallback, int priority) {
|
||||
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "%s: Setting back callback %s",
|
||||
this, onBackInvokedCallback);
|
||||
mOnBackInvokedCallback = onBackInvokedCallback;
|
||||
if (priority >= 0) {
|
||||
mApplicationOnBackInvokedCallback = onBackInvokedCallback;
|
||||
} else {
|
||||
mSystemOnBackInvokedCallback = onBackInvokedCallback;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
IOnBackInvokedCallback getOnBackInvokedCallback() {
|
||||
return mOnBackInvokedCallback;
|
||||
IOnBackInvokedCallback getApplicationOnBackInvokedCallback() {
|
||||
return mApplicationOnBackInvokedCallback;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
IOnBackInvokedCallback getSystemOnBackInvokedCallback() {
|
||||
return mSystemOnBackInvokedCallback;
|
||||
}
|
||||
|
||||
interface PowerManagerWrapper {
|
||||
@@ -2385,7 +2396,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
dc.getDisplayPolicy().removeWindowLw(this);
|
||||
|
||||
disposeInputChannel();
|
||||
mOnBackInvokedCallback = null;
|
||||
mSystemOnBackInvokedCallback = null;
|
||||
mApplicationOnBackInvokedCallback = null;
|
||||
|
||||
mSession.windowRemovedLocked();
|
||||
try {
|
||||
@@ -2439,7 +2451,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
|
||||
try {
|
||||
disposeInputChannel();
|
||||
mOnBackInvokedCallback = null;
|
||||
mSystemOnBackInvokedCallback = null;
|
||||
mApplicationOnBackInvokedCallback = null;
|
||||
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
|
||||
"Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b "
|
||||
|
||||
@@ -97,7 +97,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
|
||||
BackNavigationInfo backNavigationInfo =
|
||||
mBackNavigationController.startBackNavigation(task, new StubTransaction());
|
||||
assertThat(backNavigationInfo).isNotNull();
|
||||
assertThat(backNavigationInfo.getDepartingWindowContainer()).isNotNull();
|
||||
assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull();
|
||||
assertThat(backNavigationInfo.getScreenshotSurface()).isNotNull();
|
||||
assertThat(backNavigationInfo.getScreenshotHardwareBuffer()).isNotNull();
|
||||
assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull();
|
||||
|
||||
Reference in New Issue
Block a user