From 7c64d6873a5f72cb11a6a62ab5771c5a50eed14c Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Wed, 8 Nov 2023 07:19:40 +0000 Subject: Refine back navigation search method. - Remove embedded window check, EmbeddedWindowController#getByFocusToken should search with input token instead of window token, so it always return null nowaday. - Skip search if the closing target isn't visibleRequested, usually that means the closing transition is collecting or playing, either case the window shouldn't receive another back invoked event. Inject the back key then next focus app will handle it. - Use TYPE_CALLBACK if we cannot find any task below current task, this could also happen on some specific device.(e.g. No home) Bug: 303266152 Bug: 309683765 Test: atest BackNavigationControllerTests Change-Id: Ia1f5ec664ea7154d9c8ac59cbc247a51226dfdf1 --- data/etc/services.core.protolog.json | 30 +---- .../server/wm/BackNavigationController.java | 133 +++++++++------------ .../server/wm/BackNavigationControllerTests.java | 14 +++ 3 files changed, 76 insertions(+), 101 deletions(-) diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index dc2b0561957d..b06561101071 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -415,12 +415,6 @@ "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/Transition.java" }, - "-1717147904": { - "message": "Current focused window is embeddedWindow. Dispatch KEYCODE_BACK.", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "-1710206702": { "message": "Display id=%d is frozen while keyguard locked, return %d", "level": "VERBOSE", @@ -1213,12 +1207,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-997565097": { - "message": "Focused window found using getFocusedWindowToken", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "-993378225": { "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", "level": "VERBOSE", @@ -2233,6 +2221,12 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, + "-98422345": { + "message": "Focus window is closing.", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "-91393839": { "message": "Set animatingExit: reason=remove\/applyAnimation win=%s", "level": "VERBOSE", @@ -2731,12 +2725,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "309039362": { - "message": "SURFACE MATRIX [%f,%f,%f,%f]: %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" - }, "312030608": { "message": "New topFocusedDisplayId=%d", "level": "DEBUG", @@ -3091,12 +3079,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "633654009": { - "message": "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", - "level": "INFO", - "group": "WM_SHOW_TRANSACTIONS", - "at": "com\/android\/server\/wm\/WindowSurfaceController.java" - }, "638429464": { "message": "\tRemove container=%s", "level": "DEBUG", diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 87ae045d4f12..43f32096b6c0 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -39,7 +39,6 @@ import android.content.res.ResourceId; import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; -import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SystemProperties; @@ -60,7 +59,6 @@ import android.window.TaskSnapshot; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TransitionAnimation; import com.android.internal.protolog.common.ProtoLog; -import com.android.server.LocalServices; import com.android.server.wm.utils.InsetUtils; import java.io.PrintWriter; @@ -151,97 +149,77 @@ class BackNavigationController { // Don't start any animation for it. return null; } - WindowManagerInternal windowManagerInternal = - LocalServices.getService(WindowManagerInternal.class); - IBinder focusedWindowToken = windowManagerInternal.getFocusedWindowToken(); window = wmService.getFocusedWindowLocked(); - if (window == null) { - EmbeddedWindowController.EmbeddedWindow embeddedWindow = - wmService.mEmbeddedWindowController.getByInputTransferToken( - focusedWindowToken); - if (embeddedWindow != null) { - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, - "Current focused window is embeddedWindow. Dispatch KEYCODE_BACK."); - return null; - } - } - - // Lets first gather the states of things - // - What is our current window ? - // - Does it has an Activity and a Task ? - // TODO Temp workaround for Sysui until b/221071505 is fixed - if (window != null) { - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, - "Focused window found using getFocusedWindowToken"); - } - - if (window != null) { - // This is needed to bridge the old and new back behavior with recents. While in - // Overview with live tile enabled, the previous app is technically focused but we - // add an input consumer to capture all input that would otherwise go to the apps - // being controlled by the animation. This means that the window resolved is not - // the right window to consume back while in overview, so we need to route it to - // launcher and use the legacy behavior of injecting KEYCODE_BACK since the existing - // compat callback in VRI only works when the window is focused. - // This symptom also happen while shell transition enabled, we can check that by - // isTransientLaunch to know whether the focus window is point to live tile. - final RecentsAnimationController recentsAnimationController = - wmService.getRecentsAnimationController(); - final ActivityRecord ar = window.mActivityRecord; - if ((ar != null && ar.isActivityTypeHomeOrRecents() - && ar.mTransitionController.isTransientLaunch(ar)) - || (recentsAnimationController != null - && recentsAnimationController.shouldApplyInputConsumer(ar))) { - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Current focused window being animated by " - + "recents. Overriding back callback to recents controller callback."); - return null; - } - - if (!window.isDrawn()) { - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, - "Focused window didn't have a valid surface drawn."); - return null; - } - } - if (window == null) { // We don't have any focused window, fallback ont the top currentTask of the focused // display. ProtoLog.w(WM_DEBUG_BACK_PREVIEW, "No focused window, defaulting to top current task's window"); currentTask = wmService.mAtmService.getTopDisplayFocusedRootTask(); - window = currentTask.getWindow(WindowState::isFocused); + window = currentTask != null + ? currentTask.getWindow(WindowState::isFocused) : null; + } + + if (window == null) { + Slog.e(TAG, "Window is null, returning null."); + return null; } + // This is needed to bridge the old and new back behavior with recents. While in + // Overview with live tile enabled, the previous app is technically focused but we + // add an input consumer to capture all input that would otherwise go to the apps + // being controlled by the animation. This means that the window resolved is not + // the right window to consume back while in overview, so we need to route it to + // launcher and use the legacy behavior of injecting KEYCODE_BACK since the existing + // compat callback in VRI only works when the window is focused. + // This symptom also happen while shell transition enabled, we can check that by + // isTransientLaunch to know whether the focus window is point to live tile. + final RecentsAnimationController recentsAnimationController = + wmService.getRecentsAnimationController(); + final ActivityRecord tmpAR = window.mActivityRecord; + if ((tmpAR != null && tmpAR.isActivityTypeHomeOrRecents() + && tmpAR.mTransitionController.isTransientLaunch(tmpAR)) + || (recentsAnimationController != null + && recentsAnimationController.shouldApplyInputConsumer(tmpAR))) { + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Current focused window being animated by " + + "recents. Overriding back callback to recents controller callback."); + return null; + } + + if (!window.isDrawn()) { + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, + "Focused window didn't have a valid surface drawn."); + return null; + } + + currentActivity = window.mActivityRecord; + currentTask = window.getTask(); + if ((currentTask != null && !currentTask.isVisibleRequested()) + || (currentActivity != null && !currentActivity.isVisibleRequested())) { + // Closing transition is happening on focus window and should be update soon, + // don't drive back navigation with it. + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Focus window is closing."); + return null; + } // Now let's find if this window has a callback from the client side. - OnBackInvokedCallbackInfo callbackInfo = null; - if (window != null) { - currentActivity = window.mActivityRecord; - currentTask = window.getTask(); - callbackInfo = window.getOnBackInvokedCallbackInfo(); - if (callbackInfo == null) { - Slog.e(TAG, "No callback registered, returning null."); - return null; - } - if (!callbackInfo.isSystemCallback()) { - backType = BackNavigationInfo.TYPE_CALLBACK; - } - infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback()); - infoBuilder.setAnimationCallback(callbackInfo.isAnimationCallback()); - mNavigationMonitor.startMonitor(window, navigationObserver); + final OnBackInvokedCallbackInfo callbackInfo = window.getOnBackInvokedCallbackInfo(); + if (callbackInfo == null) { + Slog.e(TAG, "No callback registered, returning null."); + return null; } + if (!callbackInfo.isSystemCallback()) { + backType = BackNavigationInfo.TYPE_CALLBACK; + } + infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback()); + infoBuilder.setAnimationCallback(callbackInfo.isAnimationCallback()); + mNavigationMonitor.startMonitor(window, navigationObserver); ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, " + "topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", currentTask, currentActivity, callbackInfo, window); - if (window == null) { - Slog.e(TAG, "Window is null, returning null."); - return null; - } - // If we don't need to set up the animation, we return early. This is the case when // - We have an application callback. // - We don't have any ActivityRecord or Task to animate. @@ -322,12 +300,13 @@ class BackNavigationController { } return false; }, currentTask, false /*includeBoundary*/, true /*traverseTopToBottom*/); - final ActivityRecord tmpPre = prevTask.getTopNonFinishingActivity(); + final ActivityRecord tmpPre = prevTask != null + ? prevTask.getTopNonFinishingActivity() : null; if (tmpPre != null) { prevActivities.add(tmpPre); findAdjacentActivityIfExist(tmpPre, prevActivities); } - if (prevActivities.isEmpty() + if (prevTask == null || prevActivities.isEmpty() || (isOccluded && !prevActivities.get(0).canShowWhenLocked())) { backType = BackNavigationInfo.TYPE_CALLBACK; } else if (prevTask.isActivityTypeHome()) { 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 6790dc2e8733..afea8114d508 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -116,6 +116,20 @@ public class BackNavigationControllerTests extends WindowTestsBase { assertTrue("Animation scheduled", backNavigationInfo.isPrepareRemoteAnimation()); } + @Test + public void noBackWhenMoveTaskToBack() { + Task taskA = createTask(mDefaultDisplay); + ActivityRecord recordA = createActivityRecord(taskA); + Mockito.doNothing().when(recordA).reparentSurfaceControl(any(), any()); + + final Task topTask = createTopTaskWithActivity(); + withSystemCallback(topTask); + // simulate moveTaskToBack + topTask.setVisibleRequested(false); + BackNavigationInfo backNavigationInfo = startBackNavigation(); + assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNull(); + } + @Test public void backTypeCrossTaskWhenBackToPreviousTask() { Task taskA = createTask(mDefaultDisplay); -- cgit v1.2.3-59-g8ed1b