1 /*
2  * Copyright (C) 2018 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.telephony.ims;
18 
19 import android.annotation.SystemApi;
20 import android.os.Bundle;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.PersistableBundle;
24 import android.telecom.VideoProfile;
25 import android.util.Log;
26 
27 import com.android.internal.telephony.PhoneConstants;
28 
29 /**
30  * Parcelable object to handle IMS call profile.
31  * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
32  * It provides the service and call type, the additional information related to the call.
33  *
34  * @hide
35  */
36 @SystemApi
37 public final class ImsCallProfile implements Parcelable {
38     private static final String TAG = "ImsCallProfile";
39 
40     /**
41      * Service types
42      */
43     /**
44      * It is for a special case. It helps that the application can make a call
45      * without IMS connection (not registered).
46      * In the moment of the call initiation, the device try to connect to the IMS network
47      * and initiates the call.
48      */
49     public static final int SERVICE_TYPE_NONE = 0;
50     /**
51      * It is a default type and can be selected when the device is connected to the IMS network.
52      */
53     public static final int SERVICE_TYPE_NORMAL = 1;
54     /**
55      * It is for an emergency call.
56      */
57     public static final int SERVICE_TYPE_EMERGENCY = 2;
58 
59     /**
60      * Call types
61      */
62     /**
63      * IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
64      */
65     public static final int CALL_TYPE_VOICE_N_VIDEO = 1;
66     /**
67      * IR.92 (Voice only)
68      */
69     public static final int CALL_TYPE_VOICE = 2;
70     /**
71      * VT to support IR.92 & IR.94 (voice + video upgrade/downgrade)
72      */
73     public static final int CALL_TYPE_VIDEO_N_VOICE = 3;
74     /**
75      * Video Telephony (audio / video two way)
76      */
77     public static final int CALL_TYPE_VT = 4;
78     /**
79      * Video Telephony (audio two way / video TX one way)
80      */
81     public static final int CALL_TYPE_VT_TX = 5;
82     /**
83      * Video Telephony (audio two way / video RX one way)
84      */
85     public static final int CALL_TYPE_VT_RX = 6;
86     /**
87      * Video Telephony (audio two way / video inactive)
88      */
89     public static final int CALL_TYPE_VT_NODIR = 7;
90     /**
91      * VideoShare (video two way)
92      */
93     public static final int CALL_TYPE_VS = 8;
94     /**
95      * VideoShare (video TX one way)
96      */
97     public static final int CALL_TYPE_VS_TX = 9;
98     /**
99      * VideoShare (video RX one way)
100      */
101     public static final int CALL_TYPE_VS_RX = 10;
102 
103     /**
104      * Extra properties for IMS call.
105      */
106     /**
107      * Boolean extra properties - "true" / "false"
108      *  conference : Indicates if the session is for the conference call or not.
109      *  e_call : Indicates if the session is for the emergency call or not.
110      *  vms : Indicates if the session is connected to the voice mail system or not.
111      *  call_mode_changeable : Indicates if the session is able to upgrade/downgrade
112      *      the video during voice call.
113      *  conference_avail : Indicates if the session can be extended to the conference.
114      */
115     /**
116      * @hide
117      */
118     public static final String EXTRA_CONFERENCE = "conference";
119     /**
120      * @hide
121      */
122     public static final String EXTRA_E_CALL = "e_call";
123     /**
124      * @hide
125      */
126     public static final String EXTRA_VMS = "vms";
127     /**
128      * @hide
129      */
130     public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
131     /**
132      * @hide
133      */
134     public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
135 
136     // Extra string for internal use only. OEMs should not use
137     // this for packing extras.
138     /**
139      * @hide
140      */
141     public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
142 
143     /**
144      * Rule for originating identity (number) presentation, MO/MT.
145      *      {@link ImsCallProfile#OIR_DEFAULT}
146      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
147      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
148      */
149     public static final String EXTRA_OIR = "oir";
150     /**
151      * Rule for calling name presentation
152      *      {@link ImsCallProfile#OIR_DEFAULT}
153      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
154      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
155      */
156     public static final String EXTRA_CNAP = "cnap";
157     /**
158      * To identify the Ims call type, MO
159      *      {@link ImsCallProfile#DIALSTRING_NORMAL}
160      *      {@link ImsCallProfile#DIALSTRING_SS_CONF}
161      *      {@link ImsCallProfile#DIALSTRING_USSD}
162      */
163     public static final String EXTRA_DIALSTRING = "dialstring";
164 
165     /**
166      * Values for EXTRA_OIR / EXTRA_CNAP
167      */
168     /**
169      * Default presentation for Originating Identity.
170      */
171     public static final int OIR_DEFAULT = 0;    // "user subscription default value"
172     /**
173      * Restricted presentation for Originating Identity.
174      */
175     public static final int OIR_PRESENTATION_RESTRICTED = 1;
176     /**
177      * Not restricted presentation for Originating Identity.
178      */
179     public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
180     /**
181      * Presentation unknown for Originating Identity.
182      */
183     public static final int OIR_PRESENTATION_UNKNOWN = 3;
184     /**
185      * Payphone presentation for Originating Identity.
186      */
187     public static final int OIR_PRESENTATION_PAYPHONE = 4;
188 
189     //Values for EXTRA_DIALSTRING
190     /**
191      * A default or normal normal call.
192      */
193     public static final int DIALSTRING_NORMAL = 0;
194     /**
195      * Call for SIP-based user configuration
196      */
197     public static final int DIALSTRING_SS_CONF = 1;
198     /**
199      * Call for USSD message
200      */
201     public static final int DIALSTRING_USSD = 2;
202 
203     /**
204      * Values for causes that restrict call types
205      */
206     // Default cause not restricted at peer and HD is supported
207     public static final int CALL_RESTRICT_CAUSE_NONE = 0;
208     // Service not supported by RAT at peer
209     public static final int CALL_RESTRICT_CAUSE_RAT = 1;
210     // Service Disabled at peer
211     public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
212     // HD is not supported
213     public static final int CALL_RESTRICT_CAUSE_HD = 3;
214 
215     /**
216      * String extra properties
217      *  oi : Originating identity (number), MT only
218      *  cna : Calling name
219      *  ussd : For network-initiated USSD, MT only
220      *  remote_uri : Connected user identity (it can be used for the conference)
221      *  ChildNum: Child number info.
222      *  Codec: Codec info.
223      *  DisplayText: Display text for the call.
224      *  AdditionalCallInfo: Additional call info.
225      *  CallPull: Boolean value specifying if the call is a pulled call.
226      */
227     public static final String EXTRA_OI = "oi";
228     public static final String EXTRA_CNA = "cna";
229     public static final String EXTRA_USSD = "ussd";
230     public static final String EXTRA_REMOTE_URI = "remote_uri";
231     public static final String EXTRA_CHILD_NUMBER = "ChildNum";
232     public static final String EXTRA_CODEC = "Codec";
233     public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
234     public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
235     public static final String EXTRA_IS_CALL_PULL = "CallPull";
236 
237     /**
238      * Extra key which the RIL can use to indicate the radio technology used for a call.
239      * Valid values are:
240      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE},
241      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}, and the other defined
242      * {@code RIL_RADIO_TECHNOLOGY_*} constants.
243      * Note: Despite the fact the {@link android.telephony.ServiceState} values are integer
244      * constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
245      * "14" vs (int) 14).
246      * Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
247      *      updateWifiStateFromExtras(Bundle)} to determine whether to set the
248      * {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
249      */
250     public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
251 
252     /**
253      * Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'.  Used to ensure
254      * compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
255      * extra key.  Should be removed when the non-compliant modems are fixed.
256      * @hide
257      */
258     public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
259 
260     /** @hide */
261     public int mServiceType;
262     /** @hide */
263     public int mCallType;
264     /** @hide */
265     public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
266 
267     /**
268      * Extras associated with this {@link ImsCallProfile}.
269      * <p>
270      * Valid data types include:
271      * <ul>
272      *     <li>{@link Integer} (and int)</li>
273      *     <li>{@link Long} (and long)</li>
274      *     <li>{@link Double} (and double)</li>
275      *     <li>{@link String}</li>
276      *     <li>{@code int[]}</li>
277      *     <li>{@code long[]}</li>
278      *     <li>{@code double[]}</li>
279      *     <li>{@code String[]}</li>
280      *     <li>{@link PersistableBundle}</li>
281      *     <li>{@link Boolean} (and boolean)</li>
282      *     <li>{@code boolean[]}</li>
283      *     <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
284      * </ul>
285      * <p>
286      * Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
287      * a {@link android.os.Binder}.
288      */
289     /** @hide */
290     public Bundle mCallExtras;
291     /** @hide */
292     public ImsStreamMediaProfile mMediaProfile;
293 
294     /** @hide */
ImsCallProfile(Parcel in)295     public ImsCallProfile(Parcel in) {
296         readFromParcel(in);
297     }
298 
299     /**
300      * Default Constructor that initializes the call profile with service type
301      * {@link #SERVICE_TYPE_NORMAL} and call type {@link #CALL_TYPE_VIDEO_N_VOICE}
302      */
ImsCallProfile()303     public ImsCallProfile() {
304         mServiceType = SERVICE_TYPE_NORMAL;
305         mCallType = CALL_TYPE_VOICE_N_VIDEO;
306         mCallExtras = new Bundle();
307         mMediaProfile = new ImsStreamMediaProfile();
308     }
309 
310     /**
311      * Constructor.
312      *
313      * @param serviceType the service type for the call. Can be one of the following:
314      *                    {@link #SERVICE_TYPE_NONE},
315      *                    {@link #SERVICE_TYPE_NORMAL},
316      *                    {@link #SERVICE_TYPE_EMERGENCY}
317      * @param callType the call type. Can be one of the following:
318      *                 {@link #CALL_TYPE_VOICE_N_VIDEO},
319      *                 {@link #CALL_TYPE_VOICE},
320      *                 {@link #CALL_TYPE_VIDEO_N_VOICE},
321      *                 {@link #CALL_TYPE_VT},
322      *                 {@link #CALL_TYPE_VT_TX},
323      *                 {@link #CALL_TYPE_VT_RX},
324      *                 {@link #CALL_TYPE_VT_NODIR},
325      *                 {@link #CALL_TYPE_VS},
326      *                 {@link #CALL_TYPE_VS_TX},
327      *                 {@link #CALL_TYPE_VS_RX}
328      */
ImsCallProfile(int serviceType, int callType)329     public ImsCallProfile(int serviceType, int callType) {
330         mServiceType = serviceType;
331         mCallType = callType;
332         mCallExtras = new Bundle();
333         mMediaProfile = new ImsStreamMediaProfile();
334     }
335 
336     /**
337      * Constructor.
338      *
339      * @param serviceType the service type for the call. Can be one of the following:
340      *                    {@link #SERVICE_TYPE_NONE},
341      *                    {@link #SERVICE_TYPE_NORMAL},
342      *                    {@link #SERVICE_TYPE_EMERGENCY}
343      * @param callType the call type. Can be one of the following:
344      *                 {@link #CALL_TYPE_VOICE_N_VIDEO},
345      *                 {@link #CALL_TYPE_VOICE},
346      *                 {@link #CALL_TYPE_VIDEO_N_VOICE},
347      *                 {@link #CALL_TYPE_VT},
348      *                 {@link #CALL_TYPE_VT_TX},
349      *                 {@link #CALL_TYPE_VT_RX},
350      *                 {@link #CALL_TYPE_VT_NODIR},
351      *                 {@link #CALL_TYPE_VS},
352      *                 {@link #CALL_TYPE_VS_TX},
353      *                 {@link #CALL_TYPE_VS_RX}
354      * @param callExtras A bundle with the call extras.
355      * @param mediaProfile The IMS stream media profile.
356      */
ImsCallProfile(int serviceType, int callType, Bundle callExtras, ImsStreamMediaProfile mediaProfile)357     public ImsCallProfile(int serviceType, int callType, Bundle callExtras,
358             ImsStreamMediaProfile mediaProfile) {
359         mServiceType = serviceType;
360         mCallType = callType;
361         mCallExtras = callExtras;
362         mMediaProfile = mediaProfile;
363     }
364 
getCallExtra(String name)365     public String getCallExtra(String name) {
366         return getCallExtra(name, "");
367     }
368 
getCallExtra(String name, String defaultValue)369     public String getCallExtra(String name, String defaultValue) {
370         if (mCallExtras == null) {
371             return defaultValue;
372         }
373 
374         return mCallExtras.getString(name, defaultValue);
375     }
376 
getCallExtraBoolean(String name)377     public boolean getCallExtraBoolean(String name) {
378         return getCallExtraBoolean(name, false);
379     }
380 
getCallExtraBoolean(String name, boolean defaultValue)381     public boolean getCallExtraBoolean(String name, boolean defaultValue) {
382         if (mCallExtras == null) {
383             return defaultValue;
384         }
385 
386         return mCallExtras.getBoolean(name, defaultValue);
387     }
388 
getCallExtraInt(String name)389     public int getCallExtraInt(String name) {
390         return getCallExtraInt(name, -1);
391     }
392 
getCallExtraInt(String name, int defaultValue)393     public int getCallExtraInt(String name, int defaultValue) {
394         if (mCallExtras == null) {
395             return defaultValue;
396         }
397 
398         return mCallExtras.getInt(name, defaultValue);
399     }
400 
setCallExtra(String name, String value)401     public void setCallExtra(String name, String value) {
402         if (mCallExtras != null) {
403             mCallExtras.putString(name, value);
404         }
405     }
406 
setCallExtraBoolean(String name, boolean value)407     public void setCallExtraBoolean(String name, boolean value) {
408         if (mCallExtras != null) {
409             mCallExtras.putBoolean(name, value);
410         }
411     }
412 
setCallExtraInt(String name, int value)413     public void setCallExtraInt(String name, int value) {
414         if (mCallExtras != null) {
415             mCallExtras.putInt(name, value);
416         }
417     }
418 
updateCallType(ImsCallProfile profile)419     public void updateCallType(ImsCallProfile profile) {
420         mCallType = profile.mCallType;
421     }
422 
updateCallExtras(ImsCallProfile profile)423     public void updateCallExtras(ImsCallProfile profile) {
424         mCallExtras.clear();
425         mCallExtras = (Bundle) profile.mCallExtras.clone();
426     }
427 
428     /**
429      * Updates the media profile for the call.
430      *
431      * @param profile Call profile with new media profile.
432      */
updateMediaProfile(ImsCallProfile profile)433     public void updateMediaProfile(ImsCallProfile profile) {
434         mMediaProfile = profile.mMediaProfile;
435     }
436 
437 
438     @Override
toString()439     public String toString() {
440         return "{ serviceType=" + mServiceType +
441                 ", callType=" + mCallType +
442                 ", restrictCause=" + mRestrictCause +
443                 ", mediaProfile=" + mMediaProfile.toString() + " }";
444     }
445 
446     @Override
describeContents()447     public int describeContents() {
448         return 0;
449     }
450 
451     @Override
writeToParcel(Parcel out, int flags)452     public void writeToParcel(Parcel out, int flags) {
453         Bundle filteredExtras = maybeCleanseExtras(mCallExtras);
454         out.writeInt(mServiceType);
455         out.writeInt(mCallType);
456         out.writeBundle(filteredExtras);
457         out.writeParcelable(mMediaProfile, 0);
458     }
459 
readFromParcel(Parcel in)460     private void readFromParcel(Parcel in) {
461         mServiceType = in.readInt();
462         mCallType = in.readInt();
463         mCallExtras = in.readBundle();
464         mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
465     }
466 
467     public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
468         @Override
469         public ImsCallProfile createFromParcel(Parcel in) {
470             return new ImsCallProfile(in);
471         }
472 
473         @Override
474         public ImsCallProfile[] newArray(int size) {
475             return new ImsCallProfile[size];
476         }
477     };
478 
getServiceType()479     public int getServiceType() {
480         return mServiceType;
481     }
482 
getCallType()483     public int getCallType() {
484         return mCallType;
485     }
486 
getRestrictCause()487     public int getRestrictCause() {
488         return mRestrictCause;
489     }
490 
getCallExtras()491     public Bundle getCallExtras() {
492         return mCallExtras;
493     }
494 
getMediaProfile()495     public ImsStreamMediaProfile getMediaProfile() {
496         return mMediaProfile;
497     }
498 
499     /**
500      * Converts from the call types defined in {@link ImsCallProfile} to the
501      * video state values defined in {@link VideoProfile}.
502      *
503      * @param callProfile The call profile.
504      * @return The video state.
505      */
getVideoStateFromImsCallProfile(ImsCallProfile callProfile)506     public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) {
507         int videostate = getVideoStateFromCallType(callProfile.mCallType);
508         if (callProfile.isVideoPaused() && !VideoProfile.isAudioOnly(videostate)) {
509             videostate |= VideoProfile.STATE_PAUSED;
510         } else {
511             videostate &= ~VideoProfile.STATE_PAUSED;
512         }
513         return videostate;
514     }
515 
516     /**
517      * Translates a {@link ImsCallProfile} {@code CALL_TYPE_*} constant into a video state.
518      * @param callType The call type.
519      * @return The video state.
520      */
getVideoStateFromCallType(int callType)521     public static int getVideoStateFromCallType(int callType) {
522         int videostate = VideoProfile.STATE_AUDIO_ONLY;
523         switch (callType) {
524             case CALL_TYPE_VT_TX:
525                 videostate = VideoProfile.STATE_TX_ENABLED;
526                 break;
527             case CALL_TYPE_VT_RX:
528                 videostate = VideoProfile.STATE_RX_ENABLED;
529                 break;
530             case CALL_TYPE_VT:
531                 videostate = VideoProfile.STATE_BIDIRECTIONAL;
532                 break;
533             case CALL_TYPE_VOICE:
534                 videostate = VideoProfile.STATE_AUDIO_ONLY;
535                 break;
536             default:
537                 videostate = VideoProfile.STATE_AUDIO_ONLY;
538                 break;
539         }
540         return videostate;
541     }
542 
543     /**
544      * Converts from the video state values defined in {@link VideoProfile}
545      * to the call types defined in {@link ImsCallProfile}.
546      *
547      * @param videoState The video state.
548      * @return The call type.
549      */
getCallTypeFromVideoState(int videoState)550     public static int getCallTypeFromVideoState(int videoState) {
551         boolean videoTx = isVideoStateSet(videoState, VideoProfile.STATE_TX_ENABLED);
552         boolean videoRx = isVideoStateSet(videoState, VideoProfile.STATE_RX_ENABLED);
553         boolean isPaused = isVideoStateSet(videoState, VideoProfile.STATE_PAUSED);
554         if (isPaused) {
555             return ImsCallProfile.CALL_TYPE_VT_NODIR;
556         } else if (videoTx && !videoRx) {
557             return ImsCallProfile.CALL_TYPE_VT_TX;
558         } else if (!videoTx && videoRx) {
559             return ImsCallProfile.CALL_TYPE_VT_RX;
560         } else if (videoTx && videoRx) {
561             return ImsCallProfile.CALL_TYPE_VT;
562         }
563         return ImsCallProfile.CALL_TYPE_VOICE;
564     }
565 
566     /**
567      * Badly named old method, kept for compatibility.
568      * See {@link #presentationToOir(int)}.
569      * @hide
570      */
presentationToOIR(int presentation)571     public static int presentationToOIR(int presentation) {
572         switch (presentation) {
573             case PhoneConstants.PRESENTATION_RESTRICTED:
574                 return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
575             case PhoneConstants.PRESENTATION_ALLOWED:
576                 return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
577             case PhoneConstants.PRESENTATION_PAYPHONE:
578                 return ImsCallProfile.OIR_PRESENTATION_PAYPHONE;
579             case PhoneConstants.PRESENTATION_UNKNOWN:
580                 return ImsCallProfile.OIR_PRESENTATION_UNKNOWN;
581             default:
582                 return ImsCallProfile.OIR_DEFAULT;
583         }
584     }
585 
586     /**
587      * Translate presentation value to OIR value
588      * @param presentation
589      * @return OIR values
590      */
presentationToOir(int presentation)591     public static int presentationToOir(int presentation) {
592         return presentationToOIR(presentation);
593     }
594 
595     /**
596      * Translate OIR value to presentation value
597      * @param oir value
598      * @return presentation value
599      * @hide
600      */
OIRToPresentation(int oir)601     public static int OIRToPresentation(int oir) {
602         switch(oir) {
603             case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
604                 return PhoneConstants.PRESENTATION_RESTRICTED;
605             case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
606                 return PhoneConstants.PRESENTATION_ALLOWED;
607             case ImsCallProfile.OIR_PRESENTATION_PAYPHONE:
608                 return PhoneConstants.PRESENTATION_PAYPHONE;
609             case ImsCallProfile.OIR_PRESENTATION_UNKNOWN:
610                 return PhoneConstants.PRESENTATION_UNKNOWN;
611             default:
612                 return PhoneConstants.PRESENTATION_UNKNOWN;
613         }
614     }
615 
616     /**
617      * Checks if video call is paused
618      * @return true if call is video paused
619      */
isVideoPaused()620     public boolean isVideoPaused() {
621         return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE;
622     }
623 
624     /**
625      * Determines if the {@link ImsCallProfile} represents a video call.
626      *
627      * @return {@code true} if the profile is for a video call, {@code false} otherwise.
628      */
isVideoCall()629     public boolean isVideoCall() {
630         return VideoProfile.isVideo(getVideoStateFromCallType(mCallType));
631     }
632 
633     /**
634      * Cleanses a {@link Bundle} to ensure that it contains only data of type:
635      * 1. Primitive data types (e.g. int, bool, and other values determined by
636      * {@link android.os.PersistableBundle#isValidType(Object)}).
637      * 2. Other Bundles.
638      * 3. {@link Parcelable} objects in the {@code android.*} namespace.
639      * @param extras the source {@link Bundle}
640      * @return where all elements are valid types the source {@link Bundle} is returned unmodified,
641      *      otherwise a copy of the {@link Bundle} with the invalid elements is returned.
642      */
maybeCleanseExtras(Bundle extras)643     private Bundle maybeCleanseExtras(Bundle extras) {
644         if (extras == null) {
645             return null;
646         }
647 
648         int startSize = extras.size();
649         Bundle filtered = extras.filterValues();
650         int endSize = filtered.size();
651         if (startSize != endSize) {
652             Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
653                     + "removed - only primitive types and system parcelables are permitted.");
654         }
655         return filtered;
656     }
657 
658     /**
659      * Determines if a video state is set in a video state bit-mask.
660      *
661      * @param videoState The video state bit mask.
662      * @param videoStateToCheck The particular video state to check.
663      * @return True if the video state is set in the bit-mask.
664      */
isVideoStateSet(int videoState, int videoStateToCheck)665     private static boolean isVideoStateSet(int videoState, int videoStateToCheck) {
666         return (videoState & videoStateToCheck) == videoStateToCheck;
667     }
668 }
669