Home | History | Annotate | Download | only in telecom
      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      */
    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      */
    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
    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
    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
    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
    216     public void writeToParcel(Parcel dest, int flags) {
    217         dest.writeInt(mVideoState);
    218         dest.writeInt(mQuality);
    219     }
    220 
    221     @Override
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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          */
    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          */
    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
    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
    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          */
    446         public int getWidth() {
    447             return mWidth;
    448         }
    449 
    450         /**
    451          * The height of the camera video in pixels.
    452          */
    453         public int getHeight() {
    454             return mHeight;
    455         }
    456 
    457         /**
    458          * Returns {@code true} is zoom is supported, {@code false} otherwise.
    459          */
    460         public boolean isZoomSupported() {
    461             return mZoomSupported;
    462         }
    463 
    464         /**
    465          * Returns the maximum zoom supported by the camera.
    466          */
    467         public float getMaxZoom() {
    468             return mMaxZoom;
    469         }
    470     }
    471 
    472 }
    473