Updating picture-in-picture API.
- Consolidating to enterPictureInPictureMode(), the new method will
attempt to put the activity into picture-in-picture mode if the
activity is visible or pausing in a state that would allow us to
pip it. Also consolidate the setting of the PiP aspect ratio and
actions into setPictureInPictureArgs().
- Fixing issue with onPause not completing when moving the
paused activity between stacks while dispatching onPause
Bug: 33692987
Test: android.server.cts.ActivityManagerPinnedStackTests
Change-Id: I3af2365f31a9b95de4a92eae46b77108947b2a49
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2a324eb..db7d505 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -151,7 +151,6 @@
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManager.TaskThumbnailInfo;
import android.app.ActivityManagerInternal;
-import android.app.ActivityManagerInternal.PictureInPictureArguments;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
import android.app.ActivityThread;
@@ -182,6 +181,7 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.PictureInPictureArgs;
import android.app.ProfilerInfo;
import android.app.RemoteAction;
import android.app.WaitResult;
@@ -229,7 +229,6 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
import android.graphics.Point;
import android.graphics.Rect;
import android.location.LocationManager;
@@ -7556,45 +7555,31 @@
}
@Override
- public void enterPictureInPictureMode(IBinder token) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, -1f /* aspectRatio */,
- false /* checkAspectRatio */);
- }
-
- @Override
- public void enterPictureInPictureModeWithAspectRatio(IBinder token, float aspectRatio) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio, true /* checkAspectRatio */);
- }
-
- @Override
- public void enterPictureInPictureModeOnMoveToBackground(IBinder token,
- boolean enterPictureInPictureOnMoveToBg) {
+ public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureArgs args) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
- "enterPictureInPictureModeOnMoveToBackground", token, -1f /* aspectRatio */,
- false /* checkAspectRatio */, false /* checkActivityVisibility */);
+ final ActivityRecord r = ensureValidPictureInPictureActivityArgsLocked(
+ "enterPictureInPictureMode", token, args);
- r.supportsPipOnMoveToBackground = enterPictureInPictureOnMoveToBg;
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
+ // Activity supports picture-in-picture, now check that we can enter PiP at this
+ // point, if it is
+ if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode")) {
+ return false;
+ }
- private void enterPictureInPictureMode(IBinder token, int displayId, float aspectRatio,
- boolean checkAspectRatio) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(this) {
- final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
- "enterPictureInPictureMode", token, aspectRatio, checkAspectRatio,
- true /* checkActivityVisibility */);
final Runnable enterPipRunnable = () -> {
- r.pictureInPictureArgs.aspectRatio = aspectRatio;
- enterPictureInPictureModeLocked(r, displayId, r.pictureInPictureArgs,
- true /* moveHomeStackToFront */, "enterPictureInPictureMode");
+ // Only update the saved args from the args that are set
+ r.pictureInPictureArgs.copyOnlySet(args);
+ final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
+ final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
+ final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
+ ? mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+ aspectRatio)
+ : mWindowManager.getPictureInPictureDefaultBounds(DEFAULT_DISPLAY);
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
+ bounds, true /* moveHomeStackToFront */);
+ mWindowManager.setPictureInPictureActions(actions);
};
if (isKeyguardLocked()) {
@@ -7625,35 +7610,7 @@
// Enter picture in picture immediately otherwise
enterPipRunnable.run();
}
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- void enterPictureInPictureModeLocked(ActivityRecord r, int displayId,
- PictureInPictureArguments pipArgs, boolean moveHomeStackToFront, String reason) {
- final Rect bounds = isValidPictureInPictureAspectRatio(pipArgs.aspectRatio)
- ? mWindowManager.getPictureInPictureBounds(displayId, pipArgs.aspectRatio)
- : mWindowManager.getPictureInPictureDefaultBounds(displayId);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, reason, bounds, moveHomeStackToFront);
- mWindowManager.setPictureInPictureActions(pipArgs.userActions);
- }
-
- @Override
- public void setPictureInPictureAspectRatio(IBinder token, float aspectRatio) {
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(this) {
- final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
- "setPictureInPictureAspectRatio", token, aspectRatio,
- true /* checkAspectRatio */, false /* checkActivityVisibility */);
-
- r.pictureInPictureArgs.aspectRatio = aspectRatio;
- if (r.getStack().getStackId() == PINNED_STACK_ID) {
- // If the activity is already in picture-in-picture, update the pinned stack now
- mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
- }
+ return true;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -7661,26 +7618,21 @@
}
@Override
- public void setPictureInPictureActions(IBinder token, ParceledListSlice actionsList) {
+ public void setPictureInPictureArgs(IBinder token, final PictureInPictureArgs args) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
- "setPictureInPictureActions", token, -1 /* aspectRatio */,
- false /* checkAspectRatio */, false /* checkActivityVisibility */);
+ final ActivityRecord r = ensureValidPictureInPictureActivityArgsLocked(
+ "setPictureInPictureArgs", token, args);
- final List<RemoteAction> actions = actionsList.getList();
- if (actions.size() > ActivityManager.getMaxNumPictureInPictureActions()) {
- throw new IllegalArgumentException("setPictureInPictureActions: Invalid number"
- + " of picture-in-picture actions. Only a maximum of "
- + ActivityManager.getMaxNumPictureInPictureActions()
- + " actions allowed");
- }
-
- r.pictureInPictureArgs.userActions = actions;
+ // Only update the saved args from the args that are set
+ r.pictureInPictureArgs.copyOnlySet(args);
if (r.getStack().getStackId() == PINNED_STACK_ID) {
// If the activity is already in picture-in-picture, update the pinned stack now
- mWindowManager.setPictureInPictureActions(actions);
+ mWindowManager.setPictureInPictureAspectRatio(
+ r.pictureInPictureArgs.getAspectRatio());
+ mWindowManager.setPictureInPictureActions(
+ r.pictureInPictureArgs.getActions());
}
}
} finally {
@@ -7696,14 +7648,10 @@
* Checks the state of the system and the activity associated with the given {@param token} to
* verify that picture-in-picture is supported for that activity.
*
- * @param checkAspectRatio whether or not to check {@param aspectRatio} is within a valid range
- * @param checkActivityVisibility whether or not to enforce that the activity is currently
- * visible
- *
* @return the activity record for the given {@param token} if all the checks pass.
*/
- private ActivityRecord ensureValidPictureInPictureActivityLocked(String caller, IBinder token,
- float aspectRatio, boolean checkAspectRatio, boolean checkActivityVisibility) {
+ private ActivityRecord ensureValidPictureInPictureActivityArgsLocked(String caller,
+ IBinder token, PictureInPictureArgs args) {
if (!mSupportsPictureInPicture) {
throw new IllegalStateException(caller
+ ": Device doesn't support picture-in-picture mode.");
@@ -7715,10 +7663,9 @@
+ ": Can't find activity for token=" + token);
}
- if (!r.canEnterPictureInPicture(checkActivityVisibility)) {
- throw new IllegalArgumentException(caller
- + ": Current activity does not support picture-in-picture or is not "
- + "visible r=" + r);
+ if (!r.supportsPictureInPicture()) {
+ throw new IllegalStateException(caller
+ + ": Current activity does not support picture-in-picture.");
}
if (r.getStack().isHomeStack()) {
@@ -7726,12 +7673,20 @@
+ ": Activities on the home stack not supported");
}
- if (checkAspectRatio && !isValidPictureInPictureAspectRatio(aspectRatio)) {
+ if (args.hasSetAspectRatio()
+ && !isValidPictureInPictureAspectRatio(args.getAspectRatio())) {
throw new IllegalArgumentException(String.format(caller
+ ": Aspect ratio is too extreme (must be between %f and %f).",
mMinPipAspectRatio, mMaxPipAspectRatio));
}
+ if (args.hasSetActions()
+ && args.getActions().size() > ActivityManager.getMaxNumPictureInPictureActions()) {
+ throw new IllegalArgumentException(String.format(caller + ": Invalid number of"
+ + "picture-in-picture actions. Only a maximum of %d actions allowed",
+ ActivityManager.getMaxNumPictureInPictureActions()));
+ }
+
return r;
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a2fb9f9..6134d75 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -63,9 +63,9 @@
import android.annotation.NonNull;
import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManagerInternal.PictureInPictureArguments;
import android.app.ActivityOptions;
import android.app.PendingIntent;
+import android.app.PictureInPictureArgs;
import android.app.ResultInfo;
import android.content.ComponentName;
import android.content.Intent;
@@ -229,13 +229,10 @@
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
boolean forceNewConfig; // force re-create with new config next time
- boolean supportsPipOnMoveToBackground; // Supports automatically entering picture-in-picture
- // when this activity is hidden. This flag is requested by the activity.
- private boolean enterPipOnMoveToBackground; // Flag to enter picture in picture when this
- // activity is made invisible. This flag is set specifically when another task is being
- // launched or moved to the front which may cause this activity to try and enter PiP
- // when it is next made invisible.
- PictureInPictureArguments pictureInPictureArgs = new PictureInPictureArguments(); // The PiP
+ boolean supportsPictureInPictureWhilePausing; // This flag is set by the system to indicate
+ // that the activity can enter picture in picture while pausing (ie. only when another
+ // task is brought to front or started)
+ PictureInPictureArgs pictureInPictureArgs = new PictureInPictureArgs(); // The PiP
// arguments used when deferring the entering of picture-in-picture.
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last launch of this activity
@@ -453,12 +450,8 @@
if (info != null) {
pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
}
- if (supportsPipOnMoveToBackground) {
- pw.println(prefix + "supportsPipOnMoveToBackground=1");
- pw.println(prefix + "enterPipOnMoveToBackground=" +
- (enterPipOnMoveToBackground ? 1 : 0));
- pictureInPictureArgs.dump(pw, prefix);
- }
+ pw.println(prefix + "supportsPictureInPictureWhilePausing: "
+ + supportsPictureInPictureWhilePausing);
}
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
@@ -819,23 +812,6 @@
}
/**
- * If this activity has requested that it auto-enter picture-in-picture and we can actually do
- * this, then mark it to enter picture in picture at that point.
- */
- void setEnterPipOnMoveToBackground(boolean enterPipOnInvisible) {
- if (supportsPipOnMoveToBackground) {
- enterPipOnMoveToBackground = enterPipOnInvisible;
- }
- }
-
- /**
- * @return whether to enter PiP when this activity is made invisible.
- */
- public boolean shouldEnterPictureInPictureOnInvisible() {
- return enterPipOnMoveToBackground;
- }
-
- /**
* @return Stack value from current task, null if there is no task.
*/
ActivityStack getStack() {
@@ -918,24 +894,34 @@
}
/**
- * @return whether this activity is currently allowed to enter PIP, if
- * {@param checkActivityVisibility} is set, then the current activity visibility is taken into
- * account.
+ * @return whether this activity is currently allowed to enter PIP, throwing an exception if
+ * the activity is not currently visible.
*/
- boolean canEnterPictureInPicture(boolean checkActivityVisibility) {
- if (!checkActivityVisibility) {
- return supportsPictureInPicture();
+ boolean checkEnterPictureInPictureState(String caller) {
+ boolean isKeyguardLocked = service.isKeyguardLocked();
+ boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
+ switch (state) {
+ case RESUMED:
+ // When visible, allow entering PiP if not on the lockscreen. If there is another
+ // PiP activity, the logic to handle that comes later in enterPictureInPictureMode()
+ return !isKeyguardLocked;
+ case PAUSING:
+ case PAUSED:
+ // When pausing, only allow enter PiP if not on the lockscreen and there is not
+ // already an existing PiP activity
+ return !isKeyguardLocked && !hasPinnedStack && supportsPictureInPictureWhilePausing;
+ case STOPPING:
+ // When stopping in a valid state, then only allow enter PiP as in the pause state.
+ // Otherwise, fall through to throw an exception if the caller is trying to enter
+ // PiP in an invalid stopping state.
+ if (supportsPictureInPictureWhilePausing) {
+ return !isKeyguardLocked && !hasPinnedStack;
+ }
+ default:
+ throw new IllegalStateException(caller
+ + ": Current activity is not visible (state=" + state.name() + ") "
+ + "r=" + this);
}
-
- if (supportsPictureInPicture()) {
- switch (state) {
- case RESUMED:
- case PAUSING:
- case PAUSED:
- return true;
- }
- }
- return false;
}
boolean canGoInDockedStack() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4df0cb1..cd11d21 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1698,9 +1698,7 @@
+ stackInvisible + " behindFullscreenActivity="
+ behindFullscreenActivity + " mLaunchTaskBehind="
+ r.mLaunchTaskBehind);
- if (!enterPictureInPictureOnActivityInvisible(r)) {
- makeInvisible(r, visibleBehind);
- }
+ makeInvisible(r, visibleBehind);
}
}
if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -1859,35 +1857,6 @@
return false;
}
- /**
- * Attempts to enter picture-in-picture if the activity that is being made invisible supports
- * it. If not, then
- *
- * @return whether or not picture-in-picture mode was entered.
- */
- private boolean enterPictureInPictureOnActivityInvisible(ActivityRecord r) {
- final boolean hasPinnedStack =
- mStackSupervisor.getStack(PINNED_STACK_ID) != null;
- final boolean isKeyguardLocked = mService.isKeyguardLocked();
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, " enterPictureInPictureOnInvisible="
- + r.shouldEnterPictureInPictureOnInvisible()
- + " hasPinnedStack=" + hasPinnedStack
- + " isKeyguardLocked=" + isKeyguardLocked);
- if (!hasPinnedStack && !isKeyguardLocked && r.visible &&
- r.shouldEnterPictureInPictureOnInvisible()) {
- r.setEnterPipOnMoveToBackground(false);
-
- // Enter picture in picture, but don't move the home stack to the front
- // since it will affect the focused stack's visibility and occlude
- // starting activities
- mService.enterPictureInPictureModeLocked(r, r.getDisplayId(),
- r.pictureInPictureArgs, false /* moveHomeStackToFront */,
- "ensureActivitiesVisibleLocked");
- return true;
- }
- return false;
- }
-
private void makeInvisible(ActivityRecord r, ActivityRecord visibleBehind) {
if (!r.visible) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
@@ -1906,6 +1875,10 @@
"Scheduling invisibility: " + r);
r.app.thread.scheduleWindowVisibility(r.appToken, false);
}
+
+ // Reset the flag indicating that an app can enter picture-in-picture once the
+ // activity is hidden
+ r.supportsPictureInPictureWhilePausing = false;
break;
case INITIALIZING:
@@ -2187,15 +2160,16 @@
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
- // We need to start pausing the current activity so the top one can be resumed...
- final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
- boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, dontWaitForPause);
+ // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
+ // to be paused, while at the same time resuming the new resume activity
+ final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
+ boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
- pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
+ pausing |= startPausingLocked(userLeaving, false, next, false);
}
- if (pausing) {
+ if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
@@ -2696,10 +2670,10 @@
if (r.mLaunchTaskBehind) {
transit = TRANSIT_TASK_OPEN_BEHIND;
} else {
- // If a new task is being launched, then mark the existing top activity to
- // enter picture-in-picture if it supports auto-entering PiP
+ // If a new task is being launched, then mark the existing top activity as
+ // supporting picture-in-picture while pausing
if (focusedTopActivity != null) {
- focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ focusedTopActivity.supportsPictureInPictureWhilePausing = true;
}
transit = TRANSIT_TASK_OPEN;
}
@@ -4245,10 +4219,10 @@
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
- // If a new task is moved to the front, then mark the existing top activity to enter
- // picture-in-picture if it supports auto-entering PiP
+ // If a new task is moved to the front, then mark the existing top activity as supporting
+ // picture-in-picture while paused
if (focusedTopActivity != null) {
- focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ focusedTopActivity.supportsPictureInPictureWhilePausing = true;
}
mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4966,8 +4940,8 @@
}
}
- void moveToFrontAndResumeStateIfNeeded(
- ActivityRecord r, boolean moveToFront, boolean setResume, String reason) {
+ void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
+ boolean setPause, String reason) {
if (!moveToFront) {
return;
}
@@ -4978,6 +4952,10 @@
if (setResume) {
mResumedActivity = r;
}
+ // If the activity was previously pausing, then ensure we transfer that as well
+ if (setPause) {
+ mPausingActivity = r;
+ }
// Move the stack in which we are placing the activity to the front. The call will also
// make sure the activity focus is set.
moveToFront(reason);
@@ -4998,6 +4976,7 @@
final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack)
&& (mStackSupervisor.topRunningActivityLocked() == r);
final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
+ final boolean wasPaused = prevStack.mPausingActivity == r;
final TaskRecord task = createTaskRecord(
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
@@ -5005,10 +4984,14 @@
r.setTask(task, null);
task.addActivityToTop(r);
mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
- moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack");
+ moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused,
+ "moveActivityToStack");
if (wasResumed) {
prevStack.mResumedActivity = null;
}
+ if (wasPaused) {
+ prevStack.mPausingActivity = null;
+ }
}
public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4fe8939..1224abd 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2617,6 +2617,7 @@
final ActivityStack prevStack = task.getStack();
final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
final boolean wasResumed = prevStack.mResumedActivity == r;
+ final boolean wasPaused = prevStack.mPausingActivity == r;
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
// Whenever we are moving the top activity from the front stack we want to make sure to move
// the stack to the front.
@@ -2641,10 +2642,19 @@
task.mTemporarilyUnresizable = false;
task.reparent(stack.mStackId, toTop ? MAX_VALUE : 0, reason);
+ // Reset the resumed activity on the previous stack
+ if (wasResumed) {
+ prevStack.mResumedActivity = null;
+ }
+ // Reset the paused activity on the previous stack
+ if (wasPaused) {
+ prevStack.mPausingActivity = null;
+ }
+
// If the task had focus before (or we're requested to move focus),
// move focus to the new stack by moving the stack to the front.
- stack.moveToFrontAndResumeStateIfNeeded(
- r, forceFocus || wasFocused || wasFront, wasResumed, reason);
+ stack.moveToFrontAndResumeStateIfNeeded(r, forceFocus || wasFocused || wasFront, wasResumed,
+ wasPaused, reason);
return stack;
}
@@ -2795,8 +2805,12 @@
if (task.mActivities.size() == 1) {
// There is only one activity in the task. So, we can just move the task over to
- // the stack without re-parenting the activity in a different task.
- if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+ // the stack without re-parenting the activity in a different task. We don't
+ // move the home stack forward if we are currently entering picture-in-picture
+ // while pausing because that changes the focused stack and may prevent the new
+ // starting activity from resuming.
+ if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE
+ && !r.supportsPictureInPictureWhilePausing) {
// Move the home stack forward if the task we just moved to the pinned stack
// was launched from home so home should be visible behind it.
moveHomeStackToFront(reason);
@@ -2808,6 +2822,10 @@
// reveal/leave the other activities in their original task
stack.moveActivityToStack(r);
}
+
+ // Reset the state that indicates it can enter PiP while pausing after we've moved it
+ // to the pinned stack
+ r.supportsPictureInPictureWhilePausing = false;
} finally {
mWindowManager.continueSurfaceLayout();
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index bfb4269..08f9b45 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -333,7 +333,9 @@
*/
void setActions(List<RemoteAction> actions) {
mActions.clear();
- mActions.addAll(actions);
+ if (actions != null) {
+ mActions.addAll(actions);
+ }
notifyActionsChanged(mActions);
}