summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rob Carr <racarr@google.com> 2020-03-27 16:57:03 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-03-27 16:57:03 +0000
commit428309a9182ab07b6c2011d27d13c23bf810f37c (patch)
tree3c2f8832bf1f27f9508944e5277bdc55d1b31586
parentbce4b444e30b859e1880e23a4f11d41c04ad37cd (diff)
parentde96c8acce87366b2cc4ecab1c415dc565f612d2 (diff)
Merge "TaskOrganizer: Wait for apps to draw." into rvc-dev
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java45
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java134
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java16
5 files changed, 154 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 2f814f598a05..29f7d523e9a0 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5201,7 +5201,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
finishLaunchTickingLocked();
if (task != null) {
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7a41ea57610d..91b4ec95f8fd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -258,7 +258,7 @@ class Task extends WindowContainer<WindowContainer> {
boolean autoRemoveRecents; // If true, we should automatically remove the task from
// recents when activity finishes
boolean askedCompatMode;// Have asked the user about compat mode for this task.
- boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
+ private boolean mHasBeenVisible; // Set if any activities in the task have been visible
String stringName; // caching of toString() result.
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
@@ -483,6 +483,10 @@ class Task extends WindowContainer<WindowContainer> {
*/
ITaskOrganizer mTaskOrganizer;
private int mLastTaskOrganizerWindowingMode = -1;
+ /**
+ * Prevent duplicate calls to onTaskAppeared.
+ */
+ boolean mTaskAppearedSent;
/**
* Last Picture-in-Picture params applicable to the task. Updated when the app
@@ -1517,7 +1521,7 @@ class Task extends WindowContainer<WindowContainer> {
// We will automatically remove the task either if it has explicitly asked for
// this, or it is empty and has never contained an activity that got shown to
// the user.
- return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
+ return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
}
/**
@@ -2030,7 +2034,7 @@ class Task extends WindowContainer<WindowContainer> {
}
private void saveLaunchingStateIfNeeded(DisplayContent display) {
- if (!hasBeenVisible) {
+ if (!getHasBeenVisible()) {
// Not ever visible to user.
return;
}
@@ -3558,7 +3562,7 @@ class Task extends WindowContainer<WindowContainer> {
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
- pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
+ pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible());
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
@@ -4087,14 +4091,42 @@ class Task extends WindowContainer<WindowContainer> {
super.reparentSurfaceControl(t, newParent);
}
+ void setHasBeenVisible(boolean hasBeenVisible) {
+ mHasBeenVisible = hasBeenVisible;
+ if (hasBeenVisible) {
+ sendTaskAppeared();
+ if (!isRootTask()) {
+ getRootTask().setHasBeenVisible(true);
+ }
+ }
+ }
+
+ boolean getHasBeenVisible() {
+ return mHasBeenVisible;
+ }
+
+ /** In the case that these three conditions are true, we want to send the Task to
+ * the organizer:
+ * 1. We have a SurfaceControl
+ * 2. An organizer has been set
+ * 3. We have finished drawing
+ * Any time any of these conditions are updated, the updating code should call
+ * sendTaskAppeared.
+ */
+ private boolean taskAppearedReady() {
+ return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible();
+ }
+
private void sendTaskAppeared() {
- if (mSurfaceControl != null && mTaskOrganizer != null) {
+ if (taskAppearedReady() && !mTaskAppearedSent) {
+ mTaskAppearedSent = true;
mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
}
}
private void sendTaskVanished() {
- if (mTaskOrganizer != null) {
+ if (mTaskOrganizer != null && mTaskAppearedSent) {
+ mTaskAppearedSent = false;
mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
}
}
@@ -4113,6 +4145,7 @@ class Task extends WindowContainer<WindowContainer> {
void taskOrganizerUnregistered() {
mTaskOrganizer = null;
+ mTaskAppearedSent = false;
mLastTaskOrganizerWindowingMode = -1;
onTaskOrganizerChanged();
if (mCreatedByOrganizer) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 8f3ff52b8018..ae467c0c811d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -120,7 +120,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
mTestTask.mUserId = TEST_USER_ID;
mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
- mTestTask.hasBeenVisible = true;
+ mTestTask.setHasBeenVisible(true);
mTaskWithDifferentComponent = new TaskBuilder(mSupervisor)
.setComponent(ALTERNATIVE_COMPONENT).build();
@@ -346,7 +346,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500);
- anotherTaskOfTheSameUser.hasBeenVisible = true;
+ anotherTaskOfTheSameUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfTheSameUser);
stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
@@ -358,7 +358,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
.build();
anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600);
- anotherTaskOfDifferentUser.hasBeenVisible = true;
+ anotherTaskOfDifferentUser.setHasBeenVisible(true);
mTarget.saveTask(anotherTaskOfDifferentUser);
mTarget.onCleanupUser(TEST_USER_ID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index ed635ce3f69e..4cc84a65fb29 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -96,10 +96,28 @@ public class TaskOrganizerTests extends WindowTestsBase {
return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
}
+ Task createTask(ActivityStack stack, boolean fakeDraw) {
+ final Task task = createTaskInStack(stack, 0);
+
+ if (fakeDraw) {
+ task.setHasBeenVisible(true);
+ }
+ return task;
+ }
+
+ Task createTask(ActivityStack stack) {
+ // Fake draw notifications for most of our tests.
+ return createTask(stack, true);
+ }
+
+ ActivityStack createStack() {
+ return createTaskStackOnDisplay(mDisplayContent);
+ }
+
@Test
public void testAppearVanish() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
task.setTaskOrganizer(organizer);
@@ -110,9 +128,42 @@ public class TaskOrganizerTests extends WindowTestsBase {
}
@Test
+ public void testAppearWaitsForVisibility() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+
+ verify(organizer, never()).onTaskAppeared(any());
+ task.setHasBeenVisible(true);
+ assertTrue(stack.getHasBeenVisible());
+
+ verify(organizer).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
+
+ @Test
+ public void testNoVanishedIfNoAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack, false /* hasBeenVisible */);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ // In this test we skip making the Task visible, and verify
+ // that even though a TaskOrganizer is set remove doesn't emit
+ // a vanish callback, because we never emitted appear.
+ task.setTaskOrganizer(organizer);
+ verify(organizer, never()).onTaskAppeared(any());
+ task.removeImmediately();
+ verify(organizer, never()).onTaskVanished(any());
+ }
+
+ @Test
public void testSwapOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -125,8 +176,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testSwapWindowingModes() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -139,8 +190,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testClearOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setTaskOrganizer(organizer);
@@ -154,8 +205,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testUnregisterOrganizer() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
final ITaskOrganizer organizer = registerMockOrganizer();
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -169,12 +220,12 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityStack stack3 = createTaskStackOnDisplay(mDisplayContent);
- final Task task3 = createTaskInStack(stack3, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ActivityStack stack2 = createStack();
+ final Task task2 = createTask(stack2);
+ final ActivityStack stack3 = createStack();
+ final Task task3 = createTask(stack3);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
// First organizer is registered, verify a task appears when changing windowing mode
@@ -202,9 +253,9 @@ public class TaskOrganizerTests extends WindowTestsBase {
public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final Task task2 = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final Task task2 = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
verify(organizer, times(1)).onTaskAppeared(any());
@@ -214,8 +265,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
- final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
stack.setWindowingMode(WINDOWING_MODE_PINNED);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
@@ -560,8 +611,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testTrivialBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -582,8 +633,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testOverlappingBLASTCallback() throws RemoteException {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
spyOn(task);
@@ -611,8 +662,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
makeWindowVisible(w);
@@ -635,8 +686,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithInvisibleWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
@@ -657,8 +708,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
@Test
public void testBLASTCallbackWithChildWindow() {
- final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ActivityStack stackController1 = createStack();
+ final Task task = createTask(stackController1);
final ITaskOrganizer organizer = registerMockOrganizer();
final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
@@ -708,6 +759,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
spyOn(record);
doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
+
+ record.getRootTask().setHasBeenVisible(true);
return record;
}
@@ -755,4 +808,23 @@ public class TaskOrganizerTests extends WindowTestsBase {
assertEquals(3, ratio.getNumerator());
assertEquals(4, ratio.getDenominator());
}
+
+ @Test
+ public void testPreventDuplicateAppear() throws RemoteException {
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ task.setTaskOrganizer(organizer);
+ // setHasBeenVisible was already called once by the set-up code.
+ task.setHasBeenVisible(true);
+ verify(organizer, times(1)).onTaskAppeared(any());
+
+ task.taskOrganizerUnregistered();
+ task.setTaskOrganizer(organizer);
+ verify(organizer, times(2)).onTaskAppeared(any());
+
+ task.removeImmediately();
+ verify(organizer).onTaskVanished(any());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 56c19a47b68a..1ad4079c5193 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -874,11 +874,11 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister).saveTask(task, task.getDisplayContent());
@@ -890,7 +890,7 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
final DisplayContent oldDisplay = task.getDisplayContent();
@@ -900,7 +900,7 @@ public class TaskRecordTests extends ActivityTestsBase {
persister.getLaunchParams(task, null, params);
assertEquals(WINDOWING_MODE_UNDEFINED, params.mWindowingMode);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.removeImmediately();
verify(persister).saveTask(task, oldDisplay);
@@ -915,10 +915,10 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());
@@ -930,11 +930,11 @@ public class TaskRecordTests extends ActivityTestsBase {
spyOn(persister);
final Task task = getTestTask();
- task.hasBeenVisible = false;
+ task.setHasBeenVisible(false);
task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM);
task.getStack().setWindowingMode(WINDOWING_MODE_PINNED);
- task.hasBeenVisible = true;
+ task.setHasBeenVisible(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
verify(persister, never()).saveTask(same(task), any());