Split animation methods out of OnBackInvokedCallback

This makes OnBackInvokedCallback SAM compatible

Bug: 227789359
Test: atest \
        CtsWindowManagerDeviceTestCases:android.server.wm.BackNavigationLegacyTest \
        CtsWindowManagerDeviceTestCases:android.server.wm.BackNavigationTests \
        WmTests:com.android.server.wm.BackNavigationControllerTests \
        FrameworksCoreTests:android.window.BackNavigationTest \
        FrameworksCoreTests:android.window.WindowOnBackInvokedDispatcherTest \
        CtsViewTestCases:android.view.cts.OnBackInvokedDispatcherTest
Change-Id: Iab86b0488f1b3048eb02042191acaeb6a645a0bc
This commit is contained in:
Vadim Caen 2022-03-31 18:29:26 +02:00
parent 924b02bb03
commit c627777dda
11 changed files with 97 additions and 83 deletions

View File

@ -57974,7 +57974,7 @@ package android.widget.inline {
package android.window {
public interface OnBackInvokedCallback {
method public default void onBackInvoked();
method public void onBackInvoked();
}
public interface OnBackInvokedDispatcher {

View File

@ -1663,12 +1663,7 @@ public class Activity extends ContextThemeWrapper
.isOnBackInvokedCallbackEnabled(this);
if (aheadOfTimeBack) {
// Add onBackPressed as default back behavior.
mDefaultBackCallback = new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
navigateBack();
}
};
mDefaultBackCallback = this::navigateBack;
getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
}
}

View File

@ -459,12 +459,7 @@ public class Dialog implements DialogInterface, Window.Callback,
if (mContext != null
&& WindowOnBackInvokedDispatcher.isOnBackInvokedCallbackEnabled(mContext)) {
// Add onBackPressed as default back behavior.
mDefaultBackCallback = new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
onBackPressed();
}
};
mDefaultBackCallback = this::onBackPressed;
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mDefaultBackCallback);
mDefaultBackCallback = null;

View File

@ -10765,12 +10765,9 @@ public final class ViewRootImpl implements ViewParent,
}
private void registerCompatOnBackInvokedCallback() {
mCompatOnBackInvokedCallback = new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
mCompatOnBackInvokedCallback = () -> {
sendBackKeyEvent(KeyEvent.ACTION_DOWN);
sendBackKeyEvent(KeyEvent.ACTION_UP);
}
};
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);

View File

@ -240,12 +240,7 @@ public class Editor {
private final boolean mHapticTextHandleEnabled;
/** Handles OnBackInvokedCallback back dispatch */
private final OnBackInvokedCallback mBackCallback = new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
stopTextActionMode();
}
};
private final OnBackInvokedCallback mBackCallback = this::stopTextActionMode;
private boolean mBackCallbackRegistered;
@Nullable

View File

