diff options
| author | 2020-04-06 19:23:23 -0700 | |
|---|---|---|
| committer | 2020-04-09 15:56:00 -0700 | |
| commit | 8b5d23ab108e80a4c6af5253733c3c6cf504e13f (patch) | |
| tree | 5161bfde6312d13e52d6f54e5f8a9abf4c994673 | |
| parent | 1b5d055f2ea3823b62d694ded7ec19f18d2b1777 (diff) | |
Fix a couple issues with previous CL (keeping tasks hidden)
- Attempting to set the visiblity when the task org is set can happen too
early and cause the app to not draw and preventing taskAppeared().
Instead, move this to setHasBeenVisible() to be in line with other
cases in the system where we defer setting visibility until the apps
are good to go. However, if we do this, we also need the first draw
(including the starting window) to trigger setHasBeenVisible() to
ensure the task org can hide it in time (the task org will also want
to receive the task as soon as possible). As a result of moving it out
of when the task org is set on the task the PIP transition then also
has to defer setting the visibility of the activity until the first
draw.
- Also fix a case where we are dispatching task info change before
taskAppeared(). There's a brief period where the task has an organizer
set, but the task org state has not added that task yet or sent
taskAppeared() because it has not yet drawn. But in that state, config
changes still happen causing a task info changed call to the task org.
Bug: 152809695
Bug: 152134460
Test: Open a bubble, ensure that we don't see the task in fullscreen
first. Enter pip, ensure that we don't see flash of the task
before SysUI can fade it in.
Test: atest PipAnimationControllerTest
Test: atest TaskOrganizerTests
Test: atest SplitScreenTests
Change-Id: I7d2ca2a2e538f07c73fff79686e040c159c1dce3
5 files changed, 49 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c47d2151a958..4e2b745ff409 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5212,6 +5212,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateReportedVisibilityLocked(); } + void onStartingWindowDrawn() { + if (task != null) { + task.setHasBeenVisible(true); + } + } + /** Called when the windows associated app window container are drawn. */ void onWindowsDrawn(boolean drawn, long timestampNs) { mDrawn = drawn; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 80b8b5854966..42cd66e4e964 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -38,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; @@ -2118,16 +2119,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> try { final Task task = r.getTask(); - final ActivityStack pinnedStack = taskDisplayArea.getRootPinnedTask(); + // This will change the pinned stack's windowing mode to its original mode, ensuring // we only have one stack that is in pinned mode. if (pinnedStack != null) { pinnedStack.dismissPip(); } - final boolean singleActivity = task.getChildCount() == 1; + // Set a transition to ensure that we don't immediately try and update the visibility + // of the activity entering PIP + r.getDisplayContent().prepareAppTransition(TRANSIT_NONE, false); + final boolean singleActivity = task.getChildCount() == 1; final ActivityStack stack; if (singleActivity) { stack = r.getRootTask(); @@ -2150,11 +2154,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mService.continueWindowLayout(); } - // TODO: revisit the following statement after the animation is moved from WM to SysUI. - // Update the visibility of all activities after the they have been reparented to the new - // stack. This MUST run after the animation above is scheduled to ensure that the windows - // drawn signal is scheduled after the bounds animation start call on the bounds animator - // thread. ensureActivitiesVisible(null, 0, false /* preserveWindows */); resumeFocusedStacksTopActivities(); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 58326c38f259..50a0ea837df3 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4100,8 +4100,18 @@ class Task extends WindowContainer<WindowContainer> { } void setHasBeenVisible(boolean hasBeenVisible) { + final boolean prevHasBeenVisible = mHasBeenVisible; mHasBeenVisible = hasBeenVisible; if (hasBeenVisible) { + // If the task is not yet visible when it is added to the task organizer, then we should + // hide it to allow the task organizer to show it when it is properly reparented. We + // skip this for tasks created by the organizer because they can synchronously update + // the leash before new children are added to the task. + if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) { + getPendingTransaction().hide(getSurfaceControl()); + commitPendingTransaction(); + } + sendTaskAppeared(); if (!isRootTask()) { getRootTask().setHasBeenVisible(true); @@ -4146,15 +4156,6 @@ class Task extends WindowContainer<WindowContainer> { sendTaskVanished(); mTaskOrganizer = organizer; - // If the task is not yet visible when it is added to the task organizer, then we should - // hide it to allow the task organizer to show it when it is properly reparented. We skip - // this for tasks created by the organizer because they can synchronously update the leash - // before new children are added to the task. - if (!mCreatedByOrganizer && organizer != null - && (!getHasBeenVisible() || !hasVisibleChildren())) { - getPendingTransaction().hide(getSurfaceControl()); - commitPendingTransaction(); - } sendTaskAppeared(); onTaskOrganizerChanged(); diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 243af14fece2..9873031e0138 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -131,6 +131,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) { + if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) { + // Skip if the task has not yet received taskAppeared(), except for tasks created + // by the organizer that don't receive that signal + return; + } mDeferTaskOrgCallbacksConsumer.accept(() -> { if (!task.isOrganized()) { // This is safe to ignore if the task is no longer organized @@ -145,6 +150,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } void onBackPressedOnTaskRoot(Task task) { + if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) { + // Skip if the task has not yet received taskAppeared(), except for tasks created + // by the organizer that don't receive that signal + return; + } mDeferTaskOrgCallbacksConsumer.accept(() -> { if (!task.isOrganized()) { // This is safe to ignore if the task is no longer organized @@ -193,23 +203,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mOrganizedTasks.add(t); } if (t.taskAppearedReady()) { - try { - t.mTaskAppearedSent = true; - mOrganizer.onTaskAppeared(t); - } catch (Exception e) { - Slog.e(TAG, "Exception sending taskAppeared callback" + e); - } + t.mTaskAppearedSent = true; + mOrganizer.onTaskAppeared(t); } } void removeTask(Task t) { if (t.mTaskAppearedSent) { - try { - t.mTaskAppearedSent = false; - mOrganizer.onTaskVanished(t); - } catch (Exception e) { - Slog.e(TAG, "Exception sending taskVanished callback" + e); - } + t.mTaskAppearedSent = false; + mOrganizer.onTaskVanished(t); } mOrganizedTasks.remove(t); } @@ -460,9 +462,15 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { mTmpTaskInfo = null; if (task.isOrganized()) { + // Because we defer sending taskAppeared() until the app has drawn, we may receive a + // configuration change before the state actually has the task registered. As such we + // should ignore these change events to the organizer until taskAppeared(). If the task + // was created by the organizer, then we always send the info change. final TaskOrganizerState state = mTaskOrganizerStates.get( task.mTaskOrganizer.asBinder()); - state.mOrganizer.onTaskInfoChanged(task, newInfo); + if (state != null) { + state.mOrganizer.onTaskInfoChanged(task, newInfo); + } } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 5a76bac67d64..627fdc342a9a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4274,9 +4274,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP logPerformShow("performShow on "); final int drawState = mWinAnimator.mDrawState; - if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) - && mAttrs.type != TYPE_APPLICATION_STARTING && mActivityRecord != null) { - mActivityRecord.onFirstWindowDrawn(this, mWinAnimator); + if ((drawState == HAS_DRAWN || drawState == READY_TO_SHOW) && mActivityRecord != null) { + if (mAttrs.type != TYPE_APPLICATION_STARTING) { + mActivityRecord.onFirstWindowDrawn(this, mWinAnimator); + } else { + mActivityRecord.onStartingWindowDrawn(); + } } if (mWinAnimator.mDrawState != READY_TO_SHOW || !isReadyForDisplay()) { |