From affbd7951e1e1e7697661f35592b9f297b3ec252 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Mon, 15 Aug 2022 06:14:25 +0000 Subject: [PATCH] Update top resumed activity and focused app while adding a task on top Drag to dismiss a split pair reparents the task on non-dismissing side to the top of its TaskDisplayArea. The focused app should be updated if the task on dismissing side was top focused. This makes sure to update top resumed activity when adding a task on top of a TaskDisplayArea. Also makes sure to update focsued app and last resumsed activity in AMS while updating top resumed activity. Fix: 242141128 Test: check mFocusedApp in dumpsys with repro steps of the bug Test: atest ActivityTaskSupervisorTests Test: atest ActivityRecordTests TaskDisplayAreaTests Change-Id: I2dd0ca73df9c46ffce42cfc52280be35aeb9e2ec --- .../java/com/android/server/wm/ActivityRecord.java | 2 +- .../android/server/wm/ActivityTaskManagerService.java | 2 +- .../com/android/server/wm/ActivityTaskSupervisor.java | 8 +++++++- .../com/android/server/wm/RootWindowContainer.java | 2 +- services/core/java/com/android/server/wm/Task.java | 8 ++------ .../java/com/android/server/wm/TaskDisplayArea.java | 11 +++++------ .../core/java/com/android/server/wm/TaskFragment.java | 5 +---- .../server/wm/ActivityTaskSupervisorTests.java | 5 +++-- 8 files changed, 21 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index bd88c41b52684..6ff9e57e5015d 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3247,7 +3247,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A rootTask.moveToFront(reason, task); // Report top activity change to tracking services and WM if (mRootWindowContainer.getTopResumedActivity() == this) { - mAtmService.setResumedActivityUncheckLocked(this, reason); + mAtmService.setLastResumedActivityUncheckLocked(this, reason); } return true; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 7d814c7047a79..90a8179c716f0 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4623,7 +4623,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } /** Update AMS states when an activity is resumed. */ - void setResumedActivityUncheckLocked(ActivityRecord r, String reason) { + void setLastResumedActivityUncheckLocked(ActivityRecord r, String reason) { final Task task = r.getTask(); if (task.isActivityTypeStandard()) { if (mCurAppTimeTracker != r.appTimeTracker) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 208b001dfd0e3..a870b8afe2f97 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2083,7 +2083,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { * activity releases the top state and reports back, message about acquiring top state will be * sent to the new top resumed activity. */ - void updateTopResumedActivityIfNeeded() { + void updateTopResumedActivityIfNeeded(String reason) { final ActivityRecord prevTopActivity = mTopResumedActivity; final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); if (topRootTask == null || topRootTask.getTopResumedActivity() == prevTopActivity) { @@ -2119,6 +2119,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } mService.updateOomAdj(); } + // Update the last resumed activity and focused app when the top resumed activity changed + // because the new top resumed activity might be already resumed and thus won't have + // activity state change to update the records to AMS. + if (mTopResumedActivity != null) { + mService.setLastResumedActivityUncheckLocked(mTopResumedActivity, reason); + } scheduleTopResumedActivityStateIfNeeded(); mService.updateTopApp(mTopResumedActivity); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index aab9d5bc8cf1f..b79c6f44bad5c 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -514,7 +514,7 @@ class RootWindowContainer extends WindowContainer void onChildPositionChanged(WindowContainer child) { mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, !mWmService.mPerDisplayFocusEnabled /* updateInputWindows */); - mTaskSupervisor.updateTopResumedActivityIfNeeded(); + mTaskSupervisor.updateTopResumedActivityIfNeeded("onChildPositionChanged"); } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 75552e079575e..e1334dc0ab88a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -920,7 +920,7 @@ class Task extends TaskFragment { // If the original state is resumed, there is no state change to update focused app. // So here makes sure the activity focus is set if it is the top. if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) { - mAtmService.setResumedActivityUncheckLocked(r, reason); + mAtmService.setLastResumedActivityUncheckLocked(r, reason); } } if (!animate) { @@ -2439,11 +2439,7 @@ class Task extends TaskFragment { focusableTask.moveToFront(myReason); // Top display focused root task is changed, update top resumed activity if needed. if (rootTask.getTopResumedActivity() != null) { - mTaskSupervisor.updateTopResumedActivityIfNeeded(); - // Set focused app directly because if the next focused activity is already resumed - // (e.g. the next top activity is on a different display), there won't have activity - // state change to update it. - mAtmService.setResumedActivityUncheckLocked(rootTask.getTopResumedActivity(), reason); + mTaskSupervisor.updateTopResumedActivityIfNeeded(reason); } return rootTask; } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 8220cae74dc81..0f46c4f166aee 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -323,6 +323,10 @@ final class TaskDisplayArea extends DisplayArea { // Clear preferred top because the adding focusable task has a higher z-order. mPreferredTopFocusableRootTask = null; } + + // Update the top resumed activity because the preferred top focusable task may be changed. + mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("addChildTask"); + mAtmService.updateSleepIfNeededLocked(); onRootTaskOrderChanged(task); } @@ -416,12 +420,7 @@ final class TaskDisplayArea extends DisplayArea { } // Update the top resumed activity because the preferred top focusable task may be changed. - mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded(); - - final ActivityRecord r = child.getTopResumedActivity(); - if (r != null && r == mRootWindowContainer.getTopResumedActivity()) { - mAtmService.setResumedActivityUncheckLocked(r, "positionChildAt"); - } + mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("positionChildTaskAt"); if (mChildren.indexOf(child) != oldPosition) { onRootTaskOrderChanged(child); diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index f3f21103a7e81..ee1b68b57820f 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -460,7 +460,7 @@ class TaskFragment extends WindowContainer { final ActivityRecord prevR = mResumedActivity; mResumedActivity = r; - mTaskSupervisor.updateTopResumedActivityIfNeeded(); + mTaskSupervisor.updateTopResumedActivityIfNeeded(reason); if (r == null && prevR.mDisplayContent != null && prevR.mDisplayContent.getFocusedRootTask() == null) { // Only need to notify DWPC when no activity will resume. @@ -773,9 +773,6 @@ class TaskFragment extends WindowContainer { Slog.v(TAG, "set resumed activity to:" + record + " reason:" + reason); } setResumedActivity(record, reason + " - onActivityStateChanged"); - if (record == mRootWindowContainer.getTopResumedActivity()) { - mAtmService.setResumedActivityUncheckLocked(record, reason); - } mTaskSupervisor.mRecentTasks.add(record.getTask()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 75ecfd870eb26..d5e336b1cf2fe 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -228,7 +228,7 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { mAtm.getTaskChangeNotificationController(); spyOn(taskChangeNotifier); - mAtm.setResumedActivityUncheckLocked(fullScreenActivityA, "resumeA"); + mAtm.setLastResumedActivityUncheckLocked(fullScreenActivityA, "resumeA"); verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskA.mTaskId) /* taskId */, eq(true) /* focused */); reset(taskChangeNotifier); @@ -237,7 +237,7 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { .build(); final Task taskB = fullScreenActivityB.getTask(); - mAtm.setResumedActivityUncheckLocked(fullScreenActivityB, "resumeB"); + mAtm.setLastResumedActivityUncheckLocked(fullScreenActivityB, "resumeB"); verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskA.mTaskId) /* taskId */, eq(false) /* focused */); verify(taskChangeNotifier).notifyTaskFocusChanged(eq(taskB.mTaskId) /* taskId */, @@ -295,6 +295,7 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { activity1.moveFocusableActivityToTop("test"); assertEquals(activity1.getUid(), pendingTopUid[0]); verify(mAtm).updateOomAdj(); + verify(mAtm).setLastResumedActivityUncheckLocked(any(), eq("test")); } /**