@ -122,12 +122,7 @@ public class MediaController extends FrameLayout {
private final AccessibilityManager mAccessibilityManager;
private boolean mBackCallbackRegistered;
/** Handles back invocation */
private final OnBackInvokedCallback mBackCallback = new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
hide();
}
};
private final OnBackInvokedCallback mBackCallback = this::hide;
/** Handles decor view attach state change */
private final OnAttachStateChangeListener mAttachStateListener =
new OnAttachStateChangeListener() {

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.Dialog;
import android.view.View;
/**
* Interface for applications to register back animation callbacks along their custom back
* handling.
* <p>
* This allows the client to customize various back behaviors by overriding the corresponding
* callback methods.
* <p>
* Callback instances can be added to and removed from {@link OnBackInvokedDispatcher}, held
* by classes that implement {@link OnBackInvokedDispatcherOwner} (such as {@link Activity},
* {@link Dialog} and {@link View}).
* <p>
* When back is triggered, callbacks on the in-focus window are invoked in reverse order in which
* they are added within the same priority. Between different priorities, callbacks with higher
* priority are invoked first.
* <p>
* @see OnBackInvokedCallback
* @hide
*/
public interface OnBackAnimationCallback extends OnBackInvokedCallback {
/**
* Called when a back gesture has been started, or back button has been pressed down.
*/
default void onBackStarted() { }
/**
* Called on back gesture progress.
*
* @param backEvent An {@link BackEvent} object describing the progress event.
*
* @see BackEvent
*/
default void onBackProgressed(@NonNull BackEvent backEvent) { }
/**
* Called when a back gesture or back button press has been cancelled.
*/
default void onBackCancelled() { }
}

View File

@ -21,49 +21,29 @@ import android.app.Dialog;
import android.view.View;
/**
* Interface for applications to register back invocation callbacks. This allows the client
* to customize various back behaviors by overriding the corresponding callback methods.
*
* Callback allowing applications to handle back events in place of the system.
* <p>
* Callback instances can be added to and removed from {@link OnBackInvokedDispatcher}, held
* by classes that implement {@link OnBackInvokedDispatcherOwner} (such as {@link Activity},
* {@link Dialog} and {@link View}).
*
* <p>
* Under the hood callbacks are registered at window level. When back is triggered,
* callbacks on the in-focus window are invoked in reverse order in which they are added
* within the same priority. Between different pirorities, callbacks with higher priority
* are invoked first.
* <p>
* This replaces {@link Activity#onBackPressed()}, {@link Dialog#onBackPressed()} and
* {@link android.view.KeyEvent#KEYCODE_BACK}
*
* See {@link OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback)}
* for specifying callback priority.
* @see OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback)
* registerOnBackInvokedCallback(priority, OnBackInvokedCallback)
* to specify callback priority.
*/
@SuppressWarnings("deprecation")
public interface OnBackInvokedCallback {
/**
* Called when a back gesture has been started, or back button has been pressed down.
*
* @hide
*/
default void onBackStarted() { };
/**
* Called on back gesture progress.
*
* @param backEvent An {@link android.window.BackEvent} object describing the progress event.
*
* @see android.window.BackEvent
* @hide
*/
default void onBackProgressed(BackEvent backEvent) { };
/**
* Called when a back gesture or back button press has been cancelled.
*
* @hide
*/
default void onBackCancelled() { };
/**
* Called when a back gesture has been completed and committed, or back button pressed
* has been released and committed.
*/
default void onBackInvoked() { };
void onBackInvoked();
}

View File

@ -199,36 +199,30 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
@Override
public void onBackStarted() {
Handler.getMain().post(() -> {
final OnBackInvokedCallback callback = mCallback.get();
if (callback == null) {
return;
final OnBackAnimationCallback callback = getBackAnimationCallback();
if (callback != null) {
callback.onBackStarted();
}
callback.onBackStarted();
});
}
@Override
public void onBackProgressed(BackEvent backEvent) {
Handler.getMain().post(() -> {
final OnBackInvokedCallback callback = mCallback.get();
if (callback == null) {
return;
final OnBackAnimationCallback callback = getBackAnimationCallback();
if (callback != null) {
callback.onBackProgressed(backEvent);
}
callback.onBackProgressed(backEvent);
});
}
@Override
public void onBackCancelled() {
Handler.getMain().post(() -> {
final OnBackInvokedCallback callback = mCallback.get();
if (callback == null) {
return;
final OnBackAnimationCallback callback = getBackAnimationCallback();
if (callback != null) {
callback.onBackCancelled();
}
callback.onBackCancelled();
});
}
@ -243,6 +237,13 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
callback.onBackInvoked();
});
}
@Nullable
private OnBackAnimationCallback getBackAnimationCallback() {
OnBackInvokedCallback callback = mCallback.get();
return callback instanceof OnBackAnimationCallback ? (OnBackAnimationCallback) callback
: null;
}
}
/**

View File

@ -111,12 +111,7 @@ public class BackNavigationTest {
CountDownLatch backRegisteredLatch = new CountDownLatch(1);
mScenario.onActivity(activity -> {
activity.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
0, new OnBackInvokedCallback() {
@Override
public void onBackInvoked() {
backInvokedLatch.countDown();
}
}
0, backInvokedLatch::countDown
);
backRegisteredLatch.countDown();
});

View File

@ -56,9 +56,9 @@ public class WindowOnBackInvokedDispatcherTest {
private IWindow mWindow;
private WindowOnBackInvokedDispatcher mDispatcher;
@Mock
private OnBackInvokedCallback mCallback1;
private OnBackAnimationCallback mCallback1;
@Mock
private OnBackInvokedCallback mCallback2;
private OnBackAnimationCallback mCallback2;
@Before
public void setUp() throws Exception {