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