Merge "Add compatibility back callbacks."
This commit is contained in:
@@ -48950,10 +48950,9 @@ package android.view {
|
||||
method public default void onBackInvoked();
|
||||
}
|
||||
|
||||
public abstract class OnBackInvokedDispatcher {
|
||||
ctor public OnBackInvokedDispatcher();
|
||||
method public abstract void registerOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback, int);
|
||||
method public abstract void unregisterOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback);
|
||||
public interface OnBackInvokedDispatcher {
|
||||
method public void registerOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback, @IntRange(from=0) int);
|
||||
method public void unregisterOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback);
|
||||
field public static final int PRIORITY_DEFAULT = 0; // 0x0
|
||||
field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240
|
||||
}
|
||||
|
||||
@@ -2802,6 +2802,10 @@ package android.view {
|
||||
field public static final int FLAG_IS_ACCESSIBILITY_EVENT = 2048; // 0x800
|
||||
}
|
||||
|
||||
public interface OnBackInvokedDispatcher {
|
||||
field public static final long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L; // 0xbade858L
|
||||
}
|
||||
|
||||
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface RemotableViewMethod {
|
||||
method public abstract String asyncImpl() default "";
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OnBackInvokedCallback;
|
||||
import android.view.OnBackInvokedDispatcher;
|
||||
import android.view.OnBackInvokedDispatcherOwner;
|
||||
import android.view.RemoteAnimationDefinition;
|
||||
@@ -144,6 +145,7 @@ import android.widget.AdapterView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
import android.window.SplashScreen;
|
||||
import android.window.WindowOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -791,6 +793,7 @@ public class Activity extends ContextThemeWrapper
|
||||
private static final int LOG_AM_ON_ACTIVITY_RESULT_CALLED = 30062;
|
||||
private static final int LOG_AM_ON_TOP_RESUMED_GAINED_CALLED = 30064;
|
||||
private static final int LOG_AM_ON_TOP_RESUMED_LOST_CALLED = 30065;
|
||||
private OnBackInvokedCallback mDefaultBackCallback;
|
||||
|
||||
/**
|
||||
* After {@link Build.VERSION_CODES#TIRAMISU},
|
||||
@@ -1617,7 +1620,16 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
mRestoredFromBundle = savedInstanceState != null;
|
||||
mCalled = true;
|
||||
|
||||
if (!WindowOnBackInvokedDispatcher.shouldUseLegacyBack()) {
|
||||
// Add onBackPressed as default back behavior.
|
||||
mDefaultBackCallback = new OnBackInvokedCallback() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
navigateBack();
|
||||
}
|
||||
};
|
||||
getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2653,6 +2665,10 @@ public class Activity extends ContextThemeWrapper
|
||||
if (mUiTranslationController != null) {
|
||||
mUiTranslationController.onActivityDestroyed();
|
||||
}
|
||||
|
||||
if (mDefaultBackCallback != null) {
|
||||
getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mDefaultBackCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3773,10 +3789,13 @@ public class Activity extends ContextThemeWrapper
|
||||
* @see KeyEvent
|
||||
*/
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (getApplicationInfo().targetSdkVersion
|
||||
>= Build.VERSION_CODES.ECLAIR) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
|
||||
&& !event.isCanceled()) {
|
||||
int sdkVersion = getApplicationInfo().targetSdkVersion;
|
||||
if (sdkVersion >= Build.VERSION_CODES.ECLAIR) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
&& event.isTracking()
|
||||
&& !event.isCanceled()
|
||||
&& mDefaultBackCallback == null) {
|
||||
// Using legacy back handling.
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
@@ -3841,6 +3860,10 @@ public class Activity extends ContextThemeWrapper
|
||||
if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
|
||||
return;
|
||||
}
|
||||
navigateBack();
|
||||
}
|
||||
|
||||
private void navigateBack() {
|
||||
if (!isTaskRoot()) {
|
||||
// If the activity is not the root of the task, allow finish to proceed normally.
|
||||
finishAfterTransition();
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OnBackInvokedCallback;
|
||||
import android.view.OnBackInvokedDispatcher;
|
||||
import android.view.OnBackInvokedDispatcherOwner;
|
||||
import android.view.SearchEvent;
|
||||
@@ -62,6 +63,7 @@ import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.window.WindowOnBackInvokedDispatcher;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.app.WindowDecorActionBar;
|
||||
@@ -156,6 +158,7 @@ public class Dialog implements DialogInterface, Window.Callback,
|
||||
|
||||
/** A {@link Runnable} to run instead of dismissing when {@link #dismiss()} is called. */
|
||||
private Runnable mDismissOverride;
|
||||
private OnBackInvokedCallback mDefaultBackCallback;
|
||||
|
||||
/**
|
||||
* Creates a dialog window that uses the default dialog theme.
|
||||
@@ -453,6 +456,16 @@ public class Dialog implements DialogInterface, Window.Callback,
|
||||
*/
|
||||
protected void onStart() {
|
||||
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);
|
||||
if (mContext != null && !WindowOnBackInvokedDispatcher.shouldUseLegacyBack()) {
|
||||
// Add onBackPressed as default back behavior.
|
||||
mDefaultBackCallback = new OnBackInvokedCallback() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
onBackPressed();
|
||||
}
|
||||
};
|
||||
getOnBackInvokedDispatcher().registerSystemOnBackInvokedCallback(mDefaultBackCallback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -460,6 +473,9 @@ public class Dialog implements DialogInterface, Window.Callback,
|
||||
*/
|
||||
protected void onStop() {
|
||||
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
|
||||
if (mDefaultBackCallback != null) {
|
||||
getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mDefaultBackCallback);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
|
||||
@@ -685,7 +701,8 @@ public class Dialog implements DialogInterface, Window.Callback,
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
|
||||
&& event.isTracking()
|
||||
&& !event.isCanceled()) {
|
||||
&& !event.isCanceled()
|
||||
&& WindowOnBackInvokedDispatcher.shouldUseLegacyBack()) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
package android.view;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TestApi;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledSince;
|
||||
import android.os.Build;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -32,13 +37,29 @@ import java.lang.annotation.RetentionPolicy;
|
||||
* Attribute updates are proactively pushed to the window manager if they change the dispatch
|
||||
* target (a.k.a. the callback to be invoked next), or its behavior.
|
||||
*/
|
||||
public abstract class OnBackInvokedDispatcher {
|
||||
public interface OnBackInvokedDispatcher {
|
||||
/**
|
||||
* Enables dispatching the "back" action via {@link android.view.OnBackInvokedDispatcher}.
|
||||
*
|
||||
* When enabled, the following APIs are no longer invoked:
|
||||
* <ul>
|
||||
* <li> {@link android.app.Activity#onBackPressed}
|
||||
* <li> {@link android.app.Dialog#onBackPressed}
|
||||
* <li> {@link android.view.KeyEvent#KEYCODE_BACK} is no longer dispatched.
|
||||
* </ul>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@ChangeId
|
||||
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
|
||||
long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L;
|
||||
|
||||
/** @hide */
|
||||
public static final String TAG = "OnBackInvokedDispatcher";
|
||||
String TAG = "OnBackInvokedDispatcher";
|
||||
|
||||
/** @hide */
|
||||
public static final boolean DEBUG = Build.isDebuggable();
|
||||
boolean DEBUG = Build.isDebuggable();
|
||||
|
||||
/** @hide */
|
||||
@IntDef({
|
||||
@@ -46,18 +67,26 @@ public abstract class OnBackInvokedDispatcher {
|
||||
PRIORITY_OVERLAY,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Priority{}
|
||||
@interface Priority{}
|
||||
|
||||
/**
|
||||
* Priority level of {@link OnBackInvokedCallback}s for overlays such as menus and
|
||||
* navigation drawers that should receive back dispatch before non-overlays.
|
||||
*/
|
||||
public static final int PRIORITY_OVERLAY = 1000000;
|
||||
int PRIORITY_OVERLAY = 1000000;
|
||||
|
||||
/**
|
||||
* Default priority level of {@link OnBackInvokedCallback}s.
|
||||
*/
|
||||
public static final int PRIORITY_DEFAULT = 0;
|
||||
int PRIORITY_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Priority level of {@link OnBackInvokedCallback}s registered by the system.
|
||||
*
|
||||
* System back animation will play when the callback to receive dispatch has this priority.
|
||||
* @hide
|
||||
*/
|
||||
int PRIORITY_SYSTEM = -1;
|
||||
|
||||
/**
|
||||
* Registers a {@link OnBackInvokedCallback}.
|
||||
@@ -69,10 +98,11 @@ public abstract class OnBackInvokedDispatcher {
|
||||
* registered, the existing instance (no matter its priority) will be
|
||||
* unregistered and registered again.
|
||||
* @param priority The priority of the callback.
|
||||
* @throws {@link IllegalArgumentException} if the priority is negative.
|
||||
*/
|
||||
@SuppressLint("SamShouldBeLast")
|
||||
public abstract void registerOnBackInvokedCallback(
|
||||
@NonNull OnBackInvokedCallback callback, @Priority int priority);
|
||||
void registerOnBackInvokedCallback(
|
||||
@NonNull OnBackInvokedCallback callback, @Priority @IntRange(from = 0) int priority);
|
||||
|
||||
/**
|
||||
* Unregisters a {@link OnBackInvokedCallback}.
|
||||
@@ -80,5 +110,20 @@ public abstract class OnBackInvokedDispatcher {
|
||||
* @param callback The callback to be unregistered. Does nothing if the callback has not been
|
||||
* registered.
|
||||
*/
|
||||
public abstract void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback);
|
||||
void unregisterOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback);
|
||||
|
||||
/**
|
||||
* Returns the most prioritized callback to receive back dispatch next.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
default OnBackInvokedCallback getTopCallback() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link OnBackInvokedCallback} with system priority.
|
||||
* @hide
|
||||
*/
|
||||
default void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) { }
|
||||
}
|
||||
|
||||
@@ -317,6 +317,11 @@ public final class ViewRootImpl implements ViewParent,
|
||||
*/
|
||||
private final WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher =
|
||||
new WindowOnBackInvokedDispatcher();
|
||||
/**
|
||||
* Compatibility {@link OnBackInvokedCallback} that dispatches KEYCODE_BACK events
|
||||
* to view root for apps using legacy back behavior.
|
||||
*/
|
||||
private OnBackInvokedCallback mCompatOnBackInvokedCallback;
|
||||
|
||||
/**
|
||||
* Callback for notifying about global configuration changes.
|
||||
@@ -1190,6 +1195,14 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mTmpFrames.displayFrame, mTempRect2, mTmpFrames.frame);
|
||||
setFrame(mTmpFrames.frame);
|
||||
registerBackCallbackOnWindow();
|
||||
if (WindowOnBackInvokedDispatcher.shouldUseLegacyBack()) {
|
||||
// For apps requesting legacy back behavior, we add a compat callback that
|
||||
// dispatches {@link KeyEvent#KEYCODE_BACK} to their root views.
|
||||
// This way from system point of view, these apps are providing custom
|
||||
// {@link OnBackInvokedCallback}s, and will not play system back animations
|
||||
// for them.
|
||||
registerCompatOnBackInvokedCallback();
|
||||
}
|
||||
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
|
||||
if (res < WindowManagerGlobal.ADD_OKAY) {
|
||||
mAttachInfo.mRootView = null;
|
||||
@@ -5931,7 +5944,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBack(InputEvent event) {
|
||||
boolean isBack(InputEvent event) {
|
||||
if (event instanceof KeyEvent) {
|
||||
return ((KeyEvent) event).getKeyCode() == KeyEvent.KEYCODE_BACK;
|
||||
} else {
|
||||
@@ -6471,6 +6484,19 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return FINISH_NOT_HANDLED;
|
||||
}
|
||||
|
||||
if (isBack(event)
|
||||
&& mContext != null
|
||||
&& !WindowOnBackInvokedDispatcher.shouldUseLegacyBack()) {
|
||||
// Invoke the appropriate {@link OnBackInvokedCallback} if the new back
|
||||
// navigation should be used, and the key event is not handled by anything else.
|
||||
OnBackInvokedCallback topCallback =
|
||||
getOnBackInvokedDispatcher().getTopCallback();
|
||||
if (topCallback != null) {
|
||||
topCallback.onBackInvoked();
|
||||
return FINISH_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
// This dispatch is for windows that don't have a Window.Callback. Otherwise,
|
||||
// the Window.Callback usually will have already called this (see
|
||||
// DecorView.superDispatchKeyEvent) leaving this call a no-op.
|
||||
@@ -8414,6 +8440,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
mAdded = false;
|
||||
}
|
||||
unregisterCompatOnBackInvokedCallback();
|
||||
mOnBackInvokedDispatcher.detachFromWindow();
|
||||
WindowManagerGlobal.getInstance().doRemoveView(this);
|
||||
}
|
||||
@@ -10782,6 +10809,38 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mOnBackInvokedDispatcher.attachToWindow(mWindowSession, mWindow);
|
||||
}
|
||||
|
||||
private void sendBackKeyEvent(int action) {
|
||||
long when = SystemClock.uptimeMillis();
|
||||
final KeyEvent ev = new KeyEvent(when, when, action,
|
||||
KeyEvent.KEYCODE_BACK, 0 /* repeat */, 0 /* metaState */,
|
||||
KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
|
||||
KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
|
||||
InputDevice.SOURCE_KEYBOARD);
|
||||
|
||||
ev.setDisplayId(mContext.getDisplay().getDisplayId());
|
||||
if (mView != null) {
|
||||
mView.dispatchKeyEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCompatOnBackInvokedCallback() {
|
||||
mCompatOnBackInvokedCallback = new OnBackInvokedCallback() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
sendBackKeyEvent(KeyEvent.ACTION_DOWN);
|
||||
sendBackKeyEvent(KeyEvent.ACTION_UP);
|
||||
}
|
||||
};
|
||||
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
|
||||
mCompatOnBackInvokedCallback, OnBackInvokedDispatcher.PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
private void unregisterCompatOnBackInvokedCallback() {
|
||||
if (mCompatOnBackInvokedCallback != null) {
|
||||
mOnBackInvokedDispatcher.unregisterOnBackInvokedCallback(mCompatOnBackInvokedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTouchableRegion(Region r) {
|
||||
if (r != null) {
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.List;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ProxyOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
|
||||
/**
|
||||
* List of pair representing an {@link OnBackInvokedCallback} and its associated priority.
|
||||
@@ -60,14 +60,16 @@ public class ProxyOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
Log.v(TAG, String.format("Pending register %s. Actual=%s", callback,
|
||||
mActualDispatcherOwner));
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mCallbacks.add(Pair.create(callback, priority));
|
||||
if (mActualDispatcherOwner != null) {
|
||||
mActualDispatcherOwner.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
callback, priority);
|
||||
}
|
||||
|
||||
if (priority < 0) {
|
||||
throw new IllegalArgumentException("Application registered OnBackInvokedCallback "
|
||||
+ "cannot have negative priority. Priority: " + priority);
|
||||
}
|
||||
registerOnBackInvokedCallbackUnchecked(callback, priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
|
||||
registerOnBackInvokedCallbackUnchecked(callback, PRIORITY_SYSTEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,6 +84,17 @@ public class ProxyOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerOnBackInvokedCallbackUnchecked(
|
||||
@NonNull OnBackInvokedCallback callback, int priority) {
|
||||
synchronized (mLock) {
|
||||
mCallbacks.add(Pair.create(callback, priority));
|
||||
if (mActualDispatcherOwner != null) {
|
||||
mActualDispatcherOwner.getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
callback, priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfers all the pending callbacks to the provided dispatcher.
|
||||
* <p>
|
||||
@@ -99,8 +112,12 @@ public class ProxyOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
dispatcher));
|
||||
}
|
||||
for (Pair<OnBackInvokedCallback, Integer> callbackPair : mCallbacks) {
|
||||
dispatcher.registerOnBackInvokedCallback(callbackPair.first,
|
||||
callbackPair.second);
|
||||
int priority = callbackPair.second;
|
||||
if (priority >= 0) {
|
||||
dispatcher.registerOnBackInvokedCallback(callbackPair.first, priority);
|
||||
} else {
|
||||
dispatcher.registerSystemOnBackInvokedCallback(callbackPair.first);
|
||||
}
|
||||
}
|
||||
mCallbacks.clear();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,10 @@ package android.window;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.IWindow;
|
||||
import android.view.IWindowSession;
|
||||
@@ -31,7 +33,7 @@ import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Provides window based implementation of {@link OnBackInvokedDispatcher}.
|
||||
* Provides window based implementation of {@link android.view.OnBackInvokedDispatcher}.
|
||||
*
|
||||
* Callbacks with higher priorities receive back dispatching first.
|
||||
* Within the same priority, callbacks receive back dispatching in the reverse order
|
||||
@@ -39,16 +41,19 @@ import java.util.TreeMap;
|
||||
*
|
||||
* When the top priority callback is updated, the new callback is propagated to the Window Manager
|
||||
* if the window the instance is associated with has been attached. It is allowed to register /
|
||||
* unregister {@link OnBackInvokedCallback}s before the window is attached, although callbacks
|
||||
* will not receive dispatches until window attachment.
|
||||
* unregister {@link android.view.OnBackInvokedCallback}s before the window is attached, although
|
||||
* callbacks will not receive dispatches until window attachment.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class WindowOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
|
||||
private IWindowSession mWindowSession;
|
||||
private IWindow mWindow;
|
||||
private static final String TAG = "WindowOnBackDispatcher";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String BACK_PREDICTABILITY_PROP = "persist.debug.back_predictability";
|
||||
private static final boolean IS_BACK_PREDICTABILITY_ENABLED = SystemProperties
|
||||
.getInt(BACK_PREDICTABILITY_PROP, 0) > 0;
|
||||
|
||||
/** The currently most prioritized callback. */
|
||||
@Nullable
|
||||
@@ -82,6 +87,15 @@ public class WindowOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
@Override
|
||||
public void registerOnBackInvokedCallback(
|
||||
@NonNull OnBackInvokedCallback callback, @Priority int priority) {
|
||||
if (priority < 0) {
|
||||
throw new IllegalArgumentException("Application registered OnBackInvokedCallback "
|
||||
+ "cannot have negative priority. Priority: " + priority);
|
||||
}
|
||||
registerOnBackInvokedCallbackUnchecked(callback, priority);
|
||||
}
|
||||
|
||||
private void registerOnBackInvokedCallbackUnchecked(
|
||||
@NonNull OnBackInvokedCallback callback, @Priority int priority) {
|
||||
if (!mOnBackInvokedCallbacks.containsKey(priority)) {
|
||||
mOnBackInvokedCallbacks.put(priority, new ArrayList<>());
|
||||
}
|
||||
@@ -120,6 +134,11 @@ public class WindowOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerSystemOnBackInvokedCallback(@NonNull OnBackInvokedCallback callback) {
|
||||
registerOnBackInvokedCallbackUnchecked(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM);
|
||||
}
|
||||
|
||||
/** Clears all registered callbacks on the instance. */
|
||||
public void clear() {
|
||||
mAllCallbacks.clear();
|
||||
@@ -198,4 +217,21 @@ public class WindowOnBackInvokedDispatcher extends OnBackInvokedDispatcher {
|
||||
Handler.getMain().post(() -> mCallback.onBackInvoked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OnBackInvokedCallback getTopCallback() {
|
||||
return mTopCallback == null ? null : mTopCallback.getCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the legacy back behavior should be used.
|
||||
*
|
||||
* Legacy back behavior dispatches KEYCODE_BACK instead of invoking the application registered
|
||||
* {@link android.view.OnBackInvokedCallback}.
|
||||
*
|
||||
*/
|
||||
public static boolean shouldUseLegacyBack() {
|
||||
return !CompatChanges.isChangeEnabled(DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME)
|
||||
|| !IS_BACK_PREDICTABILITY_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user