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