Fix SHOW_WHEN_LOCKED splitscreen bug
In ag/29956640, the lock/wake behavior for splitscreen was changed to fix a camera bug. At the time, I think the SHOW_WHEN_LOCKED behavior was working as well. However, the logic is no longer working in the same way today, and the SHOW_WHEN_LOCKED issue has regressed. It seems to be because we are receiving TRANSIT_TO_FRONT changes now, instead of TRANSIT_TO_BACK as previously expected.
To fix this, I changed the logic to account for both TRANSIT_TO_BACK and TRANSIT_TO_FRONT changes -- both apps must receive a TO_BACK or TO_FRONT in the same transition, or else we will break split. This fixes the regression.
Fixes: 387227528
Test: Repro steps do not repro anymore
Flag: EXEMPT bugfix
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ea5fb8087eece78df3f6caf79982c32971784b60)
Merged-In: Ib833c78032545032797593578ac61478b695d558
Change-Id: Ib833c78032545032797593578ac61478b695d558
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 5eadd06..221beaf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2951,9 +2951,11 @@
final int transitType = info.getType();
TransitionInfo.Change pipChange = null;
int closingSplitTaskId = -1;
- // This array tracks if we are sending stages TO_BACK in this transition.
- // TODO (b/349828130): Update for n apps
- boolean[] stagesSentToBack = new boolean[2];
+ // This array tracks where we are sending stages (TO_BACK/TO_FRONT) in this transition.
+ // TODO (b/349828130): Update for n apps (needs to handle different indices than 0/1).
+ // Also make sure having multiple changes per stage (2+ tasks in one stage) is being
+ // handled properly.
+ int[] stageChanges = new int[2];
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
@@ -3016,18 +3018,25 @@
+ " with " + taskId + " before startAnimation().");
}
}
- if (isClosingType(change.getMode()) &&
- getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED) {
- // Record which stages are getting sent to back
- if (change.getMode() == TRANSIT_TO_BACK) {
- stagesSentToBack[getStageOfTask(taskId)] = true;
- }
-
+ final int stageOfTaskId = getStageOfTask(taskId);
+ if (stageOfTaskId == STAGE_TYPE_UNDEFINED) {
+ continue;
+ }
+ if (isClosingType(change.getMode())) {
// (For PiP transitions) If either one of the 2 stages is closing we're assuming
// we'll break split
closingSplitTaskId = taskId;
}
+ if (transitType == WindowManager.TRANSIT_WAKE) {
+ // Record which stages are receiving which changes
+ if ((change.getMode() == TRANSIT_TO_BACK
+ || change.getMode() == TRANSIT_TO_FRONT)
+ && (stageOfTaskId == STAGE_TYPE_MAIN
+ || stageOfTaskId == STAGE_TYPE_SIDE)) {
+ stageChanges[stageOfTaskId] = change.getMode();
+ }
+ }
}
if (pipChange != null) {
@@ -3052,19 +3061,11 @@
return true;
}
- // If keyguard is active, check to see if we have our TO_BACK transitions in order.
- // This array should either be all false (no split stages sent to back) or all true
- // (all stages sent to back). In any other case (which can happen with SHOW_ABOVE_LOCKED
- // apps) we should break split.
- if (mKeyguardActive) {
- boolean isFirstStageSentToBack = stagesSentToBack[0];
- for (boolean b : stagesSentToBack) {
- // Compare each boolean to the first one. If any are different, break split.
- if (b != isFirstStageSentToBack) {
- dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
- break;
- }
- }
+ // If keyguard is active, check to see if we have all our stages showing. If one stage
+ // was moved but not the other (which can happen with SHOW_ABOVE_LOCKED apps), we should
+ // break split.
+ if (mKeyguardActive && stageChanges[STAGE_TYPE_MAIN] != stageChanges[STAGE_TYPE_SIDE]) {
+ dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
}
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();