diff options
3 files changed, 111 insertions, 87 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index eb16394e4edb..428a99c8464d 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -703,12 +703,6 @@ "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", @@ -859,6 +853,12 @@ "group": "WM_DEBUG_ANIM", "at": "com\/android\/server\/wm\/WindowState.java" }, + "-1277068810": { + "message": "startBackNavigation currentTask=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "-1270731689": { "message": "Attempted to set replacing window on app token with no content %s", "level": "WARN", @@ -1099,12 +1099,6 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, - "-1010850753": { - "message": "No focused window, defaulting to top task's window", - "level": "WARN", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "-1009117329": { "message": "isFetchingAppTransitionSpecs=true", "level": "VERBOSE", @@ -3049,12 +3043,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "878005951": { - "message": "startBackNavigation task=%s, topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "892244061": { "message": "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", "level": "INFO", @@ -3331,12 +3319,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "1172542963": { - "message": "onBackNavigationDone backType=%s, task=%s, prevTaskTopActivity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_BACK_PREVIEW", - "at": "com\/android\/server\/wm\/BackNavigationController.java" - }, "1175495463": { "message": "ImeContainer just became organized. Reparenting under parent. imeParentSurfaceControl=%s", "level": "INFO", @@ -3409,6 +3391,12 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "1264179654": { + "message": "No focused window, defaulting to top current task's window", + "level": "WARN", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "1270792394": { "message": "Resumed after relaunch %s", "level": "DEBUG", @@ -3853,6 +3841,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "1778919449": { + "message": "onBackNavigationDone backType=%s, task=%s, prevActivity=%s", + "level": "DEBUG", + "group": "WM_DEBUG_BACK_PREVIEW", + "at": "com\/android\/server\/wm\/BackNavigationController.java" + }, "1781673113": { "message": "onAnimationFinished(): targetRootTask=%s targetActivity=%s mRestoreTargetBehindRootTask=%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 f70dc52bf5e7..b37f980ce9a0 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -94,12 +94,22 @@ class BackNavigationController { } int backType = BackNavigationInfo.TYPE_UNDEFINED; + + // The currently visible activity (if any). + ActivityRecord currentActivity = null; + + // The currently visible task (if any). + Task currentTask = null; + + // The previous task we're going back to. Can be the same as currentTask, if there are + // multiple Activities in the Stack. Task prevTask = null; - ActivityRecord prev; + + // The previous activity we're going back to. This can be either a child of currentTask + // if there are more than one Activity in currentTask, or a child of prevTask, if + // currentActivity is the last child of currentTask. + ActivityRecord prevActivity; WindowContainer<?> removedWindowContainer = null; - ActivityRecord activityRecord = null; - ActivityRecord prevTaskTopActivity = null; - Task task = null; SurfaceControl animationLeashParent = null; HardwareBuffer screenshotBuffer = null; RemoteAnimationTarget topAppTarget = null; @@ -143,19 +153,19 @@ class BackNavigationController { } if (window == null) { - // We don't have any focused window, fallback ont the top task of the focused + // 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 task's window"); - task = wmService.mAtmService.getTopDisplayFocusedRootTask(); - window = task.getWindow(WindowState::isFocused); + "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) { - activityRecord = window.mActivityRecord; - task = window.getTask(); + currentActivity = window.mActivityRecord; + currentTask = window.getTask(); callbackInfo = window.getOnBackInvokedCallbackInfo(); if (callbackInfo == null) { Slog.e(TAG, "No callback registered, returning null."); @@ -167,9 +177,9 @@ class BackNavigationController { infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback()); } - ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation task=%s, " + ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "startBackNavigation currentTask=%s, " + "topRunningActivity=%s, callbackInfo=%s, currentFocus=%s", - task, activityRecord, callbackInfo, window); + currentTask, currentActivity, callbackInfo, window); if (window == null) { Slog.e(TAG, "Window is null, returning null."); @@ -182,18 +192,18 @@ class BackNavigationController { // - The IME is opened, and we just need to close it. // - The home activity is the focused activity. if (backType == BackNavigationInfo.TYPE_CALLBACK - || activityRecord == null - || task == null - || task.getDisplayContent().getImeContainer().isVisible() - || activityRecord.isActivityTypeHome()) { + || currentActivity == null + || currentTask == null + || currentTask.getDisplayContent().getImeContainer().isVisible() + || currentActivity.isActivityTypeHome()) { return infoBuilder .setType(backType) .build(); } // We don't have an application callback, let's find the destination of the back gesture - Task finalTask = task; - prev = task.getActivity( + Task finalTask = currentTask; + prevActivity = currentTask.getActivity( (r) -> !r.finishing && r.getTask() == finalTask && !r.isTopRunningActivity()); if (window.getParent().getChildCount() > 1 && window.getParent().getChildAt(0) != window) { @@ -201,24 +211,24 @@ class BackNavigationController { // activity, we won't close the activity. backType = BackNavigationInfo.TYPE_DIALOG_CLOSE; removedWindowContainer = window; - } else if (prev != null) { - // We have another Activity in the same task to go to + } else if (prevActivity != null) { + // We have another Activity in the same currentTask to go to backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY; - removedWindowContainer = activityRecord; - } else if (task.returnsToHomeRootTask()) { + removedWindowContainer = currentActivity; + } else if (currentTask.returnsToHomeRootTask()) { // Our Task should bring back to home - removedWindowContainer = task; + removedWindowContainer = currentTask; backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; - } else if (activityRecord.isRootOfTask()) { + } else if (currentActivity.isRootOfTask()) { // TODO(208789724): Create single source of truth for this, maybe in // RootWindowContainer - // TODO: Also check Task.shouldUpRecreateTaskLocked() for prev logic - prevTask = task.mRootWindowContainer.getTaskBelow(task); - removedWindowContainer = task; + // TODO: Also check Task.shouldUpRecreateTaskLocked() for prevActivity logic + prevTask = currentTask.mRootWindowContainer.getTaskBelow(currentTask); + removedWindowContainer = currentTask; + prevActivity = prevTask.getTopNonFinishingActivity(); if (prevTask.isActivityTypeHome()) { backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; } else { - prev = prevTask.getTopNonFinishingActivity(); backType = BackNavigationInfo.TYPE_CROSS_TASK; } } @@ -229,7 +239,7 @@ class BackNavigationController { ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Previous Destination is Activity:%s Task:%s " + "removedContainer:%s, backType=%s", - prev != null ? prev.mActivityComponent : null, + prevActivity != null ? prevActivity.mActivityComponent : null, prevTask != null ? prevTask.getName() : null, removedWindowContainer, BackNavigationInfo.typeToString(backType)); @@ -241,7 +251,8 @@ class BackNavigationController { && !removedWindowContainer.hasCommittedReparentToAnimationLeash(); if (prepareAnimation) { - taskWindowConfiguration = task.getTaskInfo().configuration.windowConfiguration; + taskWindowConfiguration = + currentTask.getTaskInfo().configuration.windowConfiguration; infoBuilder.setTaskWindowConfiguration(taskWindowConfiguration); // Prepare a leash to animate the current top window @@ -254,32 +265,36 @@ class BackNavigationController { removedWindowContainer.reparentSurfaceControl(tx, animLeash); animationLeashParent = removedWindowContainer.getAnimationLeashParent(); topAppTarget = createRemoteAnimationTargetLocked(removedWindowContainer, - activityRecord, - task, animLeash); + currentActivity, + currentTask, animLeash); infoBuilder.setDepartingAnimationTarget(topAppTarget); } //TODO(207481538) Remove once the infrastructure to support per-activity screenshot is // implemented. For now we simply have the mBackScreenshots hash map that dumbly // saves the screenshots. - if (needsScreenshot(backType) && prev != null && prev.mActivityComponent != null) { - screenshotBuffer = getActivitySnapshot(task, prev.mActivityComponent); + if (needsScreenshot(backType) && prevActivity != null + && prevActivity.mActivityComponent != null) { + screenshotBuffer = + getActivitySnapshot(currentTask, prevActivity.mActivityComponent); } - if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { - task.mBackGestureStarted = true; + // Special handling for back to home animation + if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled() + && prevTask != null) { + currentTask.mBackGestureStarted = true; // Make launcher show from behind by marking its top activity as visible and // launch-behind to bump its visibility for the duration of the back gesture. - prevTaskTopActivity = prevTask.getTopNonFinishingActivity(); - if (prevTaskTopActivity != null) { - if (!prevTaskTopActivity.mVisibleRequested) { - prevTaskTopActivity.setVisibility(true); + prevActivity = prevTask.getTopNonFinishingActivity(); + if (prevActivity != null) { + if (!prevActivity.mVisibleRequested) { + prevActivity.setVisibility(true); } - prevTaskTopActivity.mLaunchTaskBehind = true; + prevActivity.mLaunchTaskBehind = true; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to true. Activity=%s", - prevTaskTopActivity); - prevTaskTopActivity.mRootWindowContainer.ensureActivitiesVisible( + prevActivity); + prevActivity.mRootWindowContainer.ensureActivitiesVisible( null /* starting */, 0 /* configChanges */, false /* preserveWindows */); } @@ -290,7 +305,7 @@ class BackNavigationController { if (topAppTarget != null && needsScreenshot(backType) && prevTask != null && screenshotBuffer == null) { SurfaceControl.Builder builder = new SurfaceControl.Builder() - .setName("BackPreview Screenshot for " + prev) + .setName("BackPreview Screenshot for " + prevActivity) .setParent(animationLeashParent) .setHidden(false) .setBLASTLayer(); @@ -302,12 +317,12 @@ class BackNavigationController { // The Animation leash needs to be above the screenshot surface, but the animation leash // needs to be added before to be in the synchronized block. tx.setLayer(topAppTarget.leash, 1); - tx.apply(); - + } - WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; + WindowContainer<?> finalRemovedWindowContainer = removedWindowContainer; + if (finalRemovedWindowContainer != null) { try { - activityRecord.token.linkToDeath( + currentActivity.token.linkToDeath( () -> resetSurfaces(finalRemovedWindowContainer), 0); } catch (RemoteException e) { Slog.e(TAG, "Failed to link to death", e); @@ -315,11 +330,16 @@ class BackNavigationController { return null; } - RemoteCallback onBackNavigationDone = new RemoteCallback( - result -> resetSurfaces(finalRemovedWindowContainer - )); + int finalBackType = backType; + ActivityRecord finalprevActivity = prevActivity; + Task finalTask = currentTask; + RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone( + result, finalRemovedWindowContainer, finalBackType, finalTask, + finalprevActivity)); infoBuilder.setOnBackNavigationDone(onBackNavigationDone); } + + tx.apply(); return infoBuilder.build(); } @@ -348,14 +368,13 @@ class BackNavigationController { } private void onBackNavigationDone( - Bundle result, WindowContainer windowContainer, int backType, - Task task, ActivityRecord prevTaskTopActivity) { + Bundle result, WindowContainer<?> windowContainer, int backType, + Task task, ActivityRecord prevActivity) { SurfaceControl surfaceControl = windowContainer.getSurfaceControl(); - boolean triggerBack = result != null - ? result.getBoolean(BackNavigationInfo.KEY_TRIGGER_BACK) - : false; + boolean triggerBack = result != null && result.getBoolean( + BackNavigationInfo.KEY_TRIGGER_BACK); ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, " - + "task=%s, prevTaskTopActivity=%s", backType, task, prevTaskTopActivity); + + "task=%s, prevActivity=%s", backType, task, prevActivity); if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && isAnimationEnabled()) { if (triggerBack) { @@ -367,13 +386,13 @@ class BackNavigationController { t.apply(); } } - if (prevTaskTopActivity != null && !triggerBack) { + if (prevActivity != null && !triggerBack) { // Restore the launch-behind state. - task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevTaskTopActivity.token); - prevTaskTopActivity.mLaunchTaskBehind = false; + task.mTaskSupervisor.scheduleLaunchTaskBehindComplete(prevActivity.token); + prevActivity.mLaunchTaskBehind = false; ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "Setting Activity.mLauncherTaskBehind to false. Activity=%s", - prevTaskTopActivity); + prevActivity); } } else { task.mBackGestureStarted = false; 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 fe59185a6893..49cd343ef4af 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -29,9 +29,12 @@ 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.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; @@ -39,6 +42,7 @@ import android.annotation.Nullable; import android.hardware.HardwareBuffer; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.view.SurfaceControl; import android.view.WindowManager; import android.window.BackEvent; import android.window.BackNavigationInfo; @@ -77,15 +81,22 @@ public class BackNavigationControllerTests extends WindowTestsBase { @Test public void backNavInfo_HomeWhenBackToLauncher() { - IOnBackInvokedCallback callback = withSystemCallback(createTopTaskWithActivity()); + Task task = createTopTaskWithActivity(); + IOnBackInvokedCallback callback = withSystemCallback(task); - BackNavigationInfo backNavigationInfo = startBackNavigation(); + SurfaceControl.Transaction tx = mock(SurfaceControl.Transaction.class); + BackNavigationInfo backNavigationInfo = mBackNavigationController.startBackNavigation(mWm, + tx); assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull(); assertThat(backNavigationInfo.getDepartingAnimationTarget()).isNotNull(); assertThat(backNavigationInfo.getTaskWindowConfiguration()).isNotNull(); assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback); assertThat(typeToString(backNavigationInfo.getType())) .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME)); + + verify(tx, atLeastOnce()).apply(); + verify(tx, times(1)).reparent(any(), + eq(backNavigationInfo.getDepartingAnimationTarget().leash)); } @Test |