Loading core/java/android/view/ViewRootImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -7733,7 +7733,7 @@ public final class ViewRootImpl implements ViewParent, if (keyEvent.isCanceled()) { animationCallback.onBackCancelled(); } else { dispatcher.tryInvokeSystemNavigationObserverCallback(); dispatcher.tryInvokeSystemNavigationObserverCallbacks(); topCallback.onBackInvoked(); } break; Loading @@ -7741,7 +7741,7 @@ public final class ViewRootImpl implements ViewParent, } else if (topCallback != null) { if (keyEvent.getAction() == KeyEvent.ACTION_UP) { if (!keyEvent.isCanceled()) { dispatcher.tryInvokeSystemNavigationObserverCallback(); dispatcher.tryInvokeSystemNavigationObserverCallbacks(); topCallback.onBackInvoked(); } else { Log.d(mTag, "Skip onBackInvoked(), reason: keyEvent.isCanceled=true"); Loading core/java/android/window/OnBackInvokedDispatcher.java +15 −5 Original line number Diff line number Diff line Loading @@ -74,12 +74,22 @@ public interface OnBackInvokedDispatcher { * Priority level of {@link OnBackInvokedCallback}s designed to observe system-level back * handling. * * <p>Callbacks registered with this priority do not consume back events. They receive back * events whenever the system handles a back navigation and have no impact on the normal back * navigation flow. Useful for logging or analytics. * <p>Callbacks registered with this priority are invoked only when a back event is not * consumed by any other registered {@link OnBackInvokedCallback} with a priority of * {@link #PRIORITY_DEFAULT} or higher. This means they are called when the system is about * to perform its default back navigation action, such as finishing the current activity or * executing a back-to-home animation. * * <p>Only one callback with {@link #PRIORITY_SYSTEM_NAVIGATION_OBSERVER} can be registered at a * time. * <p>These callbacks are purely observational. They do not consume the back event and * cannot intercept it. Their invocation has no impact on the normal back navigation flow, * making them suitable for logging, analytics, or triggering actions that should not * prevent the system's own back handling. * * <p>The invocation order for multiple callbacks registered with this priority is undefined. * * <p>On API level 36 only, there is a restriction that only one callback with * {@link #PRIORITY_SYSTEM_NAVIGATION_OBSERVER} can be registered at a time. On API level 37 and * higher, the number of registered observer callbacks is unrestricted. */ @FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) int PRIORITY_SYSTEM_NAVIGATION_OBSERVER = -2; Loading core/java/android/window/WindowOnBackInvokedDispatcher.java +51 −14 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.window; import static android.window.SystemOverrideOnBackInvokedCallback.OVERRIDE_UNDEFINED; import static com.android.window.flags.Flags.multipleSystemNavigationObserverCallbacks; import static com.android.window.flags.Flags.predictiveBackSystemOverrideCallback; import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver; import static com.android.window.flags.Flags.predictiveBackTimestampApi; Loading Loading @@ -54,7 +55,9 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.function.BooleanSupplier; import java.util.function.Supplier; Loading Loading @@ -111,6 +114,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @VisibleForTesting public OnBackInvokedCallback mSystemNavigationObserverCallback = null; @VisibleForTesting public Set<OnBackInvokedCallback> mSystemNavigationObserverCallbacks = new HashSet<>(); private Checker mChecker; private final Object mLock = new Object(); Loading Loading @@ -189,9 +194,13 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } removeCallbackInternal(callback); } if (multipleSystemNavigationObserverCallbacks()) { mSystemNavigationObserverCallbacks.add(callback); } else { mSystemNavigationObserverCallback = callback; } } } /** * Register a callback bypassing platform checks. This is used to register compatibility Loading Loading @@ -240,6 +249,15 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { Integer prevPriority = mAllCallbacks.get(callback); mOnBackInvokedCallbacks.get(prevPriority).remove(callback); } if (multipleSystemNavigationObserverCallbacks()) { if (mSystemNavigationObserverCallbacks.contains(callback)) { mSystemNavigationObserverCallbacks.remove(callback); if (DEBUG) { Log.i(TAG, "Callback already registered (as system-navigation-observer " + "callback). Removing and re-adding it."); } } } else { if (mSystemNavigationObserverCallback == callback) { mSystemNavigationObserverCallback = null; if (DEBUG) { Loading @@ -247,6 +265,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { + "callback). Removing and re-adding it."); } } } OnBackInvokedCallback previousTopCallback = getTopCallback(); callbacks.add(callback); Loading @@ -266,10 +285,17 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.unregisterOnBackInvokedCallback(callback); return; } if (multipleSystemNavigationObserverCallbacks()) { if (mSystemNavigationObserverCallbacks.contains(callback)) { mSystemNavigationObserverCallbacks.remove(callback); return; } } else { if (mSystemNavigationObserverCallback == callback) { mSystemNavigationObserverCallback = null; return; } } if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { callback = mImeBackAnimationController; } Loading Loading @@ -373,6 +399,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mAllCallbacks.clear(); mOnBackInvokedCallbacks.clear(); mSystemNavigationObserverCallback = null; mSystemNavigationObserverCallbacks.clear(); } } Loading @@ -385,11 +412,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } /** * Tries to call {@link OnBackInvokedCallback#onBackInvoked} on the system navigation observer * callback (if one is set and if the top-most regular callback has * Tries to call {@link OnBackInvokedCallback#onBackInvoked} on all system navigation observer * callback (if any are registered and if the top-most regular callback has * {@link OnBackInvokedDispatcher#PRIORITY_SYSTEM}) */ public void tryInvokeSystemNavigationObserverCallback() { public void tryInvokeSystemNavigationObserverCallbacks() { OnBackInvokedCallback topCallback = getTopCallback(); Integer callbackPriority = mAllCallbacks.getOrDefault(topCallback, null); final boolean isSystemOverride = topCallback instanceof SystemOverrideOnBackInvokedCallback; Loading @@ -399,10 +426,20 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } private void invokeSystemNavigationObserverCallback() { if (multipleSystemNavigationObserverCallbacks()) { Set<OnBackInvokedCallback> observerCallbacks; synchronized (mLock) { observerCallbacks = new HashSet<>(mSystemNavigationObserverCallbacks); } for (OnBackInvokedCallback callback : observerCallbacks) { callback.onBackInvoked(); } } else { if (mSystemNavigationObserverCallback != null) { mSystemNavigationObserverCallback.onBackInvoked(); } } } private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) { if (mWindowSession == null || mWindow == null) { Loading core/java/android/window/flags/windowing_frontend.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -472,3 +472,10 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "multiple_system_navigation_observer_callbacks" namespace: "windowing_frontend" description: "Removes restriction that only one back callback with PRIORITY_SYSTEM_NAVIGATION_OBSERVER can be registered" bug: "424146227" } core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +37 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT; import static android.window.OnBackInvokedDispatcher.PRIORITY_OVERLAY; import static android.window.OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER; import static com.android.window.flags.Flags.FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS; import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER; import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API; Loading Loading @@ -167,7 +168,8 @@ public class WindowOnBackInvokedDispatcherTest { int actualSizeOverlay = callbacksOverlay != null ? callbacksOverlay.size() : 0; assertEquals("mOnBackInvokedCallbacks OVERLAY size", expectedOverlay, actualSizeOverlay); int actualSizeObserver = mDispatcher.mSystemNavigationObserverCallback == null ? 0 : 1; int actualSizeObserver = mDispatcher.mSystemNavigationObserverCallback == null ? mDispatcher.mSystemNavigationObserverCallbacks.size() : 1; assertEquals("mOnBackInvokedCallbacks SYSTEM_NAVIGATION_OBSERVER size", expectedObserver, actualSizeObserver); } Loading Loading @@ -666,6 +668,7 @@ public class WindowOnBackInvokedDispatcherTest { @Test @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) @RequiresFlagsDisabled(FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS) public void testObserverCallback_reregistrations() { mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); Loading @@ -688,6 +691,39 @@ public class WindowOnBackInvokedDispatcherTest { assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 0); } @Test @RequiresFlagsEnabled({FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER, FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS}) public void testObserverCallback_multiple_registrations() { mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback1)); // test registration of another observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback1)); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback2)); // test reregistration of first observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); // test reregistration of observer-callback with default priority mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 1); // test reregistration of regular callback as observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); mDispatcher.unregisterOnBackInvokedCallback(mCallback2); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); mDispatcher.unregisterOnBackInvokedCallback(mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 0); } private BackMotionEvent backMotionEventFrom(float progress) { return new BackMotionEvent( /* touchX = */ 0, Loading Loading
core/java/android/view/ViewRootImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -7733,7 +7733,7 @@ public final class ViewRootImpl implements ViewParent, if (keyEvent.isCanceled()) { animationCallback.onBackCancelled(); } else { dispatcher.tryInvokeSystemNavigationObserverCallback(); dispatcher.tryInvokeSystemNavigationObserverCallbacks(); topCallback.onBackInvoked(); } break; Loading @@ -7741,7 +7741,7 @@ public final class ViewRootImpl implements ViewParent, } else if (topCallback != null) { if (keyEvent.getAction() == KeyEvent.ACTION_UP) { if (!keyEvent.isCanceled()) { dispatcher.tryInvokeSystemNavigationObserverCallback(); dispatcher.tryInvokeSystemNavigationObserverCallbacks(); topCallback.onBackInvoked(); } else { Log.d(mTag, "Skip onBackInvoked(), reason: keyEvent.isCanceled=true"); Loading
core/java/android/window/OnBackInvokedDispatcher.java +15 −5 Original line number Diff line number Diff line Loading @@ -74,12 +74,22 @@ public interface OnBackInvokedDispatcher { * Priority level of {@link OnBackInvokedCallback}s designed to observe system-level back * handling. * * <p>Callbacks registered with this priority do not consume back events. They receive back * events whenever the system handles a back navigation and have no impact on the normal back * navigation flow. Useful for logging or analytics. * <p>Callbacks registered with this priority are invoked only when a back event is not * consumed by any other registered {@link OnBackInvokedCallback} with a priority of * {@link #PRIORITY_DEFAULT} or higher. This means they are called when the system is about * to perform its default back navigation action, such as finishing the current activity or * executing a back-to-home animation. * * <p>Only one callback with {@link #PRIORITY_SYSTEM_NAVIGATION_OBSERVER} can be registered at a * time. * <p>These callbacks are purely observational. They do not consume the back event and * cannot intercept it. Their invocation has no impact on the normal back navigation flow, * making them suitable for logging, analytics, or triggering actions that should not * prevent the system's own back handling. * * <p>The invocation order for multiple callbacks registered with this priority is undefined. * * <p>On API level 36 only, there is a restriction that only one callback with * {@link #PRIORITY_SYSTEM_NAVIGATION_OBSERVER} can be registered at a time. On API level 37 and * higher, the number of registered observer callbacks is unrestricted. */ @FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) int PRIORITY_SYSTEM_NAVIGATION_OBSERVER = -2; Loading
core/java/android/window/WindowOnBackInvokedDispatcher.java +51 −14 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.window; import static android.window.SystemOverrideOnBackInvokedCallback.OVERRIDE_UNDEFINED; import static com.android.window.flags.Flags.multipleSystemNavigationObserverCallbacks; import static com.android.window.flags.Flags.predictiveBackSystemOverrideCallback; import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver; import static com.android.window.flags.Flags.predictiveBackTimestampApi; Loading Loading @@ -54,7 +55,9 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Objects; import java.util.Set; import java.util.TreeMap; import java.util.function.BooleanSupplier; import java.util.function.Supplier; Loading Loading @@ -111,6 +114,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @VisibleForTesting public OnBackInvokedCallback mSystemNavigationObserverCallback = null; @VisibleForTesting public Set<OnBackInvokedCallback> mSystemNavigationObserverCallbacks = new HashSet<>(); private Checker mChecker; private final Object mLock = new Object(); Loading Loading @@ -189,9 +194,13 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } removeCallbackInternal(callback); } if (multipleSystemNavigationObserverCallbacks()) { mSystemNavigationObserverCallbacks.add(callback); } else { mSystemNavigationObserverCallback = callback; } } } /** * Register a callback bypassing platform checks. This is used to register compatibility Loading Loading @@ -240,6 +249,15 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { Integer prevPriority = mAllCallbacks.get(callback); mOnBackInvokedCallbacks.get(prevPriority).remove(callback); } if (multipleSystemNavigationObserverCallbacks()) { if (mSystemNavigationObserverCallbacks.contains(callback)) { mSystemNavigationObserverCallbacks.remove(callback); if (DEBUG) { Log.i(TAG, "Callback already registered (as system-navigation-observer " + "callback). Removing and re-adding it."); } } } else { if (mSystemNavigationObserverCallback == callback) { mSystemNavigationObserverCallback = null; if (DEBUG) { Loading @@ -247,6 +265,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { + "callback). Removing and re-adding it."); } } } OnBackInvokedCallback previousTopCallback = getTopCallback(); callbacks.add(callback); Loading @@ -266,10 +285,17 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mImeDispatcher.unregisterOnBackInvokedCallback(callback); return; } if (multipleSystemNavigationObserverCallbacks()) { if (mSystemNavigationObserverCallbacks.contains(callback)) { mSystemNavigationObserverCallbacks.remove(callback); return; } } else { if (mSystemNavigationObserverCallback == callback) { mSystemNavigationObserverCallback = null; return; } } if (callback instanceof ImeOnBackInvokedDispatcher.DefaultImeOnBackAnimationCallback) { callback = mImeBackAnimationController; } Loading Loading @@ -373,6 +399,7 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { mAllCallbacks.clear(); mOnBackInvokedCallbacks.clear(); mSystemNavigationObserverCallback = null; mSystemNavigationObserverCallbacks.clear(); } } Loading @@ -385,11 +412,11 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } /** * Tries to call {@link OnBackInvokedCallback#onBackInvoked} on the system navigation observer * callback (if one is set and if the top-most regular callback has * Tries to call {@link OnBackInvokedCallback#onBackInvoked} on all system navigation observer * callback (if any are registered and if the top-most regular callback has * {@link OnBackInvokedDispatcher#PRIORITY_SYSTEM}) */ public void tryInvokeSystemNavigationObserverCallback() { public void tryInvokeSystemNavigationObserverCallbacks() { OnBackInvokedCallback topCallback = getTopCallback(); Integer callbackPriority = mAllCallbacks.getOrDefault(topCallback, null); final boolean isSystemOverride = topCallback instanceof SystemOverrideOnBackInvokedCallback; Loading @@ -399,10 +426,20 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } private void invokeSystemNavigationObserverCallback() { if (multipleSystemNavigationObserverCallbacks()) { Set<OnBackInvokedCallback> observerCallbacks; synchronized (mLock) { observerCallbacks = new HashSet<>(mSystemNavigationObserverCallbacks); } for (OnBackInvokedCallback callback : observerCallbacks) { callback.onBackInvoked(); } } else { if (mSystemNavigationObserverCallback != null) { mSystemNavigationObserverCallback.onBackInvoked(); } } } private void setTopOnBackInvokedCallback(@Nullable OnBackInvokedCallback callback) { if (mWindowSession == null || mWindow == null) { Loading
core/java/android/window/flags/windowing_frontend.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -472,3 +472,10 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "multiple_system_navigation_observer_callbacks" namespace: "windowing_frontend" description: "Removes restriction that only one back callback with PRIORITY_SYSTEM_NAVIGATION_OBSERVER can be registered" bug: "424146227" }
core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java +37 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT; import static android.window.OnBackInvokedDispatcher.PRIORITY_OVERLAY; import static android.window.OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER; import static com.android.window.flags.Flags.FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS; import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER; import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API; Loading Loading @@ -167,7 +168,8 @@ public class WindowOnBackInvokedDispatcherTest { int actualSizeOverlay = callbacksOverlay != null ? callbacksOverlay.size() : 0; assertEquals("mOnBackInvokedCallbacks OVERLAY size", expectedOverlay, actualSizeOverlay); int actualSizeObserver = mDispatcher.mSystemNavigationObserverCallback == null ? 0 : 1; int actualSizeObserver = mDispatcher.mSystemNavigationObserverCallback == null ? mDispatcher.mSystemNavigationObserverCallbacks.size() : 1; assertEquals("mOnBackInvokedCallbacks SYSTEM_NAVIGATION_OBSERVER size", expectedObserver, actualSizeObserver); } Loading Loading @@ -666,6 +668,7 @@ public class WindowOnBackInvokedDispatcherTest { @Test @RequiresFlagsEnabled(FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER) @RequiresFlagsDisabled(FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS) public void testObserverCallback_reregistrations() { mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); Loading @@ -688,6 +691,39 @@ public class WindowOnBackInvokedDispatcherTest { assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 0); } @Test @RequiresFlagsEnabled({FLAG_PREDICTIVE_BACK_PRIORITY_SYSTEM_NAVIGATION_OBSERVER, FLAG_MULTIPLE_SYSTEM_NAVIGATION_OBSERVER_CALLBACKS}) public void testObserverCallback_multiple_registrations() { mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback1)); // test registration of another observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback2); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback1)); assertTrue(mDispatcher.mSystemNavigationObserverCallbacks.contains(mCallback2)); // test reregistration of first observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); // test reregistration of observer-callback with default priority mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1); assertCallbacksSize(/* default */ 1, /* overlay */ 0, /* observer */ 1); // test reregistration of regular callback as observer-callback mDispatcher.registerOnBackInvokedCallback(PRIORITY_SYSTEM_NAVIGATION_OBSERVER, mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 2); mDispatcher.unregisterOnBackInvokedCallback(mCallback2); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 1); mDispatcher.unregisterOnBackInvokedCallback(mCallback1); assertCallbacksSize(/* default */ 0, /* overlay */ 0, /* observer */ 0); } private BackMotionEvent backMotionEventFrom(float progress) { return new BackMotionEvent( /* touchX = */ 0, Loading