diff --git a/core/java/android/window/TaskFragmentParentInfo.java b/core/java/android/window/TaskFragmentParentInfo.java index 64b2638407dfc..841354a921921 100644 --- a/core/java/android/window/TaskFragmentParentInfo.java +++ b/core/java/android/window/TaskFragmentParentInfo.java @@ -33,19 +33,19 @@ public class TaskFragmentParentInfo implements Parcelable { private final int mDisplayId; - private final boolean mVisibleRequested; + private final boolean mVisible; public TaskFragmentParentInfo(@NonNull Configuration configuration, int displayId, - boolean visibleRequested) { + boolean visible) { mConfiguration.setTo(configuration); mDisplayId = displayId; - mVisibleRequested = visibleRequested; + mVisible = visible; } public TaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.mDisplayId; - mVisibleRequested = info.mVisibleRequested; + mVisible = info.mVisible; } /** The {@link Configuration} of the parent Task */ @@ -62,9 +62,9 @@ public class TaskFragmentParentInfo implements Parcelable { return mDisplayId; } - /** Whether the parent Task is requested to be visible or not */ - public boolean isVisibleRequested() { - return mVisibleRequested; + /** Whether the parent Task is visible or not */ + public boolean isVisible() { + return mVisible; } /** @@ -80,7 +80,7 @@ public class TaskFragmentParentInfo implements Parcelable { return false; } return getWindowingMode() == that.getWindowingMode() && mDisplayId == that.mDisplayId - && mVisibleRequested == that.mVisibleRequested; + && mVisible == that.mVisible; } @WindowConfiguration.WindowingMode @@ -93,7 +93,7 @@ public class TaskFragmentParentInfo implements Parcelable { return TaskFragmentParentInfo.class.getSimpleName() + ":{" + "config=" + mConfiguration + ", displayId=" + mDisplayId - + ", visibleRequested=" + mVisibleRequested + + ", visible=" + mVisible + "}"; } @@ -114,14 +114,14 @@ public class TaskFragmentParentInfo implements Parcelable { final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj; return mConfiguration.equals(that.mConfiguration) && mDisplayId == that.mDisplayId - && mVisibleRequested == that.mVisibleRequested; + && mVisible == that.mVisible; } @Override public int hashCode() { int result = mConfiguration.hashCode(); result = 31 * result + mDisplayId; - result = 31 * result + (mVisibleRequested ? 1 : 0); + result = 31 * result + (mVisible ? 1 : 0); return result; } @@ -129,13 +129,13 @@ public class TaskFragmentParentInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { mConfiguration.writeToParcel(dest, flags); dest.writeInt(mDisplayId); - dest.writeBoolean(mVisibleRequested); + dest.writeBoolean(mVisible); } private TaskFragmentParentInfo(Parcel in) { mConfiguration.readFromParcel(in); mDisplayId = in.readInt(); - mVisibleRequested = in.readBoolean(); + mVisible = in.readBoolean(); } public static final Creator CREATOR = diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java index 91573ffef568a..00943f2d53e1a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java @@ -140,7 +140,7 @@ class TaskContainer { void updateTaskFragmentParentInfo(@NonNull TaskFragmentParentInfo info) { mConfiguration.setTo(info.getConfiguration()); mDisplayId = info.getDisplayId(); - mIsVisible = info.isVisibleRequested(); + mIsVisible = info.isVisible(); } /** diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index b67d2ef7ddfcd..9f45f02277ce8 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3546,12 +3546,16 @@ class Task extends TaskFragment { * {@link android.window.TaskFragmentOrganizer} */ TaskFragmentParentInfo getTaskFragmentParentInfo() { - return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), isVisibleRequested()); + return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), + shouldBeVisible(null /* starting */)); } @Override void onActivityVisibleRequestedChanged() { - if (mVisibleRequested != isVisibleRequested()) { + final boolean prevVisibleRequested = mVisibleRequested; + // mVisibleRequested is updated in super method. + super.onActivityVisibleRequestedChanged(); + if (prevVisibleRequested != mVisibleRequested) { sendTaskFragmentParentInfoChangedIfNeeded(); } } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 058a066fffa4f..d178676734747 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2690,12 +2690,26 @@ class TaskFragment extends WindowContainer { return; } mVisibleRequested = isVisibleRequested; - final TaskFragment parentTf = getParent().asTaskFragment(); + final WindowContainer parent = getParent(); + if (parent == null) { + return; + } + final TaskFragment parentTf = parent.asTaskFragment(); if (parentTf != null) { parentTf.onActivityVisibleRequestedChanged(); } } + @Nullable + @Override + TaskFragment getTaskFragment(Predicate callback) { + final TaskFragment taskFragment = super.getTaskFragment(callback); + if (taskFragment != null) { + return taskFragment; + } + return callback.test(this) ? this : null; + } + String toFullString() { final StringBuilder sb = new StringBuilder(128); sb.append(this); diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 2d5c9897a82c6..867833a3271a2 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -920,6 +920,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr for (int i = 0, n = pendingEvents.size(); i < n; i++) { final PendingTaskFragmentEvent event = pendingEvents.get(i); final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null; + // TODO(b/251132298): move visibility check to the client side. if (task != null && (task.lastActiveTime <= event.mDeferTime || !(isTaskVisible(task, visibleTasks, invisibleTasks) || shouldSendEventWhenTaskInvisible(event)))) { 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 1404de2534762..0b23359627fb3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -195,6 +195,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.dispatchPendingEvents(); + assertTaskFragmentParentInfoChangedTransaction(mTask); assertTaskFragmentAppearedTransaction(); } @@ -365,6 +366,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.onActivityReparentedToTask(activity); mController.dispatchPendingEvents(); + assertTaskFragmentParentInfoChangedTransaction(task); assertActivityReparentedToTaskTransaction(task.mTaskId, activity.intent, activity.token); } @@ -1205,7 +1207,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { /** * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls - * {@link WindowOrganizerController#applyTransaction} to apply the transaction, + * {@link WindowOrganizerController#applyTransaction(WindowContainerTransaction)} to apply the + * transaction, */ private void createTaskFragmentFromOrganizer(WindowContainerTransaction wct, ActivityRecord ownerActivity, IBinder fragmentToken) { @@ -1239,8 +1242,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - // Appeared will come with parent info changed. - final TaskFragmentTransaction.Change change = changes.get(changes.size() - 1); + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_TASK_FRAGMENT_APPEARED, change.getType()); assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo()); assertEquals(mFragmentToken, change.getTaskFragmentToken()); @@ -1253,8 +1256,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - // InfoChanged may come with parent info changed. - final TaskFragmentTransaction.Change change = changes.get(changes.size() - 1); + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_TASK_FRAGMENT_INFO_CHANGED, change.getType()); assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo()); assertEquals(mFragmentToken, change.getTaskFragmentToken()); @@ -1266,7 +1269,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragmentTransaction transaction = mTransactionCaptor.getValue(); final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - final TaskFragmentTransaction.Change change = changes.get(0); + + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_TASK_FRAGMENT_VANISHED, change.getType()); assertEquals(mTaskFragmentInfo, change.getTaskFragmentInfo()); assertEquals(mFragmentToken, change.getTaskFragmentToken()); @@ -1278,7 +1283,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragmentTransaction transaction = mTransactionCaptor.getValue(); final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - final TaskFragmentTransaction.Change change = changes.get(0); + + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED, change.getType()); assertEquals(task.mTaskId, change.getTaskId()); assertEquals(task.getTaskFragmentParentInfo(), change.getTaskFragmentParentInfo()); @@ -1290,7 +1297,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragmentTransaction transaction = mTransactionCaptor.getValue(); final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - final TaskFragmentTransaction.Change change = changes.get(0); + + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_TASK_FRAGMENT_ERROR, change.getType()); assertEquals(mErrorToken, change.getErrorCallbackToken()); final Bundle errorBundle = change.getErrorBundle(); @@ -1306,7 +1315,9 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragmentTransaction transaction = mTransactionCaptor.getValue(); final List changes = transaction.getChanges(); assertFalse(changes.isEmpty()); - final TaskFragmentTransaction.Change change = changes.get(0); + + // Use remove to verify multiple transaction changes. + final TaskFragmentTransaction.Change change = changes.remove(0); assertEquals(TYPE_ACTIVITY_REPARENTED_TO_TASK, change.getType()); assertEquals(taskId, change.getTaskId()); assertEquals(intent, change.getActivityIntent()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 76cd19be19b08..68ac1d6f2e01b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -1454,6 +1454,21 @@ public class TaskTests extends WindowTestsBase { verify(tfBehind, never()).resumeTopActivity(any(), any(), anyBoolean()); } + @Test + public void testGetTaskFragment() { + final Task parentTask = createTask(mDisplayContent); + final TaskFragment tf0 = createTaskFragmentWithParentTask(parentTask); + final TaskFragment tf1 = createTaskFragmentWithParentTask(parentTask); + + assertNull("Could not find it because there's no organized TaskFragment", + parentTask.getTaskFragment(TaskFragment::isOrganizedTaskFragment)); + + doReturn(true).when(tf0).isOrganizedTaskFragment(); + + assertEquals("tf0 must be return because it's the organized TaskFragment.", + tf0, parentTask.getTaskFragment(TaskFragment::isOrganizedTaskFragment)); + } + private Task getTestTask() { final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); return task.getBottomMostTask(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 139e44099f425..b99fd1606f55f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -718,6 +718,10 @@ class WindowTestsBase extends SystemServiceTestsBase { activity.mVisibleRequested = true; } + static TaskFragment createTaskFragmentWithParentTask(@NonNull Task parentTask) { + return createTaskFragmentWithParentTask(parentTask, false /* createEmbeddedTask */); + } + /** * Creates a {@link TaskFragment} and attach it to the {@code parentTask}. *