Adding ability for an app to request auto-enter picture-in-picture.
- If an activity requests that it can auto-enter PIP, then we will trigger
it to enter PIP when the task is effectively being occluded. This does
not affect the activity when the screen is locking, or if it starts new
activities within its own task, or if it finishes itself, or if there is
already a PIP activity.
- Changed setPictureInPictureAspectRatio to also specify the aspect ratio
to use when auto-entering PIP. If the activity is not PIP'ed and has
not requested auto-enter, then the call continues to fail.
Test: android.server.cts.ActivityManagerPinnedStackTests
Test: #testAutoEnterPictureInPicture
Test: #testAutoEnterPictureInPictureLaunchActivity
Test: #testAutoEnterPictureInPictureFinish
Test: #testAutoEnterPictureInPictureAspectRatio
Test: #testAutoEnterPictureInPictureOverPip
Change-Id: I6477b6d1f160cf0219d935123bbb505f57ee7a56
diff --git a/api/current.txt b/api/current.txt
index 3a70525..e6cf180 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3479,6 +3479,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index adef1b7..59a3512 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3596,6 +3596,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index f5ef794..3875da3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3481,6 +3481,7 @@
method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public void enterPictureInPictureMode();
method public void enterPictureInPictureMode(float);
+ method public void enterPictureInPictureModeOnMoveToBackground(boolean);
method public android.view.View findViewById(int);
method public void finish();
method public void finishActivity(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index eb73e36..6dd488f 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2030,6 +2030,28 @@
}
/**
+ * Requests to the system that the activity can be automatically put into picture-in-picture
+ * mode when the user leaves the activity causing it normally to be hidden. This is a *not*
+ * a guarantee that the activity will actually be put in picture-in-picture mode, and depends
+ * on a number of factors, including whether there is already something in picture-in-picture.
+ *
+ * If {@param enterPictureInPictureOnMoveToBg} is true, then you may also call
+ * {@link #setPictureInPictureAspectRatio(float)} to specify the aspect ratio to automatically
+ * enter picture-in-picture with.
+ *
+ * @param enterPictureInPictureOnMoveToBg whether or not this activity can automatically enter
+ * picture-in-picture
+ */
+ public void enterPictureInPictureModeOnMoveToBackground(
+ boolean enterPictureInPictureOnMoveToBg) {
+ try {
+ ActivityManagerNative.getDefault().enterPictureInPictureModeOnMoveToBackground(mToken,
+ enterPictureInPictureOnMoveToBg);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Called by the system when the device configuration changes while your
* activity is running. Note that this will <em>only</em> be called if
* you have selected configurations you would like to handle with the
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 640ca6c..62b3977 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -468,6 +468,10 @@
boolean isInPictureInPictureMode(in IBinder token);
void killPackageDependents(in String packageName, int userId);
void enterPictureInPictureMode(in IBinder token);
+ void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
+ void enterPictureInPictureModeOnMoveToBackground(in IBinder token,
+ boolean enterPictureInPictureOnMoveToBg);
+ void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
void activityRelaunched(in IBinder token);
IBinder getUriPermissionOwnerForActivity(in IBinder activityToken);
/**
@@ -568,8 +572,6 @@
boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void unregisterTaskStackListener(ITaskStackListener listener);
void moveStackToDisplay(int stackId, int displayId);
- void enterPictureInPictureModeWithAspectRatio(in IBinder token, float aspectRatio);
- void setPictureInPictureAspectRatio(in IBinder token, float aspectRatio);
boolean requestAutoFillData(in IResultReceiver receiver, in Bundle receiverExtras,
in IBinder activityToken);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback);
@@ -578,4 +580,4 @@
// side. If so, make sure they are using the correct transaction ids.
// If a transaction which will also be used on the native side is being inserted, add it
// alongside with other transactions of this kind at the top of this file.
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 982c57c..625df23 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -269,10 +269,8 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -7494,46 +7492,51 @@
@Override
public void enterPictureInPictureMode(IBinder token) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, null /* aspectRatio */);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, -1f /* aspectRatio */,
+ false /* checkAspectRatio */);
}
@Override
public void enterPictureInPictureModeWithAspectRatio(IBinder token, float aspectRatio) {
- enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio);
+ enterPictureInPictureMode(token, DEFAULT_DISPLAY, aspectRatio, true /* checkAspectRatio */);
}
- public void enterPictureInPictureMode(IBinder token, int displayId, Float aspectRatio) {
+ private void enterPictureInPictureMode(IBinder token, int displayId, float aspectRatio,
+ boolean checkAspectRatio) {
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- if (!mSupportsPictureInPicture) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Device doesn't support picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "enterPictureInPictureMode", token, aspectRatio, checkAspectRatio,
+ true /* checkActivityVisibility */);
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null) {
- throw new IllegalStateException("enterPictureInPictureMode: "
- + "Can't find activity for token=" + token);
- }
+ enterPictureInPictureModeLocked(r, displayId, aspectRatio,
+ true /* moveHomeStackToFront */, "enterPictureInPictureMode");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
- if (!r.canEnterPictureInPicture()) {
- throw new IllegalArgumentException("enterPictureInPictureMode: "
- + "Current activity does not support picture-in-picture or is not "
- + "visible r=" + r);
- }
+ void enterPictureInPictureModeLocked(ActivityRecord r, int displayId, float aspectRatio,
+ boolean moveHomeStackToFront, String reason) {
+ final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
+ ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
+ : mWindowManager.getPictureInPictureDefaultBounds(displayId);
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, reason, bounds, moveHomeStackToFront);
+ }
- if (aspectRatio != null && !isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format("enterPictureInPictureMode: "
- + "Aspect ratio is too extreme (must be between %f and %f).",
- mMinPipAspectRatio, mMaxPipAspectRatio));
- }
+ @Override
+ public void enterPictureInPictureModeOnMoveToBackground(IBinder token,
+ boolean enterPictureInPictureOnMoveToBg) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized(this) {
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "requestAutoEnterPictureInPicture", token, -1f /* aspectRatio */,
+ false /* checkAspectRatio */, false /* checkActivityVisibility */);
- final Rect bounds = isValidPictureInPictureAspectRatio(aspectRatio)
- ? mWindowManager.getPictureInPictureBounds(displayId, aspectRatio)
- : mWindowManager.getPictureInPictureDefaultBounds(displayId);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
- bounds);
+ r.supportsPipOnMoveToBackground = enterPictureInPictureOnMoveToBg;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -7545,33 +7548,68 @@
final long origId = Binder.clearCallingIdentity();
try {
synchronized(this) {
- final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- if (r == null || r.getStack().mStackId != PINNED_STACK_ID) {
- throw new IllegalStateException("setPictureInPictureAspectRatio: "
- + "Requesting activity must be in picture-in-picture mode.");
- }
+ final ActivityRecord r = ensureValidPictureInPictureActivityLocked(
+ "setPictureInPictureAspectRatio", token, aspectRatio,
+ true /* checkAspectRatio */, false /* checkActivityVisibility */);
- if (!isValidPictureInPictureAspectRatio(aspectRatio)) {
- throw new IllegalArgumentException(String.format(
- "setPictureInPictureAspectRatio: Aspect ratio is too extreme (must be "
- + "between %f and %f).", mMinPipAspectRatio,
- mMaxPipAspectRatio));
+ if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ // If the activity is already in picture-in-picture, update the pinned stack now
+ mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
}
-
- mWindowManager.setPictureInPictureAspectRatio(aspectRatio);
+ r.pictureInPictureAspectRatio = aspectRatio;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
- private boolean isValidPictureInPictureAspectRatio(Float aspectRatio) {
- if (aspectRatio == null) {
- return false;
- }
+ private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
return mMinPipAspectRatio <= aspectRatio && aspectRatio <= mMaxPipAspectRatio;
}
+ /**
+ * 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) {
+ if (!mSupportsPictureInPicture) {
+ throw new IllegalStateException(caller
+ + ": Device doesn't support picture-in-picture mode.");
+ }
+
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalStateException(caller
+ + ": 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.getStack().isHomeStack()) {
+ throw new IllegalStateException(caller
+ + ": Activities on the home stack not supported");
+ }
+
+ if (checkAspectRatio && !isValidPictureInPictureAspectRatio(aspectRatio)) {
+ throw new IllegalArgumentException(String.format(caller
+ + ": Aspect ratio is too extreme (must be between %f and %f).",
+ mMinPipAspectRatio, mMaxPipAspectRatio));
+ }
+
+ return r;
+ }
+
// =========================================================
// PROCESS INFO
// =========================================================
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 6d72228..13c422b 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -21,7 +21,6 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
@@ -84,7 +83,6 @@
import android.util.TimeUtils;
import android.view.AppTransitionAnimationSpec;
import android.view.IApplicationToken;
-import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import com.android.internal.app.ResolverActivity;
@@ -218,6 +216,14 @@
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.
+ float pictureInPictureAspectRatio; // The aspect ratio to use when auto-entering
+ // picture-in-picture
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
@@ -434,6 +440,11 @@
if (info != null) {
pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
}
+ if (supportsPipOnMoveToBackground) {
+ pw.println(prefix + "supportsPipOnMoveToBackground=1 "
+ + "enterPipOnMoveToBackground="
+ + (enterPipOnMoveToBackground ? 1 : 0));
+ }
}
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
@@ -842,6 +853,23 @@
}
/**
+ * 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() {
@@ -930,9 +958,15 @@
}
/**
- * @return whether this activity is currently allowed to enter PIP.
+ * @return whether this activity is currently allowed to enter PIP, if
+ * {@param checkActivityVisibility} is set, then the current activity visibility is taken into
+ * account.
*/
- boolean canEnterPictureInPicture() {
+ boolean canEnterPictureInPicture(boolean checkActivityVisibility) {
+ if (!checkActivityVisibility) {
+ return supportsPictureInPicture();
+ }
+
if (supportsPictureInPicture() && visible) {
switch (state) {
case RESUMED:
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d94d3cd..d160a46 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -22,7 +22,6 @@
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
@@ -723,7 +722,6 @@
mStacks.remove(this);
int addIndex = mStacks.size();
-
if (addIndex > 0) {
final ActivityStack topStack = mStacks.get(addIndex - 1);
if (StackId.isAlwaysOnTop(topStack.mStackId) && topStack != this) {
@@ -1718,7 +1716,9 @@
+ stackInvisible + " behindFullscreenActivity="
+ behindFullscreenActivity + " mLaunchTaskBehind="
+ r.mLaunchTaskBehind);
- makeInvisible(r, visibleBehind);
+ if (!enterPictureInPictureOnActivityInvisible(r)) {
+ makeInvisible(r, visibleBehind);
+ }
}
}
if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -1876,6 +1876,32 @@
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;
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, " enterPictureInPictureOnInvisible="
+ + r.shouldEnterPictureInPictureOnInvisible()
+ + " hasPinnedStack=" + hasPinnedStack);
+ if (!hasPinnedStack && 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.pictureInPictureAspectRatio, 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);
@@ -2613,8 +2639,8 @@
mWindowManager.moveTaskToTop(task.taskId);
}
- final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
- ActivityOptions options) {
+ final void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ boolean newTask, boolean keepCurTransition, ActivityOptions options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
@@ -2693,11 +2719,20 @@
mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else {
- mWindowManager.prepareAppTransition(newTask
- ? r.mLaunchTaskBehind
- ? TRANSIT_TASK_OPEN_BEHIND
- : TRANSIT_TASK_OPEN
- : TRANSIT_ACTIVITY_OPEN, keepCurTransition);
+ int transit = TRANSIT_ACTIVITY_OPEN;
+ if (newTask) {
+ 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 (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
+ transit = TRANSIT_TASK_OPEN;
+ }
+ }
+ mWindowManager.prepareAppTransition(transit, keepCurTransition);
mNoAnimActivities.remove(r);
}
addConfigOverride(r, task);
@@ -4193,6 +4228,8 @@
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
+ final ActivityRecord focusedTopActivity = mStackSupervisor.getFocusedStack() != null
+ ? mStackSupervisor.getFocusedStack().topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
@@ -4238,6 +4275,11 @@
} 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 (focusedTopActivity != null) {
+ focusedTopActivity.setEnterPipOnMoveToBackground(true);
+ }
mStackSupervisor.resumeFocusedStackTopActivityLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index dde948f..fd32a5e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2638,11 +2638,13 @@
return false;
}
- moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds);
+ moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds,
+ true /* moveHomeStackToFront */);
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds) {
+ void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
+ boolean moveHomeStackToFront) {
mWindowManager.deferSurfaceLayout();
try {
final TaskRecord task = r.task;
@@ -2666,7 +2668,7 @@
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 (task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+ if (moveHomeStackToFront && task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
// 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);
@@ -2674,6 +2676,8 @@
moveTaskToStackLocked(
task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
} else {
+ // There are multiple activities in the task and moving the top activity should
+ // reveal/leave the other activities in their original task
stack.moveActivityToStack(r);
}
} finally {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 64bf3ad..d0960a0 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1068,6 +1068,7 @@
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
final ActivityStack topStack = mSupervisor.mFocusedStack;
+ final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
@@ -1139,7 +1140,8 @@
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
- mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
+ mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
if (!mTargetStack.isFocusable()
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 01a50b7..0ad4e0a 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -135,7 +135,7 @@
mService = service;
mDisplayContent = displayContent;
mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
- mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
+ mMotionHelper = new PipMotionHelper(UiThread.getHandler());
mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
reloadResources();
}