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