summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2024-08-16 14:55:01 +0800
committer Riddle Hsu <riddlehsu@google.com> 2024-08-16 15:17:40 +0800
commitcd7d9512269630c3d14eab6b50b30ae8d66aa11f (patch)
tree2cc9fa1a344add22f0fdeaea3f0cd7757f5b876d
parent62253d6f1096b35ea88a50ef052451cba60b1ae0 (diff)
Check idle activity from all visible task fragment
The very old legacy logic only handles fullscreen windowing mode case. If multiple tasks are launching at the same time, the power mode may be finished too early by the first activity reports idle. That results in a long startup delay. Also add a case to handle cold launching activity. Before the process is attached, the activity record state is INITIALIZING. But if it can be resumed after its process is attached, its idle state should also be considered. E.g. launching a split-screen pair with hot launch of one side and cold launch on another side. When the first one reported idle, allResumedActivitiesIdle should still return false. Fix: 356522395 Flag: EXEMPT bugfix Test: atest RootWindowContainerTests#testAllResumedActivitiesIdle Change-Id: Ida677ec93916f37cf2aebd33113f9730d8c211ab
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java4
3 files changed, 38 insertions, 16 deletions
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index bded98c6c07f..8523b713b6c0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3426,26 +3426,30 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
boolean allResumedActivitiesIdle() {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- // TODO(b/117135575): Check resumed activities on all visible root tasks.
final DisplayContent display = getChildAt(displayNdx);
if (display.isSleeping()) {
// No resumed activities while display is sleeping.
continue;
}
- // If the focused root task is not null or not empty, there should have some activities
- // resuming or resumed. Make sure these activities are idle.
- final Task rootTask = display.getFocusedRootTask();
- if (rootTask == null || !rootTask.hasActivity()) {
- continue;
- }
- final ActivityRecord resumedActivity = rootTask.getTopResumedActivity();
- if (resumedActivity == null || !resumedActivity.idle) {
- ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: rootTask=%d %s "
- + "not idle", rootTask.getRootTaskId(), resumedActivity);
+ final boolean foundNotIdle = display.forAllLeafTaskFragments(tf -> {
+ if (!tf.isVisibleRequested()) {
+ return false;
+ }
+ // Note that only activities that will be resumed can report idle.
+ final ActivityRecord r = tf.topRunningActivity();
+ if (r != null && !r.idle && (r.isState(RESUMED)
+ // Its process is not attached yet and it may resume later.
+ || (r.app == null && r.isFocusable()))) {
+ ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", r);
+ return true;
+ }
+ return false;
+ });
+ if (foundNotIdle) {
return false;
}
- if (mTransitionController.isTransientLaunch(resumedActivity)) {
+ if (mTransitionController.hasTransientLaunch(display)) {
// Not idle if the transient transition animation is running.
return false;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index d29505f02fe8..538cffe81f3b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -204,6 +204,28 @@ public class RootWindowContainerTests extends WindowTestsBase {
}
@Test
+ public void testAllResumedActivitiesIdle() {
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final WindowProcessController proc2 = activity2.app;
+ activity1.setState(RESUMED, "test");
+ activity2.detachFromProcess();
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+ activity1.idle = true;
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isFalse();
+
+ activity2.setProcess(proc2);
+ activity2.setState(RESUMED, "test");
+ activity2.idle = true;
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+
+ activity1.idle = false;
+ activity1.setVisibleRequested(false);
+ assertThat(mWm.mRoot.allResumedActivitiesIdle()).isTrue();
+ }
+
+ @Test
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 49e349caa379..56fca31afa37 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1550,10 +1550,6 @@ public class TransitionTests extends WindowTestsBase {
// An active transient launch overrides idle state to avoid clearing power mode before the
// transition is finished.
- spyOn(mRootWindowContainer.mTransitionController);
- doAnswer(invocation -> controller.isTransientLaunch(invocation.getArgument(0))).when(
- mRootWindowContainer.mTransitionController).isTransientLaunch(any());
- activity2.getTask().setResumedActivity(activity2, "test");
activity2.idle = true;
assertFalse(mRootWindowContainer.allResumedActivitiesIdle());