Ensure onStop before onPictureInPictureModeChanged

We have a CTS test case
PinnedStackTests#testStopBeforeMultiWindowCallbacksOnDismiss that
ensures onStop is always sent before onPictureInPictureModeChanged. The
test itself does not simulate what user typically does and it's broken
with the shell transition.

Apps like YouTube may rely on such order so they can choose if they
should, for instance, stop the playback when the PiP is removed.

Fixing this by forcefully send onStop before setWindowingMode (which in
turn results a configuration change).

Video: http://recall/-/aaaaaabFQoRHlzixHdtY/eEEfu9mca0dzLyzC8jBcxb
Bug: 290413333
Test: manually, see also the video
Test: atest PinnedStackTests
Merged-In: I0f94d4c26f7b3ccc1df6be97a0238f995438dffd
Change-Id: I0f94d4c26f7b3ccc1df6be97a0238f995438dffd
(cherry picked from commit 59c5d8101e)
This commit is contained in:
Hongwei Wang
2023-07-11 16:20:01 -07:00
parent 1b84c35905
commit 3dfe4c8e09
2 changed files with 12 additions and 2 deletions

View File

@@ -2186,7 +2186,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
* Processes the activities to be stopped or destroyed. This should be called when the resumed
* activities are idle or drawn.
*/
private void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
void processStoppingAndFinishingActivities(ActivityRecord launchedActivity,
boolean processPausingActivities, String reason) {
// Stop any activities that are scheduled to do so but have been waiting for the transition
// animation to finish.
@@ -2194,7 +2194,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
ArrayList<ActivityRecord> readyToStopActivities = null;
for (int i = 0; i < mStoppingActivities.size(); i++) {
final ActivityRecord s = mStoppingActivities.get(i);
final boolean animating = s.isInTransition();
// Activity in a force hidden task should not be counted as animating, i.e., we want to
// send onStop before any configuration change when removing pip transition is ongoing.
final boolean animating = s.isInTransition()
&& s.getTask() != null && !s.getTask().isForceHidden();
displaySwapping |= s.isDisplaySleepingAndSwapping();
ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b "
+ "finishing=%s", s, s.nowVisible, animating, s.finishing);

View File

@@ -559,6 +559,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
if (forceHiddenForPip) {
wc.asTask().setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
// When removing pip, make sure that onStop is sent to the app ahead of
// onPictureInPictureModeChanged.
// See also PinnedStackTests#testStopBeforeMultiWindowCallbacksOnDismiss
wc.asTask().ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
wc.asTask().mTaskSupervisor.processStoppingAndFinishingActivities(
null /* launchedActivity */, false /* processPausingActivities */,
"force-stop-on-removing-pip");
}
int containerEffect = applyWindowContainerChange(wc, entry.getValue(),