1 /* 2 * Copyright (C) 2014 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.telecom; 18 19 import android.annotation.IntDef; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.lang.annotation.Retention; 24 import java.lang.annotation.RetentionPolicy; 25 26 /** 27 * Represents attributes of video calls. 28 */ 29 public class VideoProfile implements Parcelable { 30 31 /** @hide */ 32 @Retention(RetentionPolicy.SOURCE) 33 @IntDef({QUALITY_UNKNOWN, QUALITY_HIGH, QUALITY_MEDIUM, QUALITY_LOW, QUALITY_DEFAULT}) 34 public @interface VideoQuality {} 35 36 /** 37 * "Unknown" video quality. 38 * @hide 39 */ 40 public static final int QUALITY_UNKNOWN = 0; 41 /** 42 * "High" video quality. 43 */ 44 public static final int QUALITY_HIGH = 1; 45 46 /** 47 * "Medium" video quality. 48 */ 49 public static final int QUALITY_MEDIUM = 2; 50 51 /** 52 * "Low" video quality. 53 */ 54 public static final int QUALITY_LOW = 3; 55 56 /** 57 * Use default video quality. 58 */ 59 public static final int QUALITY_DEFAULT = 4; 60 61 /** @hide */ 62 @Retention(RetentionPolicy.SOURCE) 63 @IntDef( 64 flag = true, 65 prefix = { "STATE_" }, 66 value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL, 67 STATE_PAUSED}) 68 public @interface VideoState {} 69 70 /** 71 * Used when answering or dialing a call to indicate that the call does not have a video 72 * component. 73 * <p> 74 * Should <b>not</b> be used in comparison checks to determine if a video state represents an 75 * audio-only call. 76 * <p> 77 * The following, for example, is not the correct way to check if a call is audio-only: 78 * <pre> 79 * {@code 80 * // This is the incorrect way to check for an audio-only call. 81 * if (videoState == VideoProfile.STATE_AUDIO_ONLY) { 82 * // Handle audio-only call. 83 * } 84 * } 85 * </pre> 86 * <p> 87 * Instead, use the {@link VideoProfile#isAudioOnly(int)} helper function to check if a 88 * video state represents an audio-only call: 89 * <pre> 90 * {@code 91 * // This is the correct way to check for an audio-only call. 92 * if (VideoProfile.isAudioOnly(videoState)) { 93 * // Handle audio-only call. 94 * } 95 * } 96 * </pre> 97 */ 98 public static final int STATE_AUDIO_ONLY = 0x0; 99 100 /** 101 * Video transmission is enabled. 102 */ 103 public static final int STATE_TX_ENABLED = 0x1; 104 105 /** 106 * Video reception is enabled. 107 */ 108 public static final int STATE_RX_ENABLED = 0x2; 109 110 /** 111 * Video signal is bi-directional. 112 */ 113 public static final int STATE_BIDIRECTIONAL = STATE_TX_ENABLED | STATE_RX_ENABLED; 114 115 /** 116 * Video is paused. 117 */ 118 public static final int STATE_PAUSED = 0x4; 119 120 private final int mVideoState; 121 122 private final int mQuality; 123 124 /** 125 * Creates an instance of the VideoProfile 126 * 127 * @param videoState The video state. 128 */ VideoProfile(@ideoState int videoState)129 public VideoProfile(@VideoState int videoState) { 130 this(videoState, QUALITY_DEFAULT); 131 } 132 133 /** 134 * Creates an instance of the VideoProfile 135 * 136 * @param videoState The video state. 137 * @param quality The video quality. 138 */ VideoProfile(@ideoState int videoState, @VideoQuality int quality)139 public VideoProfile(@VideoState int videoState, @VideoQuality int quality) { 140 mVideoState = videoState; 141 mQuality = quality; 142 } 143 144 /** 145 * The video state of the call. 146 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 147 * {@link VideoProfile#STATE_BIDIRECTIONAL}, 148 * {@link VideoProfile#STATE_TX_ENABLED}, 149 * {@link VideoProfile#STATE_RX_ENABLED}, 150 * {@link VideoProfile#STATE_PAUSED}. 151 */ 152 @VideoState getVideoState()153 public int getVideoState() { 154 return mVideoState; 155 } 156 157 /** 158 * The desired video quality for the call. 159 * Valid values: {@link VideoProfile#QUALITY_HIGH}, {@link VideoProfile#QUALITY_MEDIUM}, 160 * {@link VideoProfile#QUALITY_LOW}, {@link VideoProfile#QUALITY_DEFAULT}. 161 */ 162 @VideoQuality getQuality()163 public int getQuality() { 164 return mQuality; 165 } 166 167 /** 168 * Responsible for creating VideoProfile objects from deserialized Parcels. 169 **/ 170 public static final Parcelable.Creator<VideoProfile> CREATOR = 171 new Parcelable.Creator<VideoProfile> () { 172 /** 173 * Creates a MediaProfile instances from a parcel. 174 * 175 * @param source The parcel. 176 * @return The MediaProfile. 177 */ 178 @Override 179 public VideoProfile createFromParcel(Parcel source) { 180 int state = source.readInt(); 181 int quality = source.readInt(); 182 183 ClassLoader classLoader = VideoProfile.class.getClassLoader(); 184 return new VideoProfile(state, quality); 185 } 186 187 @Override 188 public VideoProfile[] newArray(int size) { 189 return new VideoProfile[size]; 190 } 191 }; 192 193 /** 194 * Describe the kinds of special objects contained in this Parcelable's 195 * marshalled representation. 196 * 197 * @return a bitmask indicating the set of special object types marshalled 198 * by the Parcelable. 199 */ 200 @Override describeContents()201 public int describeContents() { 202 return 0; 203 } 204 205 /** 206 * Flatten this object in to a Parcel. 207 * 208 * @param dest The Parcel in which the object should be written. 209 * @param flags Additional flags about how the object should be written. 210 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 211 */ 212 @Override writeToParcel(Parcel dest, int flags)213 public void writeToParcel(Parcel dest, int flags) { 214 dest.writeInt(mVideoState); 215 dest.writeInt(mQuality); 216 } 217 218 @Override toString()219 public String toString() { 220 StringBuilder sb = new StringBuilder(); 221 sb.append("[VideoProfile videoState = "); 222 sb.append(videoStateToString(mVideoState)); 223 sb.append(" videoQuality = "); 224 sb.append(mQuality); 225 sb.append("]"); 226 return sb.toString(); 227 } 228 229 /** 230 * Generates a string representation of a video state. 231 * 232 * @param videoState The video state. 233 * @return String representation of the video state. 234 */ videoStateToString(@ideoState int videoState)235 public static String videoStateToString(@VideoState int videoState) { 236 StringBuilder sb = new StringBuilder(); 237 sb.append("Audio"); 238 239 if (videoState == STATE_AUDIO_ONLY) { 240 sb.append(" Only"); 241 } else { 242 if (isTransmissionEnabled(videoState)) { 243 sb.append(" Tx"); 244 } 245 246 if (isReceptionEnabled(videoState)) { 247 sb.append(" Rx"); 248 } 249 250 if (isPaused(videoState)) { 251 sb.append(" Pause"); 252 } 253 } 254 255 return sb.toString(); 256 } 257 258 /** 259 * Indicates whether the video state is audio only. 260 * <p> 261 * Note: Considers only whether either both the {@link #STATE_RX_ENABLED} or 262 * {@link #STATE_TX_ENABLED} bits are off, but not {@link #STATE_PAUSED}. 263 * 264 * @param videoState The video state. 265 * @return {@code True} if the video state is audio only, {@code false} otherwise. 266 */ isAudioOnly(@ideoState int videoState)267 public static boolean isAudioOnly(@VideoState int videoState) { 268 return !hasState(videoState, VideoProfile.STATE_TX_ENABLED) 269 && !hasState(videoState, VideoProfile.STATE_RX_ENABLED); 270 } 271 272 /** 273 * Indicates whether video transmission or reception is enabled for a video state. 274 * 275 * @param videoState The video state. 276 * @return {@code True} if video transmission or reception is enabled, {@code false} otherwise. 277 */ isVideo(@ideoState int videoState)278 public static boolean isVideo(@VideoState int videoState) { 279 return hasState(videoState, VideoProfile.STATE_TX_ENABLED) 280 || hasState(videoState, VideoProfile.STATE_RX_ENABLED) 281 || hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL); 282 } 283 284 /** 285 * Indicates whether the video state has video transmission enabled. 286 * 287 * @param videoState The video state. 288 * @return {@code True} if video transmission is enabled, {@code false} otherwise. 289 */ isTransmissionEnabled(@ideoState int videoState)290 public static boolean isTransmissionEnabled(@VideoState int videoState) { 291 return hasState(videoState, VideoProfile.STATE_TX_ENABLED); 292 } 293 294 /** 295 * Indicates whether the video state has video reception enabled. 296 * 297 * @param videoState The video state. 298 * @return {@code True} if video reception is enabled, {@code false} otherwise. 299 */ isReceptionEnabled(@ideoState int videoState)300 public static boolean isReceptionEnabled(@VideoState int videoState) { 301 return hasState(videoState, VideoProfile.STATE_RX_ENABLED); 302 } 303 304 /** 305 * Indicates whether the video state is bi-directional. 306 * 307 * @param videoState The video state. 308 * @return {@code True} if the video is bi-directional, {@code false} otherwise. 309 */ isBidirectional(@ideoState int videoState)310 public static boolean isBidirectional(@VideoState int videoState) { 311 return hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL); 312 } 313 314 /** 315 * Indicates whether the video state is paused. 316 * 317 * @param videoState The video state. 318 * @return {@code True} if the video is paused, {@code false} otherwise. 319 */ isPaused(@ideoState int videoState)320 public static boolean isPaused(@VideoState int videoState) { 321 return hasState(videoState, VideoProfile.STATE_PAUSED); 322 } 323 324 /** 325 * Indicates if a specified state is set in a videoState bit-mask. 326 * 327 * @param videoState The video state bit-mask. 328 * @param state The state to check. 329 * @return {@code True} if the state is set. 330 */ hasState(@ideoState int videoState, @VideoState int state)331 private static boolean hasState(@VideoState int videoState, @VideoState int state) { 332 return (videoState & state) == state; 333 } 334 335 /** 336 * Represents the camera capabilities important to a Video Telephony provider. 337 */ 338 public static final class CameraCapabilities implements Parcelable { 339 340 /** 341 * The width of the camera video in pixels. 342 */ 343 private final int mWidth; 344 345 /** 346 * The height of the camera video in pixels. 347 */ 348 private final int mHeight; 349 350 /** 351 * Whether the camera supports zoom. 352 */ 353 private final boolean mZoomSupported; 354 355 /** 356 * The maximum zoom supported by the camera. 357 */ 358 private final float mMaxZoom; 359 360 /** 361 * Create a call camera capabilities instance. 362 * 363 * @param width The width of the camera video (in pixels). 364 * @param height The height of the camera video (in pixels). 365 */ CameraCapabilities(int width, int height)366 public CameraCapabilities(int width, int height) { 367 this(width, height, false, 1.0f); 368 } 369 370 /** 371 * Create a call camera capabilities instance that optionally 372 * supports zoom. 373 * 374 * @param width The width of the camera video (in pixels). 375 * @param height The height of the camera video (in pixels). 376 * @param zoomSupported True when camera supports zoom. 377 * @param maxZoom Maximum zoom supported by camera. 378 * @hide 379 */ CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom)380 public CameraCapabilities(int width, int height, boolean zoomSupported, float maxZoom) { 381 mWidth = width; 382 mHeight = height; 383 mZoomSupported = zoomSupported; 384 mMaxZoom = maxZoom; 385 } 386 387 /** 388 * Responsible for creating CallCameraCapabilities objects from deserialized Parcels. 389 **/ 390 public static final Parcelable.Creator<CameraCapabilities> CREATOR = 391 new Parcelable.Creator<CameraCapabilities> () { 392 /** 393 * Creates a CallCameraCapabilities instances from a parcel. 394 * 395 * @param source The parcel. 396 * @return The CallCameraCapabilities. 397 */ 398 @Override 399 public CameraCapabilities createFromParcel(Parcel source) { 400 int width = source.readInt(); 401 int height = source.readInt(); 402 boolean supportsZoom = source.readByte() != 0; 403 float maxZoom = source.readFloat(); 404 405 return new CameraCapabilities(width, height, supportsZoom, maxZoom); 406 } 407 408 @Override 409 public CameraCapabilities[] newArray(int size) { 410 return new CameraCapabilities[size]; 411 } 412 }; 413 414 /** 415 * Describe the kinds of special objects contained in this Parcelable's 416 * marshalled representation. 417 * 418 * @return a bitmask indicating the set of special object types marshalled 419 * by the Parcelable. 420 */ 421 @Override describeContents()422 public int describeContents() { 423 return 0; 424 } 425 426 /** 427 * Flatten this object in to a Parcel. 428 * 429 * @param dest The Parcel in which the object should be written. 430 * @param flags Additional flags about how the object should be written. 431 * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. 432 */ 433 @Override writeToParcel(Parcel dest, int flags)434 public void writeToParcel(Parcel dest, int flags) { 435 dest.writeInt(getWidth()); 436 dest.writeInt(getHeight()); 437 dest.writeByte((byte) (isZoomSupported() ? 1 : 0)); 438 dest.writeFloat(getMaxZoom()); 439 } 440 441 /** 442 * The width of the camera video in pixels. 443 */ getWidth()444 public int getWidth() { 445 return mWidth; 446 } 447 448 /** 449 * The height of the camera video in pixels. 450 */ getHeight()451 public int getHeight() { 452 return mHeight; 453 } 454 455 /** 456 * Whether the camera supports zoom. 457 * @hide 458 */ isZoomSupported()459 public boolean isZoomSupported() { 460 return mZoomSupported; 461 } 462 463 /** 464 * The maximum zoom supported by the camera. 465 * @hide 466 */ getMaxZoom()467 public float getMaxZoom() { 468 return mMaxZoom; 469 } 470 } 471 472 } 473