From 69a3984aae13aaa17978c28f3bc0b254d0a4abfc Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Wed, 30 Mar 2022 20:23:59 +0000 Subject: [PATCH] Remove OnBackInvokedDispatcherOwner interface. Test: m -j update-api. Build and flash and test back behavior throughout the system. Bug: 227500290 Change-Id: Ibdb13d02e044741d05d99f1cad96e43dc0129fe4 --- core/api/current.txt | 9 +-- core/api/module-lib-current.txt | 2 +- core/api/system-current.txt | 2 +- core/api/test-current.txt | 2 +- core/java/android/app/Activity.java | 7 +-- core/java/android/app/Dialog.java | 7 +-- core/java/android/view/ViewRootImpl.java | 3 +- core/java/android/view/Window.java | 9 +++ .../android/window/OnBackInvokedCallback.java | 17 +++--- .../window/OnBackInvokedDispatcherOwner.java | 33 ----------- .../window/ProxyOnBackInvokedDispatcher.java | 56 ++++++++----------- .../android/internal/policy/PhoneWindow.java | 6 +- 12 files changed, 54 insertions(+), 99 deletions(-) delete mode 100644 core/java/android/window/OnBackInvokedDispatcherOwner.java diff --git a/core/api/current.txt b/core/api/current.txt index 37c5b9d3f2f3..16d83a4b76fd 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -4074,7 +4074,7 @@ package android.app { method @Deprecated public void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction); } - @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback { + @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { ctor public Activity(); method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams); method public void closeContextMenu(); @@ -5018,7 +5018,7 @@ package android.app { method public void onDateSet(android.widget.DatePicker, int, int, int); } - public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback { + public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.view.View.OnCreateContextMenuListener android.view.Window.Callback { ctor public Dialog(@NonNull @UiContext android.content.Context); ctor public Dialog(@NonNull @UiContext android.content.Context, @StyleRes int); ctor protected Dialog(@NonNull @UiContext android.content.Context, boolean, @Nullable android.content.DialogInterface.OnCancelListener); @@ -51087,6 +51087,7 @@ package android.view { method public android.media.session.MediaController getMediaController(); method @ColorInt public abstract int getNavigationBarColor(); method @ColorInt public int getNavigationBarDividerColor(); + method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher(); method public android.transition.Transition getReenterTransition(); method public android.transition.Transition getReturnTransition(); method @Nullable public android.view.AttachedSurfaceControl getRootSurfaceControl(); @@ -57991,10 +57992,6 @@ package android.window { field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240 } - public interface OnBackInvokedDispatcherOwner { - method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher(); - } - public interface SplashScreen { method public void clearOnExitAnimationListener(); method public void setOnExitAnimationListener(@NonNull android.window.SplashScreen.OnExitAnimationListener); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index 44a79c61e216..b9522163b5d0 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -11,7 +11,7 @@ package android { package android.app { - @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback { + @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { method public final boolean addDumpable(@NonNull android.util.Dumpable); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3f8fc5600eb1..7c1e577aaa3e 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -469,7 +469,7 @@ package android.accounts { package android.app { - @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback { + @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { method public void convertFromTranslucent(); method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions); method @Deprecated public boolean isBackgroundVisibleBehind(); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 1a34ef53a8e3..cd5ed213e6a5 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -104,7 +104,7 @@ package android.animation { package android.app { - @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback { + @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { method public final boolean addDumpable(@NonNull android.util.Dumpable); method public void dumpInternal(@NonNull String, @Nullable java.io.FileDescriptor, @NonNull java.io.PrintWriter, @Nullable String[]); method public void onMovedToDisplay(int, android.content.res.Configuration); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 5537b075d42f..acdab1b97599 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -148,7 +148,6 @@ import android.widget.Toast; import android.widget.Toolbar; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; -import android.window.OnBackInvokedDispatcherOwner; import android.window.SplashScreen; import android.window.WindowOnBackInvokedDispatcher; @@ -749,8 +748,7 @@ public class Activity extends ContextThemeWrapper Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, - ContentCaptureManager.ContentCaptureClient, - OnBackInvokedDispatcherOwner { + ContentCaptureManager.ContentCaptureClient { private static final String TAG = "Activity"; private static final boolean DEBUG_LIFECYCLE = false; @@ -8993,12 +8991,11 @@ public class Activity extends ContextThemeWrapper * @throws IllegalStateException if this Activity is not visual. */ @NonNull - @Override public OnBackInvokedDispatcher getOnBackInvokedDispatcher() { if (mWindow == null) { throw new IllegalStateException("OnBackInvokedDispatcher are not available on " + "non-visual activities"); } - return ((OnBackInvokedDispatcherOwner) mWindow).getOnBackInvokedDispatcher(); + return mWindow.getOnBackInvokedDispatcher(); } } diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 51b71f0c5d52..f0af9bad2864 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -62,7 +62,6 @@ import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; -import android.window.OnBackInvokedDispatcherOwner; import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.R; @@ -98,8 +97,7 @@ import java.lang.ref.WeakReference; * */ public class Dialog implements DialogInterface, Window.Callback, - KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback, - OnBackInvokedDispatcherOwner { + KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback { private static final String TAG = "Dialog"; @UnsupportedAppUsage private Activity mOwnerActivity; @@ -1469,8 +1467,7 @@ public class Dialog implements DialogInterface, Window.Callback, * Returns null if the dialog is not attached to a window with a decor. */ @NonNull - @Override public OnBackInvokedDispatcher getOnBackInvokedDispatcher() { - return ((OnBackInvokedDispatcherOwner) mWindow).getOnBackInvokedDispatcher(); + return mWindow.getOnBackInvokedDispatcher(); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a5b4755d638d..7b3fed74a9be 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -197,7 +197,6 @@ import android.widget.Scroller; import android.window.ClientWindowFrames; import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; -import android.window.OnBackInvokedDispatcherOwner; import android.window.SurfaceSyncer; import android.window.WindowOnBackInvokedDispatcher; @@ -240,7 +239,7 @@ import java.util.concurrent.CountDownLatch; @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"}) public final class ViewRootImpl implements ViewParent, View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks, - AttachedSurfaceControl, OnBackInvokedDispatcherOwner { + AttachedSurfaceControl { private static final String TAG = "ViewRootImpl"; private static final boolean DBG = false; private static final boolean LOCAL_LOGV = false; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 8401b7cdb243..555fd434e4d9 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -56,6 +56,7 @@ import android.transition.TransitionManager; import android.util.Pair; import android.view.View.OnApplyWindowInsetsListener; import android.view.accessibility.AccessibilityEvent; +import android.window.OnBackInvokedDispatcher; import java.util.Collections; import java.util.List; @@ -2798,4 +2799,12 @@ public abstract class Window { public @Nullable AttachedSurfaceControl getRootSurfaceControl() { return null; } + + /** + * Returns the {@link OnBackInvokedDispatcher} instance associated with this window. + */ + @NonNull + public OnBackInvokedDispatcher getOnBackInvokedDispatcher() { + throw new RuntimeException("Not implemented. Must override in a subclass."); + } } diff --git a/core/java/android/window/OnBackInvokedCallback.java b/core/java/android/window/OnBackInvokedCallback.java index 7b8cc0ae6de7..6e2d4f9edbc1 100644 --- a/core/java/android/window/OnBackInvokedCallback.java +++ b/core/java/android/window/OnBackInvokedCallback.java @@ -18,23 +18,22 @@ package android.window; import android.app.Activity; import android.app.Dialog; -import android.view.View; +import android.view.Window; /** * Callback allowing applications to handle back events in place of the system. *

- * 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}). + * Callback instances can be added to and removed from {@link OnBackInvokedDispatcher}, which + * is held at window level and accessible through {@link Activity#getOnBackInvokedDispatcher()}, + * {@link Dialog#getOnBackInvokedDispatcher()} and {@link Window#getOnBackInvokedDispatcher()}. *

- * 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. + * 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. *

* This replaces {@link Activity#onBackPressed()}, {@link Dialog#onBackPressed()} and * {@link android.view.KeyEvent#KEYCODE_BACK} - * + *

* @see OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback) * registerOnBackInvokedCallback(priority, OnBackInvokedCallback) * to specify callback priority. diff --git a/core/java/android/window/OnBackInvokedDispatcherOwner.java b/core/java/android/window/OnBackInvokedDispatcherOwner.java deleted file mode 100644 index dfe06fd39170..000000000000 --- a/core/java/android/window/OnBackInvokedDispatcherOwner.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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; - -/** - * A class that provides an {@link OnBackInvokedDispatcher} that allows you to register - * an {@link OnBackInvokedCallback} for handling the system back invocation behavior. - */ -public interface OnBackInvokedDispatcherOwner { - /** - * Returns the {@link OnBackInvokedDispatcher} that should dispatch the back invocation - * to its registered {@link OnBackInvokedCallback}s. - * Returns null when the root view is not attached to a window or a view tree with a decor. - */ - @NonNull - OnBackInvokedDispatcher getOnBackInvokedDispatcher(); -} diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java index 8a3b4ac8ba8c..44093971a23e 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -28,8 +28,8 @@ import java.util.List; * {@link OnBackInvokedDispatcher} only used to hold callbacks while an actual * dispatcher becomes available. It does not dispatch the back events. *

- * Once the actual {@link OnBackInvokedDispatcherOwner} becomes available, - * {@link #setActualDispatcherOwner(OnBackInvokedDispatcherOwner)} needs to + * Once the actual {@link OnBackInvokedDispatcher} becomes available, + * {@link #setActualDispatcher(OnBackInvokedDispatcher)} needs to * be called and this {@link ProxyOnBackInvokedDispatcher} will pass the callback registrations * onto it. *

@@ -48,14 +48,14 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { */ private final List> mCallbacks = new ArrayList<>(); private final Object mLock = new Object(); - private OnBackInvokedDispatcherOwner mActualDispatcherOwner = null; + private OnBackInvokedDispatcher mActualDispatcher = null; @Override public void registerOnBackInvokedCallback( int priority, @NonNull OnBackInvokedCallback callback) { if (DEBUG) { - Log.v(TAG, String.format("Proxy: register %s. actualDispatcherOwner=%s", callback, - mActualDispatcherOwner)); + Log.v(TAG, String.format("Proxy register %s. mActualDispatcher=%s", callback, + mActualDispatcher)); } if (priority < 0) { throw new IllegalArgumentException("Application registered OnBackInvokedCallback " @@ -74,13 +74,12 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @NonNull OnBackInvokedCallback callback) { if (DEBUG) { Log.v(TAG, String.format("Proxy unregister %s. Actual=%s", callback, - mActualDispatcherOwner)); + mActualDispatcher)); } synchronized (mLock) { mCallbacks.removeIf((p) -> p.first.equals(callback)); - if (mActualDispatcherOwner != null) { - mActualDispatcherOwner.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback( - callback); + if (mActualDispatcher != null) { + mActualDispatcher.unregisterOnBackInvokedCallback(callback); } } } @@ -89,9 +88,8 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { @NonNull OnBackInvokedCallback callback, int priority) { synchronized (mLock) { mCallbacks.add(Pair.create(callback, priority)); - if (mActualDispatcherOwner != null) { - mActualDispatcherOwner.getOnBackInvokedDispatcher().registerOnBackInvokedCallback( - priority, callback); + if (mActualDispatcher != null) { + mActualDispatcher.registerOnBackInvokedCallback(priority, callback); } } } @@ -103,34 +101,30 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { * proxy dispatcher. */ private void transferCallbacksToDispatcher() { - if (mActualDispatcherOwner == null) { + if (mActualDispatcher == null) { return; } - OnBackInvokedDispatcher dispatcher = - mActualDispatcherOwner.getOnBackInvokedDispatcher(); if (DEBUG) { - Log.v(TAG, String.format("Proxy: transferring %d pending callbacks to %s", - mCallbacks.size(), dispatcher)); + Log.v(TAG, String.format("Proxy transferring %d callbacks to %s", mCallbacks.size(), + mActualDispatcher)); } for (Pair callbackPair : mCallbacks) { int priority = callbackPair.second; if (priority >= 0) { - dispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); + mActualDispatcher.registerOnBackInvokedCallback(priority, callbackPair.first); } else { - dispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); + mActualDispatcher.registerSystemOnBackInvokedCallback(callbackPair.first); } } mCallbacks.clear(); } private void clearCallbacksOnDispatcher() { - if (mActualDispatcherOwner == null) { + if (mActualDispatcher == null) { return; } - OnBackInvokedDispatcher onBackInvokedDispatcher = - mActualDispatcherOwner.getOnBackInvokedDispatcher(); for (Pair callback : mCallbacks) { - onBackInvokedDispatcher.unregisterOnBackInvokedCallback(callback.first); + mActualDispatcher.unregisterOnBackInvokedCallback(callback.first); } } @@ -138,7 +132,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { * Resets this {@link ProxyOnBackInvokedDispatcher} so it loses track of the currently * registered callbacks. *

- * Using this method means that when setting a new {@link OnBackInvokedDispatcherOwner}, the + * Using this method means that when setting a new {@link OnBackInvokedDispatcher}, the * callbacks registered on the old one won't be removed from it and won't be registered on * the new one. */ @@ -152,28 +146,26 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } /** - * Sets the actual {@link OnBackInvokedDispatcherOwner} that will provides the - * {@link OnBackInvokedDispatcher} onto which the callbacks will be registered. + * Sets the actual {@link OnBackInvokedDispatcher} onto which the callbacks will be registered. *

- * If any dispatcher owner was already present, all the callbacks that were added via this + * If any dispatcher was already present, all the callbacks that were added via this * {@link ProxyOnBackInvokedDispatcher} will be unregistered from the old one and registered * on the new one if it is not null. *

* If you do not wish for the previously registered callbacks to be reassigned to the new * dispatcher, {@link #reset} must be called beforehand. */ - public void setActualDispatcherOwner( - @Nullable OnBackInvokedDispatcherOwner actualDispatcherOwner) { + public void setActualDispatcher(@Nullable OnBackInvokedDispatcher actualDispatcher) { if (DEBUG) { Log.v(TAG, String.format("Proxy setActual %s. Current %s", - actualDispatcherOwner, mActualDispatcherOwner)); + actualDispatcher, mActualDispatcher)); } synchronized (mLock) { - if (actualDispatcherOwner == mActualDispatcherOwner) { + if (actualDispatcher == mActualDispatcher) { return; } clearCallbacksOnDispatcher(); - mActualDispatcherOwner = actualDispatcherOwner; + mActualDispatcher = actualDispatcher; transferCallbacksToDispatcher(); } } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index b4ba16fef8e2..488fb180723e 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -111,7 +111,6 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.window.OnBackInvokedDispatcher; -import android.window.OnBackInvokedDispatcherOwner; import android.window.ProxyOnBackInvokedDispatcher; import com.android.internal.R; @@ -137,8 +136,7 @@ import java.util.List; * * @hide */ -public class PhoneWindow extends Window implements MenuBuilder.Callback, - OnBackInvokedDispatcherOwner { +public class PhoneWindow extends Window implements MenuBuilder.Callback { private final static String TAG = "PhoneWindow"; @@ -2153,7 +2151,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback, /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */ void onViewRootImplSet(ViewRootImpl viewRoot) { viewRoot.setActivityConfigCallback(mActivityConfigCallback); - mProxyOnBackInvokedDispatcher.setActualDispatcherOwner(viewRoot); + mProxyOnBackInvokedDispatcher.setActualDispatcher(viewRoot.getOnBackInvokedDispatcher()); applyDecorFitsSystemWindows(); }