From 6012e9b7489bc3ef38c54841e3a7dc77076d6f2b Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Wed, 14 Sep 2022 01:00:04 +0800 Subject: [PATCH] Send TaskFragmentParentInfo for visibility changes This CL propagates visibility from Activity to Task, and dispatch #onTaskFragmentParentInfoChanged is there's a task visiblity update. This CL also send the callback when the associated Display of Task changes. Test: atest TaskFragmentOrganizerControllerTest fixes: 243609832 Change-Id: I3b0198cfd11a3ec4917f92d0a1e540cf16827d08 --- .../window/TaskFragmentParentInfo.java | 28 ++++++++++++++++ .../com/android/server/wm/ActivityRecord.java | 18 +++++++++-- .../core/java/com/android/server/wm/Task.java | 20 ++++++++++++ .../com/android/server/wm/TaskFragment.java | 25 ++++++++++++++- .../wm/TaskFragmentOrganizerController.java | 32 ++++++++++++++++++- .../android/server/wm/WindowContainer.java | 11 +++++++ 6 files changed, 129 insertions(+), 5 deletions(-) diff --git a/core/java/android/window/TaskFragmentParentInfo.java b/core/java/android/window/TaskFragmentParentInfo.java index c89a54e90f58e..64b2638407dfc 100644 --- a/core/java/android/window/TaskFragmentParentInfo.java +++ b/core/java/android/window/TaskFragmentParentInfo.java @@ -97,6 +97,34 @@ public class TaskFragmentParentInfo implements Parcelable { + "}"; } + /** + * Indicates that whether this {@link TaskFragmentParentInfo} equals to {@code obj}. + * Note that {@link #equalsForTaskFragmentOrganizer(TaskFragmentParentInfo)} should be used + * for most cases because not all {@link Configuration} properties are interested for + * {@link TaskFragmentOrganizer}. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof TaskFragmentParentInfo)) { + return false; + } + final TaskFragmentParentInfo that = (TaskFragmentParentInfo) obj; + return mConfiguration.equals(that.mConfiguration) + && mDisplayId == that.mDisplayId + && mVisibleRequested == that.mVisibleRequested; + } + + @Override + public int hashCode() { + int result = mConfiguration.hashCode(); + result = 31 * result + mDisplayId; + result = 31 * result + (mVisibleRequested ? 1 : 0); + return result; + } + @Override public void writeToParcel(@NonNull Parcel dest, int flags) { mConfiguration.writeToParcel(dest, flags); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 4c0a0171024a9..ac75369ee38ee 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1586,11 +1586,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (oldParent != null) { oldParent.cleanUpActivityReferences(this); + // Update isVisibleRequested value of parent TaskFragment and send the callback to the + // client side if needed. + oldParent.onActivityVisibleRequestedChanged(); } - if (newParent != null && isState(RESUMED)) { - newParent.setResumedActivity(this, "onParentChanged"); - mImeInsetsFrozenUntilStartInput = false; + if (newParent != null) { + // Update isVisibleRequested value of parent TaskFragment and send the callback to the + // client side if needed. + newParent.onActivityVisibleRequestedChanged(); + if (isState(RESUMED)) { + newParent.setResumedActivity(this, "onParentChanged"); + mImeInsetsFrozenUntilStartInput = false; + } } if (rootTask != null && rootTask.topRunningActivity() == this) { @@ -5090,6 +5098,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } mVisibleRequested = visible; + final TaskFragment taskFragment = getTaskFragment(); + if (taskFragment != null) { + taskFragment.onActivityVisibleRequestedChanged(); + } setInsetsFrozen(!visible); if (app != null) { mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 85083a131373c..aede32c453f23 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2685,6 +2685,7 @@ class Task extends TaskFragment { if (isRootTask()) { updateSurfaceBounds(); } + sendTaskFragmentParentInfoChangedIfNeeded(); } boolean isResizeable() { @@ -3527,6 +3528,25 @@ class Task extends TaskFragment { return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), isVisibleRequested()); } + @Override + void onActivityVisibleRequestedChanged() { + if (mVisibleRequested != isVisibleRequested()) { + sendTaskFragmentParentInfoChangedIfNeeded(); + } + } + + void sendTaskFragmentParentInfoChangedIfNeeded() { + if (!isLeafTask()) { + // Only send parent info changed event for leaf task. + return; + } + final TaskFragment childOrganizedTf = + getTaskFragment(TaskFragment::isOrganizedTaskFragment); + if (childOrganizedTf != null) { + childOrganizedTf.sendTaskFragmentParentInfoChanged(); + } + } + boolean isTaskId(int taskId) { return mTaskId == taskId; } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 036a292c31743..0c39ff6194d1d 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -297,6 +297,9 @@ class TaskFragment extends WindowContainer { final Point mLastSurfaceSize = new Point(); + /** The latest updated value when there's a child {@link #onActivityVisibleRequestedChanged} */ + boolean mVisibleRequested; + private final Rect mTmpBounds = new Rect(); private final Rect mTmpFullBounds = new Rect(); /** For calculating screenWidthDp and screenWidthDp, i.e. the area without the system bars. */ @@ -2379,6 +2382,14 @@ class TaskFragment extends WindowContainer { } } + void sendTaskFragmentParentInfoChanged() { + final Task parentTask = getParent().asTask(); + if (mTaskFragmentOrganizer != null && parentTask != null) { + mTaskFragmentOrganizerController + .onTaskFragmentParentInfoChanged(mTaskFragmentOrganizer, parentTask); + } + } + private void sendTaskFragmentAppeared() { if (mTaskFragmentOrganizer != null) { mTaskFragmentOrganizerController.onTaskFragmentAppeared(mTaskFragmentOrganizer, this); @@ -2414,7 +2425,7 @@ class TaskFragment extends WindowContainer { mRemoteToken.toWindowContainerToken(), getConfiguration(), getNonFinishingActivityCount(), - isVisible(), + isVisibleRequested(), childActivities, positionInParent, mClearedTaskForReuse, @@ -2671,6 +2682,18 @@ class TaskFragment extends WindowContainer { return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds(); } + void onActivityVisibleRequestedChanged() { + final boolean isVisibleRequested = isVisibleRequested(); + if (mVisibleRequested == isVisibleRequested) { + return; + } + mVisibleRequested = isVisibleRequested; + final TaskFragment parentTf = getParent().asTaskFragment(); + if (parentTf != null) { + parentTf.onActivityVisibleRequestedChanged(); + } + } + 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 c4d3e3730abea..2d5c9897a82c6 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -649,6 +649,34 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr .build()); } + void onTaskFragmentParentInfoChanged(@NonNull ITaskFragmentOrganizer organizer, + @NonNull Task task) { + validateAndGetState(organizer); + final PendingTaskFragmentEvent pendingEvent = getLastPendingParentInfoChangedEvent( + organizer, task); + if (pendingEvent == null) { + addPendingEvent(new PendingTaskFragmentEvent.Builder( + PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer) + .setTask(task) + .build()); + } + } + + @Nullable + private PendingTaskFragmentEvent getLastPendingParentInfoChangedEvent( + @NonNull ITaskFragmentOrganizer organizer, @NonNull Task task) { + final List events = mPendingTaskFragmentEvents + .get(organizer.asBinder()); + for (int i = events.size() - 1; i >= 0; i--) { + final PendingTaskFragmentEvent event = events.get(i); + if (task == event.mTask + && event.mEventType == PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED) { + return event; + } + } + return null; + } + private void addPendingEvent(@NonNull PendingTaskFragmentEvent event) { mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).add(event); } @@ -851,7 +879,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr } private boolean shouldSendEventWhenTaskInvisible(@NonNull PendingTaskFragmentEvent event) { - if (event.mEventType == PendingTaskFragmentEvent.EVENT_ERROR) { + if (event.mEventType == PendingTaskFragmentEvent.EVENT_ERROR + // Always send parent info changed to update task visibility + || event.mEventType == PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED) { return true; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 979a6e5e121ad..383fcb9303d72 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2192,6 +2192,17 @@ class WindowContainer extends ConfigurationContainer< callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound); } + @Nullable + TaskFragment getTaskFragment(Predicate callback) { + for (int i = mChildren.size() - 1; i >= 0; --i) { + final TaskFragment tf = mChildren.get(i).getTaskFragment(callback); + if (tf != null) { + return tf; + } + } + return null; + } + WindowState getWindow(Predicate callback) { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState w = mChildren.get(i).getWindow(callback);