diff options
5 files changed, 36 insertions, 27 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 3fa89279e9cc..757795e06cfb 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -762,6 +762,10 @@ public class Activity extends ContextThemeWrapper private boolean mDestroyed; private boolean mDoReportFullyDrawn = true; private boolean mRestoredFromBundle; + + /** {@code true} if the activity lifecycle is in a state which supports picture-in-picture. + * This only affects the client-side exception, the actual state check still happens in AMS. */ + private boolean mCanEnterPictureInPicture = false; /** true if the activity is going through a transient pause */ /*package*/ boolean mTemporaryPause = false; /** true if the activity is being destroyed in order to recreate it with a new configuration */ @@ -2091,6 +2095,10 @@ public class Activity extends ContextThemeWrapper if (params == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture params"); } + if (!mCanEnterPictureInPicture) { + throw new IllegalStateException("Activity must be resumed to enter" + + " picture-in-picture"); + } return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, params); } catch (RemoteException e) { return false; @@ -6957,25 +6965,29 @@ public class Activity extends ContextThemeWrapper return mParent != null ? mParent.getActivityToken() : mToken; } - final void performCreateCommon() { - mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( - com.android.internal.R.styleable.Window_windowNoDisplay, false); - mFragments.dispatchActivityCreated(); - mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); - } - final void performCreate(Bundle icicle) { - restoreHasCurrentPermissionRequest(icicle); - onCreate(icicle); - mActivityTransitionState.readState(icicle); - performCreateCommon(); + performCreate(icicle, null); } final void performCreate(Bundle icicle, PersistableBundle persistentState) { + mCanEnterPictureInPicture = true; restoreHasCurrentPermissionRequest(icicle); - onCreate(icicle, persistentState); + if (persistentState != null) { + onCreate(icicle, persistentState); + } else { + onCreate(icicle); + } mActivityTransitionState.readState(icicle); - performCreateCommon(); + + mVisibleFromClient = !mWindow.getWindowStyle().getBoolean( + com.android.internal.R.styleable.Window_windowNoDisplay, false); + mFragments.dispatchActivityCreated(); + mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions()); + } + + final void performNewIntent(Intent intent) { + mCanEnterPictureInPicture = true; + onNewIntent(intent); } final void performStart() { @@ -7126,6 +7138,9 @@ public class Activity extends ContextThemeWrapper mDoReportFullyDrawn = false; mFragments.doLoaderStop(mChangingConfigurations /*retain*/); + // Disallow entering picture-in-picture after the activity has been stopped + mCanEnterPictureInPicture = false; + if (!mStopped) { if (mWindow != null) { mWindow.closeAllPanels(); diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 467fc952ffee..e260967f92d0 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -48,6 +48,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.Window; + import com.android.internal.content.ReferrerIntent; import java.io.File; @@ -1305,7 +1306,7 @@ public class Instrumentation { * @param intent The new intent being received. */ public void callActivityOnNewIntent(Activity activity, Intent intent) { - activity.onNewIntent(intent); + activity.performNewIntent(intent); } /** diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 32d34450e2c1..5c5a6b7ac205 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8045,7 +8045,7 @@ public class ActivityManagerService extends IActivityManager.Stub // 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 /* beforeStopping */)) { + 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 e5985c58e5af..874bd1e7625b 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1186,10 +1186,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo * @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. + * @return whether this activity is currently allowed to enter PIP. */ - boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) { + boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) { if (!supportsPictureInPicture()) { return false; } @@ -1237,13 +1236,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return isNotLockedOrOnKeyguard && !hasPinnedStack; } default: - if (noThrow) { - return false; - } else { - throw new IllegalStateException(caller - + ": Current activity is not visible (state=" + state.name() + ") " - + "r=" + this); - } + return false; } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index c2656a188dc8..eb3177a6e1c9 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2076,7 +2076,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state); try { final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( - "makeInvisible", true /* noThrow */, true /* beforeStopping */); + "makeInvisible", true /* beforeStopping */); // Defer telling the client it is hidden if it can enter Pip and isn't current stopped // or stopping. This gives it a chance to enter Pip in onPause(). final boolean deferHidingClient = canEnterPictureInPicture @@ -2390,7 +2390,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // represent the last resumed activity. However, the last focus stack does if it isn't null. final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity; lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( - "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */); + "resumeTopActivity", userLeaving /* beforeStopping */); } // 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 only if the |