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