• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresFeature;
22 import android.annotation.TestApi;
23 import android.content.pm.PackageManager;
24 import android.graphics.Rect;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.Rational;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Objects;
32 
33 /**
34  * Represents a set of parameters used to initialize and update an Activity in picture-in-picture
35  * mode.
36  */
37 public final class PictureInPictureParams implements Parcelable {
38 
39     /**
40      * Builder class for {@link PictureInPictureParams} objects.
41      */
42     public static class Builder {
43 
44         @Nullable
45         private Rational mAspectRatio;
46 
47         @Nullable
48         private Rational mExpandedAspectRatio;
49 
50         @Nullable
51         private List<RemoteAction> mUserActions;
52 
53         @Nullable
54         private RemoteAction mCloseAction;
55 
56         @Nullable
57         private Rect mSourceRectHint;
58 
59         private Boolean mAutoEnterEnabled;
60 
61         private Boolean mSeamlessResizeEnabled;
62 
63         private CharSequence mTitle;
64 
65         private CharSequence mSubtitle;
66 
67         private Boolean mIsLaunchIntoPip;
68 
69         /** Default constructor */
Builder()70         public Builder() {}
71 
72         /**
73          * Copy constructor
74          * @param original {@link PictureInPictureParams} instance this builder is built upon.
75          */
Builder(@onNull PictureInPictureParams original)76         public Builder(@NonNull PictureInPictureParams original) {
77             mAspectRatio = original.mAspectRatio;
78             mUserActions = original.mUserActions;
79             mCloseAction = original.mCloseAction;
80             mSourceRectHint = original.mSourceRectHint;
81             mAutoEnterEnabled = original.mAutoEnterEnabled;
82             mSeamlessResizeEnabled = original.mSeamlessResizeEnabled;
83             mTitle = original.mTitle;
84             mSubtitle = original.mSubtitle;
85             mIsLaunchIntoPip = original.mIsLaunchIntoPip;
86         }
87 
88         /**
89          * Sets the aspect ratio.  This aspect ratio is defined as the desired width / height, and
90          * does not change upon device rotation.
91          *
92          * @param aspectRatio the new aspect ratio for the activity in picture-in-picture, must be
93          *                    between 2.39:1 and 1:2.39 (inclusive).
94          * @return this builder instance.
95          */
setAspectRatio(Rational aspectRatio)96         public Builder setAspectRatio(Rational aspectRatio) {
97             mAspectRatio = aspectRatio;
98             return this;
99         }
100 
101         /**
102          * Sets the aspect ratio for the expanded picture-in-picture mode. The aspect ratio is
103          * defined as the desired width / height. <br/>
104          * The aspect ratio cannot be changed from horizontal to vertical or vertical to horizontal
105          * while the PIP is shown. Any such changes will be ignored. <br/>
106          *
107          * Setting the expanded ratio shows the activity's support for expanded mode.
108          *
109          * @param expandedAspectRatio must not be between 2.39:1 and 1:2.39 (inclusive). If {@code
110          *                            null}, expanded picture-in-picture mode is not supported.
111          * @return this builder instance.
112          */
113         @RequiresFeature(PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE)
setExpandedAspectRatio(@ullable Rational expandedAspectRatio)114         public @NonNull Builder setExpandedAspectRatio(@Nullable Rational expandedAspectRatio) {
115             mExpandedAspectRatio = expandedAspectRatio;
116             return this;
117         }
118 
119         /**
120          * Sets the user actions.  If there are more than
121          * {@link Activity#getMaxNumPictureInPictureActions()} actions, then the input list
122          * will be truncated to that number.
123          *
124          * @param actions the new actions to show in the picture-in-picture menu.
125          *
126          * @return this builder instance.
127          *
128          * @see RemoteAction
129          */
setActions(List<RemoteAction> actions)130         public Builder setActions(List<RemoteAction> actions) {
131             if (mUserActions != null) {
132                 mUserActions = null;
133             }
134             if (actions != null) {
135                 mUserActions = new ArrayList<>(actions);
136             }
137             return this;
138         }
139 
140         /**
141          * Sets a close action that should be invoked before the default close PiP action. The
142          * custom action must close the activity quickly using {@link Activity#finish()}.
143          * Otherwise, the system will forcibly close the PiP as if no custom close action was
144          * provided.
145          *
146          * If the action matches one set via {@link PictureInPictureParams.Builder#setActions(List)}
147          * it may be shown in place of that custom action in the menu.
148          *
149          * @param action to replace the system close action
150          * @return this builder instance.
151          * @see RemoteAction
152          */
153         @NonNull
setCloseAction(@ullable RemoteAction action)154         public Builder setCloseAction(@Nullable RemoteAction action) {
155             mCloseAction = action;
156             return this;
157         }
158 
159         /**
160          * Sets the source bounds hint. These bounds are only used when an activity first enters
161          * picture-in-picture, and describe the bounds in window coordinates of activity entering
162          * picture-in-picture that will be visible following the transition. For the best effect,
163          * these bounds should also match the aspect ratio in the arguments.
164          *
165          * @param launchBounds window-coordinate bounds indicating the area of the activity that
166          * will still be visible following the transition into picture-in-picture (eg. the video
167          * view bounds in a video player)
168          *
169          * @return this builder instance.
170          */
setSourceRectHint(Rect launchBounds)171         public Builder setSourceRectHint(Rect launchBounds) {
172             if (launchBounds == null) {
173                 mSourceRectHint = null;
174             } else {
175                 mSourceRectHint = new Rect(launchBounds);
176             }
177             return this;
178         }
179 
180         /**
181          * Sets whether the system will automatically put the activity in picture-in-picture mode
182          * without needing/waiting for the activity to call
183          * {@link Activity#enterPictureInPictureMode(PictureInPictureParams)}.
184          *
185          * If true, {@link Activity#onPictureInPictureRequested()} will never be called.
186          *
187          * This property is {@code false} by default.
188          * @param autoEnterEnabled {@code true} if the system will automatically put the activity
189          *                                     in picture-in-picture mode.
190          *
191          * @return this builder instance.
192          */
193         @NonNull
setAutoEnterEnabled(boolean autoEnterEnabled)194         public Builder setAutoEnterEnabled(boolean autoEnterEnabled) {
195             mAutoEnterEnabled = autoEnterEnabled;
196             return this;
197         }
198 
199         /**
200          * Sets whether the system can seamlessly resize the window while the activity is in
201          * picture-in-picture mode. This should normally be the case for video content and
202          * when it's set to {@code false}, system will perform transitions to overcome the
203          * artifacts due to resize.
204          *
205          * This property is {@code true} by default for backwards compatibility.
206          * @param seamlessResizeEnabled {@code true} if the system can seamlessly resize the window
207          *                                          while activity is in picture-in-picture mode.
208          * @return this builder instance.
209          */
210         @NonNull
setSeamlessResizeEnabled(boolean seamlessResizeEnabled)211         public Builder setSeamlessResizeEnabled(boolean seamlessResizeEnabled) {
212             mSeamlessResizeEnabled = seamlessResizeEnabled;
213             return this;
214         }
215 
216         /**
217          * Sets a title for the picture-in-picture window, which may be displayed by the system to
218          * give the user information about what this PIP is generally being used for.
219          *
220          * @param title General information about the PIP content
221          * @return this builder instance.
222          */
223         @NonNull
setTitle(@ullable CharSequence title)224         public Builder setTitle(@Nullable CharSequence title) {
225             mTitle = title;
226             return this;
227         }
228 
229         /**
230          * Sets a subtitle for the picture-in-picture window, which may be displayed by the system
231          * to give the user more detailed information about what this PIP is displaying.<br/>
232          *
233          * Setting a title via {@link PictureInPictureParams.Builder#setTitle(CharSequence)} should
234          * be prioritized.
235          *
236          * @param subtitle Details about the PIP content.
237          * @return this builder instance
238          */
239         @NonNull
setSubtitle(@ullable CharSequence subtitle)240         public Builder setSubtitle(@Nullable CharSequence subtitle) {
241             mSubtitle = subtitle;
242             return this;
243         }
244 
245         /**
246          * Sets whether the built {@link PictureInPictureParams} represents a launch into
247          * picture-in-picture request.
248          *
249          * This property is {@code false} by default.
250          * @param isLaunchIntoPip {@code true} if the built instance represents a launch into
251          *                                 picture-in-picture request
252          * @return this builder instance.
253          */
254         @NonNull
setIsLaunchIntoPip(boolean isLaunchIntoPip)255         Builder setIsLaunchIntoPip(boolean isLaunchIntoPip) {
256             mIsLaunchIntoPip = isLaunchIntoPip;
257             return this;
258         }
259 
260         /**
261          * @return an immutable {@link PictureInPictureParams} to be used when entering or updating
262          * the activity in picture-in-picture.
263          *
264          * @see Activity#enterPictureInPictureMode(PictureInPictureParams)
265          * @see Activity#setPictureInPictureParams(PictureInPictureParams)
266          */
build()267         public PictureInPictureParams build() {
268             PictureInPictureParams params = new PictureInPictureParams(mAspectRatio,
269                     mExpandedAspectRatio, mUserActions, mCloseAction, mSourceRectHint,
270                     mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle,
271                     mIsLaunchIntoPip);
272             return params;
273         }
274     }
275 
276     /**
277      * The expected aspect ratio of the picture-in-picture.
278      */
279     @Nullable
280     private Rational mAspectRatio;
281 
282     /**
283      * The expected aspect ratio of the expanded picture-in-picture window.
284      */
285     @Nullable
286     private Rational mExpandedAspectRatio;
287 
288     /**
289      * The set of actions that are associated with this activity when in picture-in-picture.
290      */
291     @Nullable
292     private List<RemoteAction> mUserActions;
293 
294     /**
295      * Action to replace the system close action.
296      */
297     @Nullable
298     private RemoteAction mCloseAction;
299 
300     /**
301      * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
302      * We can use this internally for the transition into picture-in-picture to ensure that a
303      * particular source rect is visible throughout the whole transition.
304      */
305     @Nullable
306     private Rect mSourceRectHint;
307 
308     /**
309      * Whether the system is allowed to automatically put the activity in picture-in-picture mode.
310      * {@link #isAutoEnterEnabled()} defaults to {@code false} if this is not set.
311      */
312     private Boolean mAutoEnterEnabled;
313 
314     /**
315      * Whether system can seamlessly resize the window when activity is in picture-in-picture mode.
316      * {@link #isSeamlessResizeEnabled()} defaults to {@code true} if this is not set for
317      * backwards compatibility.
318      */
319     private Boolean mSeamlessResizeEnabled;
320 
321     /**
322      * Title of the picture-in-picture window to be displayed to the user.
323      */
324     @Nullable
325     private CharSequence mTitle;
326 
327     /**
328      * Subtitle for the picture-in-picture window to be displayed to the user.
329      */
330     @Nullable
331     private CharSequence mSubtitle;
332 
333     /**
334      * Whether this {@link PictureInPictureParams} represents a launch into
335      * picture-in-picture request.
336      * {@link #isLaunchIntoPip()} defaults to {@code false} is this is not set.
337      */
338     private Boolean mIsLaunchIntoPip;
339 
340     /** {@hide} */
PictureInPictureParams()341     PictureInPictureParams() {
342     }
343 
344     /** {@hide} */
PictureInPictureParams(Parcel in)345     PictureInPictureParams(Parcel in) {
346         mAspectRatio = readRationalFromParcel(in);
347         mExpandedAspectRatio = readRationalFromParcel(in);
348         if (in.readInt() != 0) {
349             mUserActions = new ArrayList<>();
350             in.readTypedList(mUserActions, RemoteAction.CREATOR);
351         }
352         mCloseAction = in.readTypedObject(RemoteAction.CREATOR);
353         if (in.readInt() != 0) {
354             mSourceRectHint = Rect.CREATOR.createFromParcel(in);
355         }
356         if (in.readInt() != 0) {
357             mAutoEnterEnabled = in.readBoolean();
358         }
359         if (in.readInt() != 0) {
360             mSeamlessResizeEnabled = in.readBoolean();
361         }
362         if (in.readInt() != 0) {
363             mTitle = in.readCharSequence();
364         }
365         if (in.readInt() != 0) {
366             mSubtitle = in.readCharSequence();
367         }
368         if (in.readInt() != 0) {
369             mIsLaunchIntoPip = in.readBoolean();
370         }
371     }
372 
373     /** {@hide} */
PictureInPictureParams(Rational aspectRatio, Rational expandedAspectRatio, List<RemoteAction> actions, RemoteAction closeAction, Rect sourceRectHint, Boolean autoEnterEnabled, Boolean seamlessResizeEnabled, CharSequence title, CharSequence subtitle, Boolean isLaunchIntoPip)374     PictureInPictureParams(Rational aspectRatio, Rational expandedAspectRatio,
375             List<RemoteAction> actions, RemoteAction closeAction, Rect sourceRectHint,
376             Boolean autoEnterEnabled, Boolean seamlessResizeEnabled, CharSequence title,
377             CharSequence subtitle, Boolean isLaunchIntoPip) {
378         mAspectRatio = aspectRatio;
379         mExpandedAspectRatio = expandedAspectRatio;
380         mUserActions = actions;
381         mCloseAction = closeAction;
382         mSourceRectHint = sourceRectHint;
383         mAutoEnterEnabled = autoEnterEnabled;
384         mSeamlessResizeEnabled = seamlessResizeEnabled;
385         mTitle = title;
386         mSubtitle = subtitle;
387         mIsLaunchIntoPip = isLaunchIntoPip;
388     }
389 
390     /**
391      * Makes a copy from the other picture-in-picture args.
392      * @hide
393      */
PictureInPictureParams(PictureInPictureParams other)394     public PictureInPictureParams(PictureInPictureParams other) {
395         this(other.mAspectRatio, other.mExpandedAspectRatio, other.mUserActions, other.mCloseAction,
396                 other.hasSourceBoundsHint() ? new Rect(other.getSourceRectHint()) : null,
397                 other.mAutoEnterEnabled, other.mSeamlessResizeEnabled,
398                 other.mTitle, other.mSubtitle, other.mIsLaunchIntoPip);
399     }
400 
401     /**
402      * Copies the set parameters from the other picture-in-picture args.
403      * @hide
404      */
copyOnlySet(PictureInPictureParams otherArgs)405     public void copyOnlySet(PictureInPictureParams otherArgs) {
406         if (otherArgs.hasSetAspectRatio()) {
407             mAspectRatio = otherArgs.mAspectRatio;
408         }
409 
410         // Copy either way because null can be used to explicitly unset the value
411         mExpandedAspectRatio = otherArgs.mExpandedAspectRatio;
412 
413         if (otherArgs.hasSetActions()) {
414             mUserActions = otherArgs.mUserActions;
415         }
416         if (otherArgs.hasSetCloseAction()) {
417             mCloseAction = otherArgs.mCloseAction;
418         }
419         if (otherArgs.hasSourceBoundsHint()) {
420             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
421         }
422         if (otherArgs.mAutoEnterEnabled != null) {
423             mAutoEnterEnabled = otherArgs.mAutoEnterEnabled;
424         }
425         if (otherArgs.mSeamlessResizeEnabled != null) {
426             mSeamlessResizeEnabled = otherArgs.mSeamlessResizeEnabled;
427         }
428         if (otherArgs.hasSetTitle()) {
429             mTitle = otherArgs.mTitle;
430         }
431         if (otherArgs.hasSetSubtitle()) {
432             mSubtitle = otherArgs.mSubtitle;
433         }
434         if (otherArgs.mIsLaunchIntoPip != null) {
435             mIsLaunchIntoPip = otherArgs.mIsLaunchIntoPip;
436         }
437     }
438 
439     /**
440      * @return the aspect ratio. If none is set, return 0.
441      * @hide
442      */
443     @TestApi
getAspectRatioFloat()444     public float getAspectRatioFloat() {
445         if (mAspectRatio != null) {
446             return mAspectRatio.floatValue();
447         }
448         return 0f;
449     }
450 
451     /**
452      * Returns the expected aspect ratio of the picture-in-picture window.
453      *
454      * @return aspect ratio as the desired width / height or {@code null} if not set.
455      * @see PictureInPictureParams.Builder#setAspectRatio(Rational)
456      */
457     @Nullable
getAspectRatio()458     public Rational getAspectRatio() {
459         return mAspectRatio;
460     }
461 
462     /**
463      * @return whether the aspect ratio is set.
464      * @hide
465      */
hasSetAspectRatio()466     public boolean hasSetAspectRatio() {
467         return mAspectRatio != null;
468     }
469 
470     /**
471      * @return the expanded aspect ratio. If none is set, return 0.
472      * @hide
473      */
474     @TestApi
getExpandedAspectRatioFloat()475     public float getExpandedAspectRatioFloat() {
476         if (mExpandedAspectRatio != null) {
477             return mExpandedAspectRatio.floatValue();
478         }
479         return 0f;
480     }
481 
482     /**
483      * Returns the desired aspect ratio of the expanded picture-in-picture window.
484      *
485      * @return aspect ratio as the desired width / height or {@code null} if not set.
486      * @see PictureInPictureParams.Builder#setExpandedAspectRatio(Rational)
487      */
488     @Nullable
getExpandedAspectRatio()489     public Rational getExpandedAspectRatio() {
490         return mExpandedAspectRatio;
491     }
492 
493     /**
494      * @return whether the expanded aspect ratio is set
495      * @hide
496      */
hasSetExpandedAspectRatio()497     public boolean hasSetExpandedAspectRatio() {
498         return mExpandedAspectRatio != null;
499     }
500 
501     /**
502      * Returns the list of user actions that are associated with the activity when in
503      * picture-in-picture mode.
504      *
505      * @return the user actions in a new list.
506      * @see PictureInPictureParams.Builder#setActions(List)
507      */
508     @NonNull
getActions()509     public List<RemoteAction> getActions() {
510         if (mUserActions == null) {
511             return new ArrayList<>();
512         }
513         return mUserActions;
514     }
515 
516     /**
517      * @return whether the user actions are set.
518      * @hide
519      */
hasSetActions()520     public boolean hasSetActions() {
521         return mUserActions != null;
522     }
523 
524     /**
525      * Returns the action that is to replace the system close action.
526      *
527      * @return the close action or {@code null} if not set.
528      * @see PictureInPictureParams.Builder#setCloseAction(RemoteAction)
529      */
530     @Nullable
getCloseAction()531     public RemoteAction getCloseAction() {
532         return mCloseAction;
533     }
534 
535     /**
536      * @return whether the close action was set.
537      * @hide
538      */
hasSetCloseAction()539     public boolean hasSetCloseAction() {
540         return mCloseAction != null;
541     }
542 
543     /**
544      * Truncates the set of actions to the given {@param size}.
545      *
546      * @hide
547      */
truncateActions(int size)548     public void truncateActions(int size) {
549         if (hasSetActions()) {
550             mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size));
551         }
552     }
553 
554     /**
555      * Returns the source rect hint.
556      *
557      * @return the source rect hint also known as launch bounds or {@code null} if not set.
558      * @see PictureInPictureParams.Builder#setSourceRectHint(Rect)
559      */
560     @Nullable
getSourceRectHint()561     public Rect getSourceRectHint() {
562         return mSourceRectHint;
563     }
564 
565     /**
566      * @return whether there are launch bounds set
567      * @hide
568      */
hasSourceBoundsHint()569     public boolean hasSourceBoundsHint() {
570         return mSourceRectHint != null && !mSourceRectHint.isEmpty();
571     }
572 
573     /**
574      * Returns whether auto enter picture-in-picture is enabled.
575      *
576      * @return {@code true} if the system will automatically put the activity in
577      * picture-in-picture mode.
578      * @see PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)
579      */
isAutoEnterEnabled()580     public boolean isAutoEnterEnabled() {
581         return mAutoEnterEnabled == null ? false : mAutoEnterEnabled;
582     }
583 
584     /**
585      * Returns whether seamless resize is enabled.
586      *
587      * @return true if the system can seamlessly resize the window while activity is in
588      * picture-in-picture mode.
589      * @see PictureInPictureParams.Builder#setSeamlessResizeEnabled(boolean)
590      */
isSeamlessResizeEnabled()591     public boolean isSeamlessResizeEnabled() {
592         return mSeamlessResizeEnabled == null ? true : mSeamlessResizeEnabled;
593     }
594 
595     /**
596      * @return whether a title was set.
597      * @hide
598      */
hasSetTitle()599     public boolean hasSetTitle() {
600         return mTitle != null;
601     }
602 
603     /**
604      * Returns the title of the picture-in-picture window that may be displayed to the user.
605      *
606      * @return title of the picture-in-picture window.
607      * @see PictureInPictureParams.Builder#setTitle(CharSequence)
608      */
609     @Nullable
getTitle()610     public CharSequence getTitle() {
611         return mTitle;
612     }
613 
614     /**
615      * @return whether a subtitle was set.
616      * @hide
617      */
hasSetSubtitle()618     public boolean hasSetSubtitle() {
619         return mSubtitle != null;
620     }
621 
622     /**
623      * Returns the subtitle of the picture-in-picture window that may be displayed to the user.
624      *
625      * @return subtitle of the picture-in-picture window.
626      * @see PictureInPictureParams.Builder#setSubtitle(CharSequence)
627      */
628     @Nullable
getSubtitle()629     public CharSequence getSubtitle() {
630         return mSubtitle;
631     }
632 
633     /**
634      * @return whether this {@link PictureInPictureParams} represents a launch into pip request.
635      * @hide
636      */
isLaunchIntoPip()637     public boolean isLaunchIntoPip() {
638         return mIsLaunchIntoPip == null ? false : mIsLaunchIntoPip;
639     }
640 
641     /**
642      * @return True if no parameters are set
643      * @hide
644      */
empty()645     public boolean empty() {
646         return !hasSourceBoundsHint() && !hasSetActions() && !hasSetCloseAction()
647                 && !hasSetAspectRatio() && !hasSetExpandedAspectRatio() && mAutoEnterEnabled == null
648                 && mSeamlessResizeEnabled == null && !hasSetTitle()
649                 && !hasSetSubtitle() && mIsLaunchIntoPip == null;
650     }
651 
652     @Override
equals(Object o)653     public boolean equals(Object o) {
654         if (this == o) return true;
655         if (!(o instanceof PictureInPictureParams)) return false;
656         PictureInPictureParams that = (PictureInPictureParams) o;
657         return Objects.equals(mAutoEnterEnabled, that.mAutoEnterEnabled)
658                 && Objects.equals(mSeamlessResizeEnabled, that.mSeamlessResizeEnabled)
659                 && Objects.equals(mAspectRatio, that.mAspectRatio)
660                 && Objects.equals(mExpandedAspectRatio, that.mExpandedAspectRatio)
661                 && Objects.equals(mUserActions, that.mUserActions)
662                 && Objects.equals(mCloseAction, that.mCloseAction)
663                 && Objects.equals(mSourceRectHint, that.mSourceRectHint)
664                 && Objects.equals(mTitle, that.mTitle)
665                 && Objects.equals(mSubtitle, that.mSubtitle)
666                 && Objects.equals(mIsLaunchIntoPip, that.mIsLaunchIntoPip);
667     }
668 
669     @Override
hashCode()670     public int hashCode() {
671         return Objects.hash(mAspectRatio, mExpandedAspectRatio, mUserActions, mCloseAction,
672                 mSourceRectHint, mAutoEnterEnabled, mSeamlessResizeEnabled, mTitle, mSubtitle,
673                 mIsLaunchIntoPip);
674     }
675 
676     @Override
describeContents()677     public int describeContents() {
678         return 0;
679     }
680 
681     @Override
writeToParcel(Parcel out, int flags)682     public void writeToParcel(Parcel out, int flags) {
683         writeRationalToParcel(mAspectRatio, out);
684         writeRationalToParcel(mExpandedAspectRatio, out);
685         if (mUserActions != null) {
686             out.writeInt(1);
687             out.writeTypedList(mUserActions, 0);
688         } else {
689             out.writeInt(0);
690         }
691 
692         out.writeTypedObject(mCloseAction, 0);
693 
694         if (mSourceRectHint != null) {
695             out.writeInt(1);
696             mSourceRectHint.writeToParcel(out, 0);
697         } else {
698             out.writeInt(0);
699         }
700         if (mAutoEnterEnabled != null) {
701             out.writeInt(1);
702             out.writeBoolean(mAutoEnterEnabled);
703         } else {
704             out.writeInt(0);
705         }
706         if (mSeamlessResizeEnabled != null) {
707             out.writeInt(1);
708             out.writeBoolean(mSeamlessResizeEnabled);
709         } else {
710             out.writeInt(0);
711         }
712         if (mTitle != null) {
713             out.writeInt(1);
714             out.writeCharSequence(mTitle);
715         } else {
716             out.writeInt(0);
717         }
718         if (mSubtitle != null) {
719             out.writeInt(1);
720             out.writeCharSequence(mSubtitle);
721         } else {
722             out.writeInt(0);
723         }
724         if (mIsLaunchIntoPip != null) {
725             out.writeInt(1);
726             out.writeBoolean(mIsLaunchIntoPip);
727         } else {
728             out.writeInt(0);
729         }
730     }
731 
writeRationalToParcel(Rational rational, Parcel out)732     private void writeRationalToParcel(Rational rational, Parcel out) {
733         if (rational != null) {
734             out.writeInt(1);
735             out.writeInt(rational.getNumerator());
736             out.writeInt(rational.getDenominator());
737         } else {
738             out.writeInt(0);
739         }
740     }
741 
readRationalFromParcel(Parcel in)742     private Rational readRationalFromParcel(Parcel in) {
743         if (in.readInt() != 0) {
744             return new Rational(in.readInt(), in.readInt());
745         }
746         return null;
747     }
748 
749     @Override
toString()750     public String toString() {
751         return "PictureInPictureParams("
752                 + " aspectRatio=" + getAspectRatio()
753                 + " expandedAspectRatio=" + mExpandedAspectRatio
754                 + " sourceRectHint=" + getSourceRectHint()
755                 + " hasSetActions=" + hasSetActions()
756                 + " hasSetCloseAction=" + hasSetCloseAction()
757                 + " isAutoPipEnabled=" + isAutoEnterEnabled()
758                 + " isSeamlessResizeEnabled=" + isSeamlessResizeEnabled()
759                 + " title=" + getTitle()
760                 + " subtitle=" + getSubtitle()
761                 + " isLaunchIntoPip=" + isLaunchIntoPip()
762                 + ")";
763     }
764 
765     public static final @android.annotation.NonNull Creator<PictureInPictureParams> CREATOR =
766             new Creator<PictureInPictureParams>() {
767                 public PictureInPictureParams createFromParcel(Parcel in) {
768                     return new PictureInPictureParams(in);
769                 }
770                 public PictureInPictureParams[] newArray(int size) {
771                     return new PictureInPictureParams[size];
772                 }
773             };
774 }
775