From 8802eac3d8831e7af867f19d0bb1df3daa603140 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 17 Apr 2017 14:21:44 -0700 Subject: [PATCH] Account for content insets in source rect hint for transition into PiP - As a part of transitioning into PiP, we remove the content insets, and as a result, we also need to adjust the source hint rect for the change in insets as well. Bug: 37418994 Test: Enter PiP from YT, ensure no jump at the end Change-Id: I74219b05c91d3c8b8466dd8fff4d6dd692f08725 --- core/java/android/app/Activity.java | 17 ++++++ .../android/app/PictureInPictureArgs.java | 52 ++++++++++++++++++- core/java/android/view/ViewRootImpl.java | 10 ++++ .../server/am/ActivityManagerService.java | 9 +++- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b36a1600bae54..958be4f105e1b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2068,6 +2068,7 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args); } catch (RemoteException e) { return false; @@ -2085,11 +2086,27 @@ public class Activity extends ContextThemeWrapper if (args == null) { throw new IllegalArgumentException("Expected non-null picture-in-picture args"); } + updatePictureInPictureArgsForContentInsets(args); ActivityManagerNative.getDefault().setPictureInPictureArgs(mToken, args); } catch (RemoteException e) { } } + /** + * Updates the provided {@param args} with the last known content insets for this activity, to + * be used with the source hint rect for the transition into PiP. + */ + private void updatePictureInPictureArgsForContentInsets(PictureInPictureArgs args) { + if (args != null && args.hasSourceBoundsHint() && getWindow() != null && + getWindow().peekDecorView() != null && + getWindow().peekDecorView().getViewRootImpl() != null) { + args.setSourceRectHintInsets( + getWindow().peekDecorView().getViewRootImpl().getLastContentInsets()); + } else { + args.setSourceRectHintInsets(null); + } + } + void dispatchMovedToDisplay(int displayId, Configuration config) { updateDisplay(displayId); onMovedToDisplay(displayId, config); diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java index 0ce5eebed2877..2fa6360469013 100644 --- a/core/java/android/app/PictureInPictureArgs.java +++ b/core/java/android/app/PictureInPictureArgs.java @@ -49,6 +49,13 @@ public final class PictureInPictureArgs implements Parcelable { @Nullable private Rect mSourceRectHint; + /** + * The content insets that are used with the source hint rect for the transition into PiP where + * the insets are removed at the beginning of the transition. + */ + @Nullable + private Rect mSourceRectHintInsets; + PictureInPictureArgs(Parcel in) { if (in.readInt() != 0) { mAspectRatio = in.readFloat(); @@ -60,6 +67,9 @@ public final class PictureInPictureArgs implements Parcelable { if (in.readInt() != 0) { mSourceRectHint = Rect.CREATOR.createFromParcel(in); } + if (in.readInt() != 0) { + mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in); + } } /** @@ -94,6 +104,9 @@ public final class PictureInPictureArgs implements Parcelable { if (otherArgs.hasSourceBoundsHint()) { mSourceRectHint = new Rect(otherArgs.getSourceRectHint()); } + if (otherArgs.hasSourceBoundsHintInsets()) { + mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets()); + } } /** @@ -167,13 +180,33 @@ public final class PictureInPictureArgs implements Parcelable { } /** - * @return the launch bounds + * Sets the insets to be used with the source rect hint bounds. + * @hide + */ + public void setSourceRectHintInsets(Rect insets) { + if (insets == null) { + mSourceRectHintInsets = null; + } else { + mSourceRectHintInsets = new Rect(insets); + } + } + + /** + * @return the source rect hint * @hide */ public Rect getSourceRectHint() { return mSourceRectHint; } + /** + * @return the source rect hint insets. + * @hide + */ + public Rect getSourceRectHintInsets() { + return mSourceRectHintInsets; + } + /** * @return whether there are launch bounds set * @hide @@ -182,12 +215,23 @@ public final class PictureInPictureArgs implements Parcelable { return mSourceRectHint != null && !mSourceRectHint.isEmpty(); } + /** + * @return whether there are source rect hint insets set + * @hide + */ + public boolean hasSourceBoundsHintInsets() { + return mSourceRectHintInsets != null; + } + @Override public PictureInPictureArgs clone() { PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions); if (mSourceRectHint != null) { args.setSourceRectHint(mSourceRectHint); } + if (mSourceRectHintInsets != null) { + args.setSourceRectHintInsets(mSourceRectHintInsets); + } return args; } @@ -216,6 +260,12 @@ public final class PictureInPictureArgs implements Parcelable { } else { out.writeInt(0); } + if (mSourceRectHintInsets != null) { + out.writeInt(1); + mSourceRectHintInsets.writeToParcel(out, 0); + } else { + out.writeInt(0); + } } public static final Creator CREATOR = diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a7ececf6c7820..080ffeb011f81 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1561,6 +1561,16 @@ public final class ViewRootImpl implements ViewParent, host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */)); } + /** + * @return the last content insets for use in adjusting the source hint rect for the + * picture-in-picture transition. + * + * @hide + */ + public Rect getLastContentInsets() { + return mAttachInfo.mContentInsets; + } + private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) { return lp.type == TYPE_STATUS_BAR_PANEL || lp.type == TYPE_INPUT_METHOD diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1c2a6aa2bbdff..83a623acdb66d 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -7863,7 +7863,14 @@ public class ActivityManagerService extends IActivityManager.Stub r.pictureInPictureArgs.copyOnlySet(args); final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); final List actions = r.pictureInPictureArgs.getActions(); - final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint(); + // Adjust the source bounds by the insets for the transition down + final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint()); + final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets(); + if (insets != null) { + sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left), + Math.max(0, sourceBounds.top - insets.top)); + } + mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio, true /* moveHomeStackToFront */, "enterPictureInPictureMode"); final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);