diff options
8 files changed, 302 insertions, 26 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 4dbdd91d5fc7..2cd7aeb2d99d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -16,6 +16,7 @@ package android.inputmethodservice; +import static android.view.inputmethod.Flags.predictiveBackIme; import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VIEW_STARTED; import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VISIBILITY; import static android.inputmethodservice.InputMethodServiceProto.CONFIGURATION; @@ -3098,7 +3099,7 @@ public class InputMethodService extends AbstractInputMethodService { cancelImeSurfaceRemoval(); mInShowWindow = false; Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); - registerCompatOnBackInvokedCallback(); + registerDefaultOnBackInvokedCallback(); } @@ -3107,18 +3108,27 @@ public class InputMethodService extends AbstractInputMethodService { * back dispatching is enabled. We keep the {@link KeyEvent#KEYCODE_BACK} based legacy code * around to handle back on older devices. */ - private void registerCompatOnBackInvokedCallback() { + private void registerDefaultOnBackInvokedCallback() { if (mBackCallbackRegistered) { return; } if (mWindow != null) { - mWindow.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( - OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatBackCallback); + if (getApplicationInfo().isOnBackInvokedCallbackEnabled() && predictiveBackIme()) { + // Register the compat callback as system-callback if IME has opted in for + // predictive back (and predictiveBackIme feature flag is enabled). This indicates + // to the receiving process (application process) that a predictive IME dismiss + // animation may be played instead of invoking the callback. + mWindow.getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback( + mCompatBackCallback); + } else { + mWindow.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatBackCallback); + } mBackCallbackRegistered = true; } } - private void unregisterCompatOnBackInvokedCallback() { + private void unregisterDefaultOnBackInvokedCallback() { if (!mBackCallbackRegistered) { return; } @@ -3251,7 +3261,7 @@ public class InputMethodService extends AbstractInputMethodService { } mLastWasInFullscreenMode = mIsFullscreen; updateFullscreenMode(); - unregisterCompatOnBackInvokedCallback(); + unregisterDefaultOnBackInvokedCallback(); } /** @@ -3328,7 +3338,7 @@ public class InputMethodService extends AbstractInputMethodService { // Back callback is typically unregistered in {@link #hideWindow()}, but it's possible // for {@link #doFinishInput()} to be called without {@link #hideWindow()} so we also // unregister here. - unregisterCompatOnBackInvokedCallback(); + unregisterDefaultOnBackInvokedCallback(); } void doStartInput(InputConnection ic, EditorInfo editorInfo, boolean restarting) { @@ -4473,7 +4483,7 @@ public class InputMethodService extends AbstractInputMethodService { private void compatHandleBack() { if (!mDecorViewVisible) { Log.e(TAG, "Back callback invoked on a hidden IME. Removing the callback..."); - unregisterCompatOnBackInvokedCallback(); + unregisterDefaultOnBackInvokedCallback(); return; } final KeyEvent downEvent = createBackKeyEvent( diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java new file mode 100644 index 000000000000..d14e858d9fa1 --- /dev/null +++ b/core/java/android/view/ImeBackAnimationController.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2024 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 android.view; + +import static android.view.InsetsController.ANIMATION_TYPE_USER; +import static android.view.WindowInsets.Type.ime; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; +import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.graphics.Insets; +import android.util.Log; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; +import android.window.BackEvent; +import android.window.OnBackAnimationCallback; + +/** + * Controller for IME predictive back animation + * + * @hide + */ +public class ImeBackAnimationController implements OnBackAnimationCallback { + + private static final String TAG = "ImeBackAnimationController"; + private static final int POST_COMMIT_DURATION_MS = 200; + private static final int POST_COMMIT_CANCEL_DURATION_MS = 50; + private static final float PEEK_FRACTION = 0.1f; + private static final Interpolator STANDARD_DECELERATE = new PathInterpolator(0f, 0f, 0f, 1f); + private static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator( + 0.05f, 0.7f, 0.1f, 1f); + private static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(0.3f, 0f, 1f, 1f); + + private final InsetsController mInsetsController; + private final ViewRootImpl mViewRoot; + private WindowInsetsAnimationController mWindowInsetsAnimationController = null; + private ValueAnimator mPostCommitAnimator = null; + private float mLastProgress = 0f; + private boolean mTriggerBack = false; + private boolean mIsPreCommitAnimationInProgress = false; + + public ImeBackAnimationController(ViewRootImpl viewRoot) { + mInsetsController = viewRoot.getInsetsController(); + mViewRoot = viewRoot; + } + + @Override + public void onBackStarted(@NonNull BackEvent backEvent) { + if (isAdjustResize()) { + // There is no good solution for a predictive back animation if the app uses + // adjustResize, since we can't relayout the whole app for every frame. We also don't + // want to reveal any black areas behind the IME. Therefore let's not play any animation + // in that case for now. + Log.d(TAG, "onBackStarted -> not playing predictive back animation due to softinput" + + " mode adjustResize"); + return; + } + if (isHideAnimationInProgress()) { + // If IME is currently animating away, skip back gesture + return; + } + mIsPreCommitAnimationInProgress = true; + if (mWindowInsetsAnimationController != null) { + // There's still an active animation controller. This means that a cancel post commit + // animation of an earlier back gesture is still in progress. Let's cancel it and let + // the new gesture seamlessly take over. + resetPostCommitAnimator(); + setPreCommitProgress(0f); + return; + } + mInsetsController.controlWindowInsetsAnimation(ime(), /*cancellationSignal*/ null, + new WindowInsetsAnimationControlListener() { + @Override + public void onReady(@NonNull WindowInsetsAnimationController controller, + @WindowInsets.Type.InsetsType int types) { + mWindowInsetsAnimationController = controller; + if (mIsPreCommitAnimationInProgress) { + setPreCommitProgress(mLastProgress); + } else { + // gesture has already finished before IME became ready to animate + startPostCommitAnim(mTriggerBack); + } + } + + @Override + public void onFinished(@NonNull WindowInsetsAnimationController controller) { + reset(); + } + + @Override + public void onCancelled(@Nullable WindowInsetsAnimationController controller) { + reset(); + } + }, /*fromIme*/ false, /*durationMs*/ -1, /*interpolator*/ null, ANIMATION_TYPE_USER, + /*fromPredictiveBack*/ true); + } + + @Override + public void onBackProgressed(@NonNull BackEvent backEvent) { + mLastProgress = backEvent.getProgress(); + setPreCommitProgress(mLastProgress); + } + + @Override + public void onBackCancelled() { + if (isAdjustResize()) return; + startPostCommitAnim(/*hideIme*/ false); + } + + @Override + public void onBackInvoked() { + if (isAdjustResize()) { + mInsetsController.hide(ime()); + return; + } + startPostCommitAnim(/*hideIme*/ true); + } + + private void setPreCommitProgress(float progress) { + if (isHideAnimationInProgress()) return; + if (mWindowInsetsAnimationController != null) { + float hiddenY = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; + float shownY = mWindowInsetsAnimationController.getShownStateInsets().bottom; + float imeHeight = shownY - hiddenY; + float interpolatedProgress = STANDARD_DECELERATE.getInterpolation(progress); + int newY = (int) (imeHeight - interpolatedProgress * (imeHeight * PEEK_FRACTION)); + mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, newY), 1f, + progress); + } + } + + private void startPostCommitAnim(boolean triggerBack) { + mIsPreCommitAnimationInProgress = false; + if (mWindowInsetsAnimationController == null || isHideAnimationInProgress()) { + mTriggerBack = triggerBack; + return; + } + mTriggerBack = triggerBack; + int currentBottomInset = mWindowInsetsAnimationController.getCurrentInsets().bottom; + int targetBottomInset; + if (triggerBack) { + targetBottomInset = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; + } else { + targetBottomInset = mWindowInsetsAnimationController.getShownStateInsets().bottom; + } + mPostCommitAnimator = ValueAnimator.ofFloat(currentBottomInset, targetBottomInset); + mPostCommitAnimator.setInterpolator( + triggerBack ? STANDARD_ACCELERATE : EMPHASIZED_DECELERATE); + mPostCommitAnimator.addUpdateListener(animation -> { + int bottomInset = (int) ((float) animation.getAnimatedValue()); + if (mWindowInsetsAnimationController != null) { + mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, bottomInset), + 1f, animation.getAnimatedFraction()); + } else { + reset(); + } + }); + mPostCommitAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + if (mIsPreCommitAnimationInProgress) { + // this means a new gesture has started while the cancel-post-commit-animation + // was in progress. Let's not reset anything and let the new user gesture take + // over seamlessly + return; + } + if (mWindowInsetsAnimationController != null) { + mWindowInsetsAnimationController.finish(!triggerBack); + } + reset(); + } + }); + mPostCommitAnimator.setDuration( + triggerBack ? POST_COMMIT_DURATION_MS : POST_COMMIT_CANCEL_DURATION_MS); + mPostCommitAnimator.start(); + } + + private void reset() { + mWindowInsetsAnimationController = null; + resetPostCommitAnimator(); + mLastProgress = 0f; + mTriggerBack = false; + mIsPreCommitAnimationInProgress = false; + } + + private void resetPostCommitAnimator() { + if (mPostCommitAnimator != null) { + mPostCommitAnimator.cancel(); + mPostCommitAnimator = null; + } + } + + private boolean isAdjustResize() { + return (mViewRoot.mWindowAttributes.softInputMode & SOFT_INPUT_MASK_ADJUST) + == SOFT_INPUT_ADJUST_RESIZE; + } + + private boolean isHideAnimationInProgress() { + return mPostCommitAnimator != null && mTriggerBack; + } + +} diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 2fcffd06db62..90aafbdb164d 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -29,6 +29,8 @@ import static android.view.WindowInsets.Type.all; import static android.view.WindowInsets.Type.captionBar; import static android.view.WindowInsets.Type.ime; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; + import android.animation.AnimationHandler; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -322,7 +324,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public static final int ANIMATION_TYPE_HIDE = 1; /** Running animation is controlled by user via {@link #controlWindowInsetsAnimation} */ - @VisibleForTesting + @VisibleForTesting(visibility = PACKAGE) public static final int ANIMATION_TYPE_USER = 2; /** Running animation will resize insets */ @@ -1076,7 +1078,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation show(types, false /* fromIme */, null /* statsToken */); } - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + @VisibleForTesting(visibility = PACKAGE) public void show(@InsetsType int types, boolean fromIme, @Nullable ImeTracker.Token statsToken) { if ((types & ime()) != 0) { @@ -1260,14 +1262,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @Nullable CancellationSignal cancellationSignal, @NonNull WindowInsetsAnimationControlListener listener) { controlWindowInsetsAnimation(types, cancellationSignal, listener, - false /* fromIme */, durationMillis, interpolator, ANIMATION_TYPE_USER); + false /* fromIme */, durationMillis, interpolator, ANIMATION_TYPE_USER, + false /* fromPredictiveBack */); } - private void controlWindowInsetsAnimation(@InsetsType int types, + void controlWindowInsetsAnimation(@InsetsType int types, @Nullable CancellationSignal cancellationSignal, WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs, @Nullable Interpolator interpolator, - @AnimationType int animationType) { + @AnimationType int animationType, boolean fromPredictiveBack) { if ((mState.calculateUncontrollableInsetsFromFrame(mFrame) & types) != 0) { listener.onCancelled(null); return; @@ -1279,7 +1282,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, - interpolator, animationType, getLayoutInsetsDuringAnimationMode(types), + interpolator, animationType, + getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null /* statsToken */); } @@ -1526,7 +1530,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode( - @InsetsType int types) { + @InsetsType int types, boolean fromPredictiveBack) { + if (fromPredictiveBack) { + // When insets are animated by predictive back, we want insets to be shown to prevent a + // jump cut from shown to hidden at the start of the predictive back animation + return LAYOUT_INSETS_DURING_ANIMATION_SHOWN; + } // Generally, we want to layout the opposite of the current state. This is to make animation // callbacks easy to use: The can capture the layout values and then treat that as end-state // during the animation. @@ -1730,7 +1739,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return ANIMATION_TYPE_NONE; } - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + @VisibleForTesting(visibility = PACKAGE) public void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) { final @InsetsType int requestedVisibleTypes = (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a0733d445257..49d4af8a3e61 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -115,6 +115,7 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INSETS_CONTROLLER; import static com.android.input.flags.Flags.enablePointerChoreographer; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.window.flags.Flags.activityWindowInfoFlag; import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay; import static com.android.window.flags.Flags.setScPropertiesInClient; @@ -942,6 +943,7 @@ public final class ViewRootImpl implements ViewParent, new InputEventConsistencyVerifier(this, 0) : null; private final InsetsController mInsetsController; + private final ImeBackAnimationController mImeBackAnimationController; private final ImeFocusController mImeFocusController; private boolean mIsSurfaceOpaque; @@ -1206,6 +1208,7 @@ public final class ViewRootImpl implements ViewParent, // TODO(b/222696368): remove getSfInstance usage and use vsyncId for transactions mChoreographer = Choreographer.getInstance(); mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this)); + mImeBackAnimationController = new ImeBackAnimationController(this); mHandwritingInitiator = new HandwritingInitiator( mViewConfiguration, mContext.getSystemService(InputMethodManager.class)); @@ -3181,7 +3184,7 @@ public final class ViewRootImpl implements ViewParent, == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; } - @VisibleForTesting + @VisibleForTesting(visibility = PACKAGE) public InsetsController getInsetsController() { return mInsetsController; } @@ -12148,7 +12151,8 @@ public final class ViewRootImpl implements ViewParent, + "IWindow:%s Session:%s", mOnBackInvokedDispatcher, mBasePackageName, mWindow, mWindowSession)); } - mOnBackInvokedDispatcher.attachToWindow(mWindowSession, mWindow); + mOnBackInvokedDispatcher.attachToWindow(mWindowSession, mWindow, + mImeBackAnimationController); } private void sendBackKeyEvent(int action) { diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java index 0cc9a0d75154..da1993d9251c 100644 --- a/core/java/android/window/ImeOnBackInvokedDispatcher.java +++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java @@ -148,8 +148,17 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc @OnBackInvokedDispatcher.Priority int priority, int callbackId, @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) { - final ImeOnBackInvokedCallback imeCallback = - new ImeOnBackInvokedCallback(iCallback, callbackId, priority); + final ImeOnBackInvokedCallback imeCallback; + if (priority == PRIORITY_SYSTEM) { + // A callback registration with PRIORITY_SYSTEM indicates that a predictive back + // animation can be played on the IME. Therefore register the + // DefaultImeOnBackInvokedCallback with the receiving dispatcher and override the + // priority to PRIORITY_DEFAULT. + priority = PRIORITY_DEFAULT; + imeCallback = new DefaultImeOnBackAnimationCallback(iCallback, callbackId, priority); + } else { + imeCallback = new ImeOnBackInvokedCallback(iCallback, callbackId, priority); + } mImeCallbacks.add(imeCallback); receivingDispatcher.registerOnBackInvokedCallbackUnchecked(imeCallback, priority); } @@ -230,6 +239,17 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc } /** + * Subclass of ImeOnBackInvokedCallback indicating that a predictive IME back animation may be + * played instead of invoking the callback. + */ + static class DefaultImeOnBackAnimationCallback extends ImeOnBackInvokedCallback { + DefaultImeOnBackAnimationCallback(@NonNull IOnBackInvokedCallback iCallback, int id, + int priority) { + super(iCallback, id, priority); + } + } + + /** * Transfers {@link ImeOnBackInvokedCallback}s registered on one {@link ViewRootImpl} to * another {@link ViewRootImpl} on focus change. * diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 45d7767380a1..bcbac9319887 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -31,6 +31,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.IWindow; import android.view.IWindowSession; +import android.view.ImeBackAnimationController; import androidx.annotation.VisibleForTesting; @@ -71,6 +72,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @Nullable private ImeOnBackInvokedDispatcher mImeDispatcher; + @Nullable + private ImeBackAnimationController mImeBackAnimationController; + /** Convenience hashmap to quickly decide if a callback has been added. */ private final HashMap<OnBackInvokedCallback, Integer> mAllCallbacks = new HashMap<>(); /** Holds all callbacks by priorities. */ @@ -88,9 +92,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { * Sends the pending top callback (if one exists) to WM when the view root * is attached a window. */ - public void attachToWindow(@NonNull IWindowSession windowSession, @NonNull IWindow window) { + public void attachToWindow(@NonNull IWindowSession windowSession, @NonNull IWindow window, + @Nullable ImeBackAnimationController imeBackAnimationController) { mWindowSession = windowSession; mWindow = window; + mImeBackAnimationController = imeBackAnimationController; if (!mAllCallbacks.isEmpty()) { setTopOnBackInvokedCallback(getTopCallback()); } @@ -101,6 +107,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { clear(); mWindow = null; mWindowSession = null; + mImeBackAnimationController = null; } // TODO: Take an Executor for the callback to run on. @@ -125,6 +132,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { if (!mOnBackInvokedCallbacks.containsKey(priority)) { mOnBackInvokedCallbacks.put(priority, new ArrayList<>()); } + if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { + callback = mImeBackAnimationController; + } ArrayList<OnBackInvokedCallback> callbacks = mOnBackInvokedCallbacks.get(priority); // If callback has already been added, remove it and re-add it. @@ -152,6 +162,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.unregisterOnBackInvokedCallback(callback); return; } + if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { + callback = mImeBackAnimationController; + } if (!mAllCallbacks.containsKey(callback)) { if (DEBUG) { Log.i(TAG, "Callback not found. returning..."); @@ -199,7 +212,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } else { Log.w(TAG, "sendCancelIfRunning: isInProgress=" + isInProgress - + "callback=" + callback); + + " callback=" + callback); } } @@ -243,9 +256,9 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { int priority = mAllCallbacks.get(callback); final IOnBackInvokedCallback iCallback = callback instanceof ImeOnBackInvokedDispatcher - .ImeOnBackInvokedCallback + .ImeOnBackInvokedCallback ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback) - callback).getIOnBackInvokedCallback() + callback).getIOnBackInvokedCallback() : new OnBackInvokedCallbackWrapper( callback, mProgressAnimator, diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java index a709d7be898b..6321e5d97589 100644 --- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java @@ -96,7 +96,7 @@ public class WindowOnBackInvokedDispatcherTest { doReturn(mApplicationInfo).when(mContext).getApplicationInfo(); mDispatcher = new WindowOnBackInvokedDispatcher(mContext); - mDispatcher.attachToWindow(mWindowSession, mWindow); + mDispatcher.attachToWindow(mWindowSession, mWindow, null); } private void waitForIdle() { diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java index 363ae141e512..21251c33569c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -537,7 +537,7 @@ public class BackNavigationControllerTests extends WindowTestsBase { }).when(appWindow.mSession).setOnBackInvokedCallbackInfo(eq(appWindow.mClient), any()); addToWindowMap(appWindow, true); - dispatcher.attachToWindow(appWindow.mSession, appWindow.mClient); + dispatcher.attachToWindow(appWindow.mSession, appWindow.mClient, null); OnBackInvokedCallback appCallback = createBackCallback(appLatch); |