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