From 83b2b0c68df66895658ef7d6d4629eaa95538d7c Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Fri, 25 Nov 2022 08:12:19 +0000 Subject: [PATCH] Don't prepare back animation from different user's task/activity. Also fix a NPE crash for returnsToHomeRootTask. Fixes: 260375814 Test: atest BackNavigationControllerTests Change-Id: Ib84c035b1e6c32c8646d499910eac995a60e46e8 --- .../server/wm/BackNavigationController.java | 15 +++++++++++---- .../server/wm/BackNavigationControllerTests.java | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 3bb02382b57c4..14d6d7bdfb7dd 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; @@ -226,9 +227,8 @@ class BackNavigationController { mBackAnimationInProgress = true; // We don't have an application callback, let's find the destination of the back gesture - Task finalTask = currentTask; - prevActivity = currentTask.getActivity( - (r) -> !r.finishing && r.getTask() == finalTask && !r.isTopRunningActivity()); + // The search logic should align with ActivityClientController#finishActivity + prevActivity = currentTask.topRunningActivity(currentActivity.token, INVALID_TASK_ID); // TODO Dialog window does not need to attach on activity, check // window.mAttrs.type != TYPE_BASE_APPLICATION if ((window.getParent().getChildCount() > 1 @@ -244,12 +244,14 @@ class BackNavigationController { } else if (currentTask.returnsToHomeRootTask()) { // Our Task should bring back to home removedWindowContainer = currentTask; + prevTask = currentTask.getDisplayArea().getRootHomeTask(); backType = BackNavigationInfo.TYPE_RETURN_TO_HOME; mShowWallpaper = true; } else if (currentActivity.isRootOfTask()) { // TODO(208789724): Create single source of truth for this, maybe in // RootWindowContainer - prevTask = currentTask.mRootWindowContainer.getTaskBelow(currentTask); + prevTask = currentTask.mRootWindowContainer.getTask(Task::showToCurrentUser, + currentTask, false /*includeBoundary*/, true /*traverseTopToBottom*/); removedWindowContainer = currentTask; // If it reaches the top activity, we will check the below task from parent. // If it's null or multi-window, fallback the type to TYPE_CALLBACK. @@ -423,6 +425,11 @@ class BackNavigationController { void reset(@NonNull WindowContainer close, @NonNull WindowContainer open) { clearBackAnimateTarget(null); + if (close == null || open == null) { + Slog.e(TAG, "reset animation with null target close: " + + close + " open: " + open); + return; + } if (close.asActivityRecord() != null && open.asActivityRecord() != null && (close.asActivityRecord().getTask() == open.asActivityRecord().getTask())) { mSwitchType = ACTIVITY_SWITCH; 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 f3f56e0709d8f..dc3515dec2f59 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -113,6 +113,20 @@ public class BackNavigationControllerTests extends WindowTestsBase { any()); } + @Test + public void backTypeBackToHomeDifferentUser() { + Task taskA = createTask(mDefaultDisplay); + ActivityRecord recordA = createActivityRecord(taskA); + Mockito.doNothing().when(recordA).reparentSurfaceControl(any(), any()); + doReturn(false).when(taskA).showToCurrentUser(); + + withSystemCallback(createTopTaskWithActivity()); + BackNavigationInfo backNavigationInfo = startBackNavigation(); + assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull(); + assertThat(typeToString(backNavigationInfo.getType())) + .isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME)); + } + @Test public void backTypeCrossActivityWhenBackToPreviousActivity() { CrossActivityTestCase testCase = createTopTaskWithTwoActivities();