Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c64d687 authored by wilsonshih's avatar wilsonshih
Browse files

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
parent 71014618
Loading
Loading
Loading
Loading
+6 −24
Original line number Diff line number Diff line
@@ -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",
+56 −77
Original line number Diff line number Diff line
@@ -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,33 +149,24 @@ 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;
                }
                // 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 != null
                        ? currentTask.getWindow(WindowState::isFocused) : 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) {
                Slog.e(TAG, "Window is null, returning null.");
                return null;
            }

            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
@@ -189,11 +178,11 @@ class BackNavigationController {
            // 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))
            final ActivityRecord tmpAR = window.mActivityRecord;
            if ((tmpAR != null && tmpAR.isActivityTypeHomeOrRecents()
                    && tmpAR.mTransitionController.isTransientLaunch(tmpAR))
                    || (recentsAnimationController != null
                        && recentsAnimationController.shouldApplyInputConsumer(ar))) {
                    && 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;
@@ -204,23 +193,18 @@ class BackNavigationController {
                        "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);
            }

            // 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 ((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.
            final OnBackInvokedCallbackInfo callbackInfo = window.getOnBackInvokedCallbackInfo();
            if (callbackInfo == null) {
                Slog.e(TAG, "No callback registered, returning null.");
                return null;
@@ -231,17 +215,11 @@ class BackNavigationController {
            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()) {
+14 −0
Original line number Diff line number Diff line
@@ -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);