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
17package android.app;
18
19import android.annotation.Nullable;
20import android.graphics.Rect;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.util.Rational;
24
25import java.util.ArrayList;
26import java.util.List;
27
28/** @removed */
29@Deprecated
30public final class PictureInPictureArgs implements Parcelable {
31
32    /**
33     * Builder class for {@link PictureInPictureArgs} objects.
34     */
35    public static class Builder {
36
37        @Nullable
38        private Rational mAspectRatio;
39
40        @Nullable
41        private List<RemoteAction> mUserActions;
42
43        @Nullable
44        private Rect mSourceRectHint;
45
46        /**
47         * Sets the aspect ratio.  This aspect ratio is defined as the desired width / height, and
48         * does not change upon device rotation.
49         *
50         * @param aspectRatio the new aspect ratio for the activity in picture-in-picture, must be
51         * between 2.39:1 and 1:2.39 (inclusive).
52         *
53         * @return this builder instance.
54         */
55        public Builder setAspectRatio(Rational aspectRatio) {
56            mAspectRatio = aspectRatio;
57            return this;
58        }
59
60        /**
61         * Sets the user actions.  If there are more than
62         * {@link Activity#getMaxNumPictureInPictureActions()} actions, then the input list
63         * will be truncated to that number.
64         *
65         * @param actions the new actions to show in the picture-in-picture menu.
66         *
67         * @return this builder instance.
68         *
69         * @see RemoteAction
70         */
71        public Builder setActions(List<RemoteAction> actions) {
72            if (mUserActions != null) {
73                mUserActions = null;
74            }
75            if (actions != null) {
76                mUserActions = new ArrayList<>(actions);
77            }
78            return this;
79        }
80
81        /**
82         * Sets the source bounds hint. These bounds are only used when an activity first enters
83         * picture-in-picture, and describe the bounds in window coordinates of activity entering
84         * picture-in-picture that will be visible following the transition. For the best effect,
85         * these bounds should also match the aspect ratio in the arguments.
86         *
87         * @param launchBounds window-coordinate bounds indicating the area of the activity that
88         * will still be visible following the transition into picture-in-picture (eg. the video
89         * view bounds in a video player)
90         *
91         * @return this builder instance.
92         */
93        public Builder setSourceRectHint(Rect launchBounds) {
94            if (launchBounds == null) {
95                mSourceRectHint = null;
96            } else {
97                mSourceRectHint = new Rect(launchBounds);
98            }
99            return this;
100        }
101
102        public PictureInPictureArgs build() {
103            PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions,
104                    mSourceRectHint);
105            return args;
106        }
107    }
108
109    /**
110     * The expected aspect ratio of the picture-in-picture.
111     */
112    @Nullable
113    private Rational mAspectRatio;
114
115    /**
116     * The set of actions that are associated with this activity when in picture-in-picture.
117     */
118    @Nullable
119    private List<RemoteAction> mUserActions;
120
121    /**
122     * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
123     * We can use this internally for the transition into picture-in-picture to ensure that a
124     * particular source rect is visible throughout the whole transition.
125     */
126    @Nullable
127    private Rect mSourceRectHint;
128
129    /**
130     * The content insets that are used with the source hint rect for the transition into PiP where
131     * the insets are removed at the beginning of the transition.
132     */
133    @Nullable
134    private Rect mSourceRectHintInsets;
135
136    /**
137     * @hide
138     */
139    @Deprecated
140    public PictureInPictureArgs() {
141    }
142
143    /**
144     * @hide
145     */
146    @Deprecated
147    public PictureInPictureArgs(float aspectRatio, List<RemoteAction> actions) {
148        setAspectRatio(aspectRatio);
149        setActions(actions);
150    }
151
152    private PictureInPictureArgs(Parcel in) {
153        if (in.readInt() != 0) {
154            mAspectRatio = new Rational(in.readInt(), in.readInt());
155        }
156        if (in.readInt() != 0) {
157            mUserActions = new ArrayList<>();
158            in.readParcelableList(mUserActions, RemoteAction.class.getClassLoader());
159        }
160        if (in.readInt() != 0) {
161            mSourceRectHint = Rect.CREATOR.createFromParcel(in);
162        }
163    }
164
165    private PictureInPictureArgs(Rational aspectRatio, List<RemoteAction> actions,
166            Rect sourceRectHint) {
167        mAspectRatio = aspectRatio;
168        mUserActions = actions;
169        mSourceRectHint = sourceRectHint;
170    }
171
172    /**
173     * @hide
174     */
175    @Deprecated
176    public void setAspectRatio(float aspectRatio) {
177        // Temporary workaround
178        mAspectRatio = new Rational((int) (aspectRatio * 1000000000), 1000000000);
179    }
180
181    /**
182     * @hide
183     */
184    @Deprecated
185    public void setActions(List<RemoteAction> actions) {
186        if (mUserActions != null) {
187            mUserActions = null;
188        }
189        if (actions != null) {
190            mUserActions = new ArrayList<>(actions);
191        }
192    }
193
194    /**
195     * @hide
196     */
197    @Deprecated
198    public void setSourceRectHint(Rect launchBounds) {
199        if (launchBounds == null) {
200            mSourceRectHint = null;
201        } else {
202            mSourceRectHint = new Rect(launchBounds);
203        }
204    }
205
206    /**
207     * Copies the set parameters from the other picture-in-picture args.
208     * @hide
209     */
210    public void copyOnlySet(PictureInPictureArgs otherArgs) {
211        if (otherArgs.hasSetAspectRatio()) {
212            mAspectRatio = otherArgs.mAspectRatio;
213        }
214        if (otherArgs.hasSetActions()) {
215            mUserActions = otherArgs.mUserActions;
216        }
217        if (otherArgs.hasSourceBoundsHint()) {
218            mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
219        }
220    }
221
222    /**
223     * @return the aspect ratio. If none is set, return 0.
224     * @hide
225     */
226    public float getAspectRatio() {
227        if (mAspectRatio != null) {
228            return mAspectRatio.floatValue();
229        }
230        return 0f;
231    }
232
233    /** {@hide} */
234    public Rational getAspectRatioRational() {
235        return mAspectRatio;
236    }
237
238    /**
239     * @return whether the aspect ratio is set.
240     * @hide
241     */
242    public boolean hasSetAspectRatio() {
243        return mAspectRatio != null;
244    }
245
246    /**
247     * @return the set of user actions.
248     * @hide
249     */
250    public List<RemoteAction> getActions() {
251        return mUserActions;
252    }
253
254    /**
255     * @return whether the user actions are set.
256     * @hide
257     */
258    public boolean hasSetActions() {
259        return mUserActions != null;
260    }
261
262    /**
263     * Truncates the set of actions to the given {@param size}.
264     * @hide
265     */
266    public void truncateActions(int size) {
267        if (hasSetActions()) {
268            mUserActions = mUserActions.subList(0, Math.min(mUserActions.size(), size));
269        }
270    }
271
272    /**
273     * Sets the insets to be used with the source rect hint bounds.
274     * @hide
275     */
276    @Deprecated
277    public void setSourceRectHintInsets(Rect insets) {
278        if (insets == null) {
279            mSourceRectHintInsets = null;
280        } else {
281            mSourceRectHintInsets = new Rect(insets);
282        }
283    }
284
285    /**
286     * @return the source rect hint
287     * @hide
288     */
289    public Rect getSourceRectHint() {
290        return mSourceRectHint;
291    }
292
293    /**
294     * @return the source rect hint insets.
295     * @hide
296     */
297    public Rect getSourceRectHintInsets() {
298        return mSourceRectHintInsets;
299    }
300
301    /**
302     * @return whether there are launch bounds set
303     * @hide
304     */
305    public boolean hasSourceBoundsHint() {
306        return mSourceRectHint != null && !mSourceRectHint.isEmpty();
307    }
308
309    /**
310     * @return whether there are source rect hint insets set
311     * @hide
312     */
313    public boolean hasSourceBoundsHintInsets() {
314        return mSourceRectHintInsets != null;
315    }
316
317    @Override
318    public int describeContents() {
319        return 0;
320    }
321
322    @Override
323    public void writeToParcel(Parcel out, int flags) {
324        if (mAspectRatio != null) {
325            out.writeInt(1);
326            out.writeInt(mAspectRatio.getNumerator());
327            out.writeInt(mAspectRatio.getDenominator());
328        } else {
329            out.writeInt(0);
330        }
331        if (mUserActions != null) {
332            out.writeInt(1);
333            out.writeParcelableList(mUserActions, 0);
334        } else {
335            out.writeInt(0);
336        }
337        if (mSourceRectHint != null) {
338            out.writeInt(1);
339            mSourceRectHint.writeToParcel(out, 0);
340        } else {
341            out.writeInt(0);
342        }
343    }
344
345    public static final Creator<PictureInPictureArgs> CREATOR =
346            new Creator<PictureInPictureArgs>() {
347                public PictureInPictureArgs createFromParcel(Parcel in) {
348                    return new PictureInPictureArgs(in);
349                }
350                public PictureInPictureArgs[] newArray(int size) {
351                    return new PictureInPictureArgs[size];
352                }
353            };
354
355    public static PictureInPictureArgs convert(PictureInPictureParams params) {
356        return new PictureInPictureArgs(params.getAspectRatioRational(), params.getActions(),
357                params.getSourceRectHint());
358    }
359
360    public static PictureInPictureParams convert(PictureInPictureArgs args) {
361        return new PictureInPictureParams(args.getAspectRatioRational(), args.getActions(),
362                args.getSourceRectHint());
363    }
364}
365