diff options
7 files changed, 90 insertions, 16 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 931ae2748785..3b371faecacb 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -10743,7 +10743,7 @@ public final class ViewRootImpl implements ViewParent, private void registerBackCallbackOnWindow() { if (OnBackInvokedDispatcher.DEBUG) { Log.d(OnBackInvokedDispatcher.TAG, TextUtils.formatSimple( - "ViewRootImpl.registerBackCallbackOnWindow. Callback:%s Package:%s " + "ViewRootImpl.registerBackCallbackOnWindow. Dispatcher:%s Package:%s " + "IWindow:%s Session:%s", mOnBackInvokedDispatcher, mBasePackageName, mWindow, mWindowSession)); } diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java index c254a9df3b4c..6bc2b5043e79 100644 --- a/core/java/android/window/OnBackInvokedDispatcher.java +++ b/core/java/android/window/OnBackInvokedDispatcher.java @@ -19,7 +19,6 @@ package android.window; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SuppressLint; import android.os.Build; @@ -93,15 +92,6 @@ public interface OnBackInvokedDispatcher { 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 */ diff --git a/core/java/android/window/ProxyOnBackInvokedDispatcher.java b/core/java/android/window/ProxyOnBackInvokedDispatcher.java index eb776310b8bb..8a3b4ac8ba8c 100644 --- a/core/java/android/window/ProxyOnBackInvokedDispatcher.java +++ b/core/java/android/window/ProxyOnBackInvokedDispatcher.java @@ -54,7 +54,7 @@ public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher { public void registerOnBackInvokedCallback( int priority, @NonNull OnBackInvokedCallback callback) { if (DEBUG) { - Log.v(TAG, String.format("Pending register %s. Actual=%s", callback, + Log.v(TAG, String.format("Proxy: register %s. actualDispatcherOwner=%s", callback, mActualDispatcherOwner)); } if (priority < 0) { diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java index 8811116b25ad..477da5e66651 100644 --- a/core/java/android/window/WindowOnBackInvokedDispatcher.java +++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java @@ -175,7 +175,6 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher { } } - @Override public OnBackInvokedCallback getTopCallback() { if (mAllCallbacks.isEmpty()) { return null; diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 3a900e6e6bfa..80b144acd991 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -703,6 +703,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "-1427392850": { + "message": "WindowState: Setting back callback %s (priority: %d) (Client IWindow: %s). (WindowState: %s)", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "-1427184084": { "message": "addWindow: New client %s: window=%s Callers=%s", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 88d17e4e6e0a..8546e8002602 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -250,6 +250,7 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.window.ClientWindowFrames; import android.window.IOnBackInvokedCallback; +import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.KeyInterceptionInfo; @@ -1084,9 +1085,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP */ void setOnBackInvokedCallback( @Nullable IOnBackInvokedCallback onBackInvokedCallback, int priority) { - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "%s: Setting back callback %s. Client IWindow %s", - this, onBackInvokedCallback, mClient); - if (priority >= 0) { + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "WindowState: Setting back callback %s (priority: %d) " + + "(Client IWindow: %s). (WindowState: %s)", + onBackInvokedCallback, priority, mClient, this); + if (priority >= WindowOnBackInvokedDispatcher.PRIORITY_DEFAULT) { mApplicationOnBackInvokedCallback = onBackInvokedCallback; mSystemOnBackInvokedCallback = null; } else { 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 f44de1e46c0f..a4a62a4254ad 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -23,8 +23,13 @@ import static android.window.BackNavigationInfo.typeToString; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,13 +37,16 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.HardwareBuffer; +import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.view.WindowManager; import android.window.BackEvent; import android.window.BackNavigationInfo; import android.window.IOnBackInvokedCallback; +import android.window.OnBackInvokedCallback; import android.window.OnBackInvokedDispatcher; import android.window.TaskSnapshot; +import android.window.WindowOnBackInvokedDispatcher; import com.android.server.LocalServices; @@ -46,6 +54,9 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + @Presubmit @RunWith(WindowTestRunner.class) public class BackNavigationControllerTests extends WindowTestsBase { @@ -148,6 +159,61 @@ public class BackNavigationControllerTests extends WindowTestsBase { assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(appCallback); } + @Test + public void testUnregisterCallbacksWithSystemCallback() + throws InterruptedException, RemoteException { + CountDownLatch systemLatch = new CountDownLatch(1); + CountDownLatch appLatch = new CountDownLatch(1); + + Task task = createTopTaskWithActivity(); + WindowState appWindow = task.getTopVisibleAppMainWindow(); + WindowOnBackInvokedDispatcher dispatcher = new WindowOnBackInvokedDispatcher(); + doAnswer(invocation -> { + appWindow.setOnBackInvokedCallback(invocation.getArgument(1), + invocation.getArgument(2)); + return null; + }).when(appWindow.mSession).setOnBackInvokedCallback(eq(appWindow.mClient), any(), + anyInt()); + + addToWindowMap(appWindow, true); + dispatcher.attachToWindow(appWindow.mSession, appWindow.mClient); + + + OnBackInvokedCallback appCallback = createBackCallback(appLatch); + OnBackInvokedCallback systemCallback = createBackCallback(systemLatch); + + // Register both a system callback and an application callback + dispatcher.registerSystemOnBackInvokedCallback(systemCallback); + dispatcher.registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, + appCallback); + + // Check that the top callback is the app callback + assertEquals(appCallback, dispatcher.getTopCallback()); + + // Now unregister the app callback and check that the top callback is the system callback + dispatcher.unregisterOnBackInvokedCallback(appCallback); + assertEquals(systemCallback, dispatcher.getTopCallback()); + + // Verify that this has correctly been propagated to the server and that the + // BackNavigationInfo object will contain the system callback + BackNavigationInfo backNavigationInfo = startBackNavigation(); + assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull(); + IOnBackInvokedCallback callback = backNavigationInfo.getOnBackInvokedCallback(); + assertThat(callback).isNotNull(); + + try { + callback.onBackInvoked(); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + + // Check that the system callback has been call + assertTrue("System callback has not been called", + systemLatch.await(500, TimeUnit.MILLISECONDS)); + assertEquals("App callback should not have been called", + 1, appLatch.getCount()); + } + private IOnBackInvokedCallback withSystemCallback(Task task) { IOnBackInvokedCallback callback = createOnBackInvokedCallback(); task.getTopMostActivity().getTopChild().setOnBackInvokedCallback(callback, @@ -188,6 +254,17 @@ public class BackNavigationControllerTests extends WindowTestsBase { }; } + private OnBackInvokedCallback createBackCallback(CountDownLatch latch) { + return new OnBackInvokedCallback() { + @Override + public void onBackInvoked() { + if (latch != null) { + latch.countDown(); + } + } + }; + } + @NonNull private TaskSnapshotController createMockTaskSnapshotController() { TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class); |