Merge "Fix auto-pip visibility issues." into oc-dev
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 17459ea..cde3ec5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7803,7 +7803,7 @@
// Activity supports picture-in-picture, now check that we can enter PiP at this
// point, if it is
if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
- false /* noThrow */)) {
+ false /* noThrow */, false /* beforeStopping */)) {
return false;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index cfbd2b5..274dac6 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1163,10 +1163,13 @@
}
/**
+ * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
+ * the activity has requested to enter PiP when it would otherwise be stopped.
+ *
* @return whether this activity is currently allowed to enter PIP, throwing an exception if
* the activity is not currently visible and {@param noThrow} is not set.
*/
- boolean checkEnterPictureInPictureState(String caller, boolean noThrow) {
+ boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
// Check app-ops and see if PiP is supported for this package
if (!checkEnterPictureInPictureAppOpsState()) {
return false;
@@ -1177,17 +1180,24 @@
return false;
}
- boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
boolean isKeyguardLocked = service.isKeyguardLocked();
+ boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
// Don't return early if !isNotLocked, since we want to throw an exception if the activity
// is in an incorrect state
boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
+
+ // We don't allow auto-PiP when something else is already pipped.
+ if (beforeStopping && hasPinnedStack) {
+ return false;
+ }
+
switch (state) {
case RESUMED:
// When visible, allow entering PiP if the app is not locked. If it is over the
// keyguard, then we will prompt to unlock in the caller before entering PiP.
- return !isCurrentAppLocked;
+ return !isCurrentAppLocked &&
+ (supportsPictureInPictureWhilePausing || !beforeStopping);
case PAUSING:
case PAUSED:
// When pausing, then only allow enter PiP as in the resume state, and in addition,
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 0e033d2..bb71499 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2001,10 +2001,10 @@
// keeping the screen frozen.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
try {
- r.setVisible(false);
switch (r.state) {
case STOPPING:
case STOPPED:
+ r.setVisible(false);
if (r.app != null && r.app.thread != null) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Scheduling invisibility: " + r);
@@ -2023,6 +2023,7 @@
// This case created for transitioning activities from
// translucent to opaque {@link Activity#convertToOpaque}.
if (visibleBehind == r) {
+ r.setVisible(false);
releaseBackgroundResources(r);
} else {
// If this activity is in a state where it can currently enter
@@ -2030,7 +2031,18 @@
// the activity tries to enterPictureInPictureMode() later. Otherwise,
// we will try and stop the activity next time idle is processed.
final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
- "makeInvisible", true /* noThrow */);
+ "makeInvisible", true /* noThrow */, true /* beforeStopping */);
+
+ if (canEnterPictureInPicture) {
+ // We set r.visible=false so that Stop will later
+ // call setVisible for us. In this case
+ // we don't want to call setVisible(false) to avoid
+ // notifying the client of this intermittent invisible
+ // state.
+ r.visible = false;
+ } else {
+ r.setVisible(false);
+ }
addToStopping(r, true /* scheduleIdle */,
canEnterPictureInPicture /* idleDelayed */);
}