summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2022-01-15 06:45:44 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-01-15 06:45:44 +0000
commit785ee1a55c84263c64c5aaa9959287a4efb0b34f (patch)
tree18a4f99b68adad3d0e55f51e87852dd15547d7e5
parentff6577fd10869384e58b95c3ffa2882e90db3626 (diff)
parent09e0a6e823a77a6fd0d1b5a1e0d16880f8b46e56 (diff)
downloadbase-785ee1a55c84263c64c5aaa9959287a4efb0b34f.tar.gz
Merge "Send Task Fragment Info Update When Task Invisible..." into sc-v2-dev
-rw-r--r--services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java38
2 files changed, 58 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index c7fdefc412cc..123ca889c73e 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -22,6 +22,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANI
import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -497,6 +498,23 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
return null;
}
+ private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task,
+ @NonNull PendingTaskFragmentEvent event) {
+ final TaskFragmentOrganizerState state =
+ mTaskFragmentOrganizerState.get(event.mTaskFragmentOrg.asBinder());
+ final TaskFragmentInfo lastInfo = state.mLastSentTaskFragmentInfos.get(event.mTaskFragment);
+ final TaskFragmentInfo info = event.mTaskFragment.getTaskFragmentInfo();
+ // Send an info changed callback if this event is for the last activities to finish in a
+ // Task so that the {@link TaskFragmentOrganizer} can delete this TaskFragment. Otherwise,
+ // the Task may be removed before it becomes visible again to send this event because it no
+ // longer has activities. As a result, the organizer will never get this info changed event
+ // and will not delete the TaskFragment because the organizer thinks the TaskFragment still
+ // has running activities.
+ return event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED
+ && task.topRunningActivity() == null && lastInfo != null
+ && lastInfo.getRunningActivityCount() > 0 && info.getRunningActivityCount() == 0;
+ }
+
void dispatchPendingEvents() {
if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
|| mPendingTaskFragmentEvents.isEmpty()) {
@@ -510,7 +528,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
if (task != null && (task.lastActiveTime <= event.mDeferTime
- || !isTaskVisible(task, visibleTasks, invisibleTasks))) {
+ || !(isTaskVisible(task, visibleTasks, invisibleTasks)
+ || shouldSendEventWhenTaskInvisible(task, event)))) {
// Defer sending events to the TaskFragment until the host task is active again.
event.mDeferTime = task.lastActiveTime;
continue;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index dcaf9d7ae434..f8c7207cefa7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -21,14 +21,17 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.testing.Assert.assertThrows;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.Intent;
@@ -471,6 +474,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
.setParentTask(task)
.setOrganizer(mOrganizer)
+ .setFragmentToken(mFragmentToken)
.build();
// Mock the task to invisible
@@ -485,4 +489,38 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
// Verifies that event was not sent
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
}
+
+ /**
+ * Tests that a task fragment info changed event is still sent if the task is invisible only
+ * when the info changed event is because of the last activity in a task finishing.
+ */
+ @Test
+ public void testLastPendingTaskFragmentInfoChangedEventOfInvisibleTaskSent() {
+ // Create a TaskFragment with an activity, all within a parent task
+ final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
+ .setOrganizer(mOrganizer)
+ .setFragmentToken(mFragmentToken)
+ .setCreateParentTask()
+ .createActivityCount(1)
+ .build();
+ final Task parentTask = taskFragment.getTask();
+ final ActivityRecord activity = taskFragment.getTopNonFinishingActivity();
+ assertTrue(parentTask.shouldBeVisible(null));
+
+ // Dispatch pending info changed event from creating the activity
+ mController.registerOrganizer(mIOrganizer);
+ taskFragment.mTaskFragmentAppearedSent = true;
+ mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
+ mController.dispatchPendingEvents();
+
+ // Finish the activity and verify that the task is invisible
+ activity.finishing = true;
+ assertFalse(parentTask.shouldBeVisible(null));
+
+ // Verify the info changed callback still occurred despite the task being invisible
+ reset(mOrganizer);
+ mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
+ mController.dispatchPendingEvents();
+ verify(mOrganizer).onTaskFragmentInfoChanged(any());
+ }
}