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.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.annotation.UnsupportedAppUsage;
23 import android.os.Bundle;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.telecom.VideoProfile;
27 import android.telephony.emergency.EmergencyNumber;
28 import android.telephony.emergency.EmergencyNumber.EmergencyCallRouting;
29 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
30 import android.util.Log;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.internal.telephony.PhoneConstants;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 /**
41  * Parcelable object to handle IMS call profile.
42  * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
43  * It provides the service and call type, the additional information related to the call.
44  *
45  * @hide
46  */
47 @SystemApi
48 public final class ImsCallProfile implements Parcelable {
49     private static final String TAG = "ImsCallProfile";
50 
51     /**
52      * Service types
53      */
54     /**
55      * It is for a special case. It helps that the application can make a call
56      * without IMS connection (not registered).
57      * In the moment of the call initiation, the device try to connect to the IMS network
58      * and initiates the call.
59      */
60     public static final int SERVICE_TYPE_NONE = 0;
61     /**
62      * It is a default type and can be selected when the device is connected to the IMS network.
63      */
64     public static final int SERVICE_TYPE_NORMAL = 1;
65     /**
66      * It is for an emergency call.
67      */
68     public static final int SERVICE_TYPE_EMERGENCY = 2;
69 
70     /**
71      * Call types
72      */
73     /**
74      * IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
75      */
76     public static final int CALL_TYPE_VOICE_N_VIDEO = 1;
77     /**
78      * IR.92 (Voice only)
79      */
80     public static final int CALL_TYPE_VOICE = 2;
81     /**
82      * VT to support IR.92 & IR.94 (voice + video upgrade/downgrade)
83      */
84     public static final int CALL_TYPE_VIDEO_N_VOICE = 3;
85     /**
86      * Video Telephony (audio / video two way)
87      */
88     public static final int CALL_TYPE_VT = 4;
89     /**
90      * Video Telephony (audio two way / video TX one way)
91      */
92     public static final int CALL_TYPE_VT_TX = 5;
93     /**
94      * Video Telephony (audio two way / video RX one way)
95      */
96     public static final int CALL_TYPE_VT_RX = 6;
97     /**
98      * Video Telephony (audio two way / video inactive)
99      */
100     public static final int CALL_TYPE_VT_NODIR = 7;
101     /**
102      * VideoShare (video two way)
103      */
104     public static final int CALL_TYPE_VS = 8;
105     /**
106      * VideoShare (video TX one way)
107      */
108     public static final int CALL_TYPE_VS_TX = 9;
109     /**
110      * VideoShare (video RX one way)
111      */
112     public static final int CALL_TYPE_VS_RX = 10;
113 
114     /**
115      * Extra properties for IMS call.
116      */
117     /**
118      * Boolean extra properties - "true" / "false"
119      *  conference : Indicates if the session is for the conference call or not.
120      *  e_call : Indicates if the session is for the emergency call or not.
121      *  vms : Indicates if the session is connected to the voice mail system or not.
122      *  call_mode_changeable : Indicates if the session is able to upgrade/downgrade
123      *      the video during voice call.
124      *  conference_avail : Indicates if the session can be extended to the conference.
125      */
126     /**
127      * @hide
128      */
129     public static final String EXTRA_CONFERENCE = "conference";
130 
131     /**
132      * Boolean extra property set on an {@link ImsCallProfile} to indicate that this call is an
133      * emergency call.  The {@link ImsService} sets this on a call to indicate that the network has
134      * identified the call as an emergency call.
135      */
136     public static final String EXTRA_EMERGENCY_CALL = "e_call";
137 
138     /**
139      * @hide
140      */
141     public static final String EXTRA_VMS = "vms";
142     /**
143      * @hide
144      */
145     public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
146     /**
147      * @hide
148      */
149     public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
150 
151     // Extra string for internal use only. OEMs should not use
152     // this for packing extras.
153     /**
154      * @hide
155      */
156     public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
157 
158     /**
159      * Rule for originating identity (number) presentation, MO/MT.
160      *      {@link ImsCallProfile#OIR_DEFAULT}
161      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
162      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
163      */
164     public static final String EXTRA_OIR = "oir";
165     /**
166      * Rule for calling name presentation
167      *      {@link ImsCallProfile#OIR_DEFAULT}
168      *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
169      *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
170      */
171     public static final String EXTRA_CNAP = "cnap";
172     /**
173      * To identify the Ims call type, MO
174      *      {@link ImsCallProfile#DIALSTRING_NORMAL}
175      *      {@link ImsCallProfile#DIALSTRING_SS_CONF}
176      *      {@link ImsCallProfile#DIALSTRING_USSD}
177      */
178     public static final String EXTRA_DIALSTRING = "dialstring";
179 
180     /**
181      * Values for EXTRA_OIR / EXTRA_CNAP
182      */
183     /**
184      * Default presentation for Originating Identity.
185      */
186     public static final int OIR_DEFAULT = 0;    // "user subscription default value"
187     /**
188      * Restricted presentation for Originating Identity.
189      */
190     public static final int OIR_PRESENTATION_RESTRICTED = 1;
191     /**
192      * Not restricted presentation for Originating Identity.
193      */
194     public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
195     /**
196      * Presentation unknown for Originating Identity.
197      */
198     public static final int OIR_PRESENTATION_UNKNOWN = 3;
199     /**
200      * Payphone presentation for Originating Identity.
201      */
202     public static final int OIR_PRESENTATION_PAYPHONE = 4;
203 
204     //Values for EXTRA_DIALSTRING
205     /**
206      * A default or normal normal call.
207      */
208     public static final int DIALSTRING_NORMAL = 0;
209     /**
210      * Call for SIP-based user configuration
211      */
212     public static final int DIALSTRING_SS_CONF = 1;
213     /**
214      * Call for USSD message
215      */
216     public static final int DIALSTRING_USSD = 2;
217 
218     /**
219      * Call is not restricted on peer side and High Definition media is supported
220      */
221     public static final int CALL_RESTRICT_CAUSE_NONE = 0;
222 
223     /**
224      * High Definition media is not supported on the peer side due to the Radio Access Technology
225      * (RAT) it is are connected to.
226      */
227     public static final int CALL_RESTRICT_CAUSE_RAT = 1;
228 
229     /**
230      * The service has been disabled on the peer side.
231      */
232     public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
233 
234     /**
235      * High definition media is not currently supported.
236      */
237     public static final int CALL_RESTRICT_CAUSE_HD = 3;
238 
239     /**@hide*/
240     @Retention(RetentionPolicy.SOURCE)
241     @IntDef(prefix = "CALL_RESTRICT_CAUSE_", value = {
242             CALL_RESTRICT_CAUSE_NONE,
243             CALL_RESTRICT_CAUSE_RAT,
244             CALL_RESTRICT_CAUSE_DISABLED,
245             CALL_RESTRICT_CAUSE_HD
246     })
247     public @interface CallRestrictCause {}
248 
249     /**
250      * String extra properties
251      *  oi : Originating identity (number), MT only
252      *  cna : Calling name
253      *  ussd : For network-initiated USSD, MT only
254      *  remote_uri : Connected user identity (it can be used for the conference)
255      *  ChildNum: Child number info.
256      *  Codec: Codec info.
257      *  DisplayText: Display text for the call.
258      *  AdditionalCallInfo: Additional call info.
259      *  CallPull: Boolean value specifying if the call is a pulled call.
260      */
261     public static final String EXTRA_OI = "oi";
262     public static final String EXTRA_CNA = "cna";
263     public static final String EXTRA_USSD = "ussd";
264     public static final String EXTRA_REMOTE_URI = "remote_uri";
265     public static final String EXTRA_CHILD_NUMBER = "ChildNum";
266     public static final String EXTRA_CODEC = "Codec";
267     public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
268     public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
269     public static final String EXTRA_IS_CALL_PULL = "CallPull";
270 
271     /**
272      * String extra property
273      *  Containing fields from the SIP INVITE message for an IMS call
274      */
275     public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS =
276                                   "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
277 
278     /**
279      * Extra key which the RIL can use to indicate the radio technology used for a call.
280      * Valid values are:
281      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE},
282      * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}, and the other defined
283      * {@code RIL_RADIO_TECHNOLOGY_*} constants.
284      * Note: Despite the fact the {@link android.telephony.ServiceState} values are integer
285      * constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
286      * "14" vs (int) 14).
287      * Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
288      *      updateImsCallRatFromExtras(Bundle)} to determine whether to set the
289      * {@link android.telecom.TelecomManager#EXTRA_CALL_NETWORK_TYPE} extra value and
290      * {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
291      */
292     public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
293 
294     /**
295      * Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'.  Used to ensure
296      * compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
297      * extra key.  Should be removed when the non-compliant modems are fixed.
298      * @hide
299      */
300     public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
301 
302     /** @hide */
303     public int mServiceType;
304     /** @hide */
305     @UnsupportedAppUsage
306     public int mCallType;
307     /** @hide */
308     @UnsupportedAppUsage
309     public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
310 
311     /**
312      * The emergency service categories, only valid if {@link #getServiceType} returns
313      * {@link #SERVICE_TYPE_EMERGENCY}
314      *
315      * If valid, the value is the bitwise-OR combination of the following constants:
316      * <ol>
317      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
318      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
319      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
320      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
321      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
322      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
323      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
324      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
325      * </ol>
326      *
327      * Reference: 3gpp 23.167, Section 6 - Functional description;
328      *            3gpp 22.101, Section 10 - Emergency Calls.
329      */
330     private @EmergencyServiceCategories int mEmergencyServiceCategories =
331             EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
332 
333     /**
334      * The emergency Uniform Resource Names (URN), only valid if {@link #getServiceType} returns
335      * {@link #SERVICE_TYPE_EMERGENCY}.
336      *
337      * Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
338      *            3gpp 22.101, Section 10 - Emergency Calls.
339      */
340     private List<String> mEmergencyUrns = new ArrayList<>();
341 
342     /**
343      * The emergency call routing, only valid if {@link #getServiceType} returns
344      * {@link #SERVICE_TYPE_EMERGENCY}
345      *
346      * If valid, the value is any of the following constants:
347      * <ol>
348      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
349      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
350      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
351      * </ol>
352      */
353     private @EmergencyCallRouting int mEmergencyCallRouting =
354             EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
355 
356     /** Indicates if the call is for testing purpose */
357     private boolean mEmergencyCallTesting = false;
358 
359     /** Indicates if we have known the intent of the user for the call is emergency */
360     private boolean mHasKnownUserIntentEmergency = false;
361 
362     /**
363      * Extras associated with this {@link ImsCallProfile}.
364      * <p>
365      * Valid data types include:
366      * <ul>
367      *     <li>{@link Integer} (and int)</li>
368      *     <li>{@link Long} (and long)</li>
369      *     <li>{@link Double} (and double)</li>
370      *     <li>{@link String}</li>
371      *     <li>{@code int[]}</li>
372      *     <li>{@code long[]}</li>
373      *     <li>{@code double[]}</li>
374      *     <li>{@code String[]}</li>
375      *     <li>{@link android.os.PersistableBundle}</li>
376      *     <li>{@link Boolean} (and boolean)</li>
377      *     <li>{@code boolean[]}</li>
378      *     <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
379      * </ul>
380      * <p>
381      * Invalid types will be removed when the {@link ImsCallProfile} is parceled for transmit across
382      * a {@link android.os.Binder}.
383      */
384     /** @hide */
385     @UnsupportedAppUsage
386     public Bundle mCallExtras;
387     /** @hide */
388     @UnsupportedAppUsage
389     public ImsStreamMediaProfile mMediaProfile;
390 
391     /** @hide */
ImsCallProfile(Parcel in)392     public ImsCallProfile(Parcel in) {
393         readFromParcel(in);
394     }
395 
396     /**
397      * Default Constructor that initializes the call profile with service type
398      * {@link #SERVICE_TYPE_NORMAL} and call type {@link #CALL_TYPE_VIDEO_N_VOICE}
399      */
ImsCallProfile()400     public ImsCallProfile() {
401         mServiceType = SERVICE_TYPE_NORMAL;
402         mCallType = CALL_TYPE_VOICE_N_VIDEO;
403         mCallExtras = new Bundle();
404         mMediaProfile = new ImsStreamMediaProfile();
405     }
406 
407     /**
408      * Constructor.
409      *
410      * @param serviceType the service type for the call. Can be one of the following:
411      *                    {@link #SERVICE_TYPE_NONE},
412      *                    {@link #SERVICE_TYPE_NORMAL},
413      *                    {@link #SERVICE_TYPE_EMERGENCY}
414      * @param callType the call type. Can be one of the following:
415      *                 {@link #CALL_TYPE_VOICE_N_VIDEO},
416      *                 {@link #CALL_TYPE_VOICE},
417      *                 {@link #CALL_TYPE_VIDEO_N_VOICE},
418      *                 {@link #CALL_TYPE_VT},
419      *                 {@link #CALL_TYPE_VT_TX},
420      *                 {@link #CALL_TYPE_VT_RX},
421      *                 {@link #CALL_TYPE_VT_NODIR},
422      *                 {@link #CALL_TYPE_VS},
423      *                 {@link #CALL_TYPE_VS_TX},
424      *                 {@link #CALL_TYPE_VS_RX}
425      */
ImsCallProfile(int serviceType, int callType)426     public ImsCallProfile(int serviceType, int callType) {
427         mServiceType = serviceType;
428         mCallType = callType;
429         mCallExtras = new Bundle();
430         mMediaProfile = new ImsStreamMediaProfile();
431     }
432 
433     /**
434      * Constructor.
435      *
436      * @param serviceType the service type for the call. Can be one of the following:
437      *                    {@link #SERVICE_TYPE_NONE},
438      *                    {@link #SERVICE_TYPE_NORMAL},
439      *                    {@link #SERVICE_TYPE_EMERGENCY}
440      * @param callType the call type. Can be one of the following:
441      *                 {@link #CALL_TYPE_VOICE_N_VIDEO},
442      *                 {@link #CALL_TYPE_VOICE},
443      *                 {@link #CALL_TYPE_VIDEO_N_VOICE},
444      *                 {@link #CALL_TYPE_VT},
445      *                 {@link #CALL_TYPE_VT_TX},
446      *                 {@link #CALL_TYPE_VT_RX},
447      *                 {@link #CALL_TYPE_VT_NODIR},
448      *                 {@link #CALL_TYPE_VS},
449      *                 {@link #CALL_TYPE_VS_TX},
450      *                 {@link #CALL_TYPE_VS_RX}
451      * @param callExtras A bundle with the call extras.
452      * @param mediaProfile The IMS stream media profile.
453      */
ImsCallProfile(int serviceType, int callType, Bundle callExtras, ImsStreamMediaProfile mediaProfile)454     public ImsCallProfile(int serviceType, int callType, Bundle callExtras,
455             ImsStreamMediaProfile mediaProfile) {
456         mServiceType = serviceType;
457         mCallType = callType;
458         mCallExtras = callExtras;
459         mMediaProfile = mediaProfile;
460     }
461 
getCallExtra(String name)462     public String getCallExtra(String name) {
463         return getCallExtra(name, "");
464     }
465 
getCallExtra(String name, String defaultValue)466     public String getCallExtra(String name, String defaultValue) {
467         if (mCallExtras == null) {
468             return defaultValue;
469         }
470 
471         return mCallExtras.getString(name, defaultValue);
472     }
473 
getCallExtraBoolean(String name)474     public boolean getCallExtraBoolean(String name) {
475         return getCallExtraBoolean(name, false);
476     }
477 
getCallExtraBoolean(String name, boolean defaultValue)478     public boolean getCallExtraBoolean(String name, boolean defaultValue) {
479         if (mCallExtras == null) {
480             return defaultValue;
481         }
482 
483         return mCallExtras.getBoolean(name, defaultValue);
484     }
485 
getCallExtraInt(String name)486     public int getCallExtraInt(String name) {
487         return getCallExtraInt(name, -1);
488     }
489 
getCallExtraInt(String name, int defaultValue)490     public int getCallExtraInt(String name, int defaultValue) {
491         if (mCallExtras == null) {
492             return defaultValue;
493         }
494 
495         return mCallExtras.getInt(name, defaultValue);
496     }
497 
setCallExtra(String name, String value)498     public void setCallExtra(String name, String value) {
499         if (mCallExtras != null) {
500             mCallExtras.putString(name, value);
501         }
502     }
503 
setCallExtraBoolean(String name, boolean value)504     public void setCallExtraBoolean(String name, boolean value) {
505         if (mCallExtras != null) {
506             mCallExtras.putBoolean(name, value);
507         }
508     }
509 
setCallExtraInt(String name, int value)510     public void setCallExtraInt(String name, int value) {
511         if (mCallExtras != null) {
512             mCallExtras.putInt(name, value);
513         }
514     }
515 
516     /**
517      * Set the call restrict cause, which provides the reason why a call has been restricted from
518      * using High Definition media.
519      */
setCallRestrictCause(@allRestrictCause int cause)520     public void setCallRestrictCause(@CallRestrictCause int cause) {
521         mRestrictCause = cause;
522     }
523 
updateCallType(ImsCallProfile profile)524     public void updateCallType(ImsCallProfile profile) {
525         mCallType = profile.mCallType;
526     }
527 
updateCallExtras(ImsCallProfile profile)528     public void updateCallExtras(ImsCallProfile profile) {
529         mCallExtras.clear();
530         mCallExtras = (Bundle) profile.mCallExtras.clone();
531     }
532 
533     /**
534      * Updates the media profile for the call.
535      *
536      * @param profile Call profile with new media profile.
537      */
updateMediaProfile(ImsCallProfile profile)538     public void updateMediaProfile(ImsCallProfile profile) {
539         mMediaProfile = profile.mMediaProfile;
540     }
541 
542 
543     @Override
toString()544     public String toString() {
545         return "{ serviceType=" + mServiceType
546                 + ", callType=" + mCallType
547                 + ", restrictCause=" + mRestrictCause
548                 + ", mediaProfile=" + mMediaProfile.toString()
549                 + ", emergencyServiceCategories=" + mEmergencyServiceCategories
550                 + ", emergencyUrns=" + mEmergencyUrns
551                 + ", emergencyCallRouting=" + mEmergencyCallRouting
552                 + ", emergencyCallTesting=" + mEmergencyCallTesting
553                 + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }";
554     }
555 
556     @Override
describeContents()557     public int describeContents() {
558         return 0;
559     }
560 
561     @Override
writeToParcel(Parcel out, int flags)562     public void writeToParcel(Parcel out, int flags) {
563         Bundle filteredExtras = maybeCleanseExtras(mCallExtras);
564         out.writeInt(mServiceType);
565         out.writeInt(mCallType);
566         out.writeBundle(filteredExtras);
567         out.writeParcelable(mMediaProfile, 0);
568         out.writeInt(mEmergencyServiceCategories);
569         out.writeStringList(mEmergencyUrns);
570         out.writeInt(mEmergencyCallRouting);
571         out.writeBoolean(mEmergencyCallTesting);
572         out.writeBoolean(mHasKnownUserIntentEmergency);
573     }
574 
readFromParcel(Parcel in)575     private void readFromParcel(Parcel in) {
576         mServiceType = in.readInt();
577         mCallType = in.readInt();
578         mCallExtras = in.readBundle();
579         mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
580         mEmergencyServiceCategories = in.readInt();
581         mEmergencyUrns = in.createStringArrayList();
582         mEmergencyCallRouting = in.readInt();
583         mEmergencyCallTesting = in.readBoolean();
584         mHasKnownUserIntentEmergency = in.readBoolean();
585     }
586 
587     public static final @android.annotation.NonNull Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
588         @Override
589         public ImsCallProfile createFromParcel(Parcel in) {
590             return new ImsCallProfile(in);
591         }
592 
593         @Override
594         public ImsCallProfile[] newArray(int size) {
595             return new ImsCallProfile[size];
596         }
597     };
598 
getServiceType()599     public int getServiceType() {
600         return mServiceType;
601     }
602 
getCallType()603     public int getCallType() {
604         return mCallType;
605     }
606 
607     /**
608      * @return The call restrict cause, which provides the reason why a call has been restricted
609      * from using High Definition media.
610      */
getRestrictCause()611     public @CallRestrictCause int getRestrictCause() {
612         return mRestrictCause;
613     }
614 
getCallExtras()615     public Bundle getCallExtras() {
616         return mCallExtras;
617     }
618 
getMediaProfile()619     public ImsStreamMediaProfile getMediaProfile() {
620         return mMediaProfile;
621     }
622 
623     /**
624      * Converts from the call types defined in {@link ImsCallProfile} to the
625      * video state values defined in {@link VideoProfile}.
626      *
627      * @param callProfile The call profile.
628      * @return The video state.
629      */
getVideoStateFromImsCallProfile(ImsCallProfile callProfile)630     public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) {
631         int videostate = getVideoStateFromCallType(callProfile.mCallType);
632         if (callProfile.isVideoPaused() && !VideoProfile.isAudioOnly(videostate)) {
633             videostate |= VideoProfile.STATE_PAUSED;
634         } else {
635             videostate &= ~VideoProfile.STATE_PAUSED;
636         }
637         return videostate;
638     }
639 
640     /**
641      * Translates a {@link ImsCallProfile} {@code CALL_TYPE_*} constant into a video state.
642      * @param callType The call type.
643      * @return The video state.
644      */
getVideoStateFromCallType(int callType)645     public static int getVideoStateFromCallType(int callType) {
646         int videostate = VideoProfile.STATE_AUDIO_ONLY;
647         switch (callType) {
648             case CALL_TYPE_VT_TX:
649                 videostate = VideoProfile.STATE_TX_ENABLED;
650                 break;
651             case CALL_TYPE_VT_RX:
652                 videostate = VideoProfile.STATE_RX_ENABLED;
653                 break;
654             case CALL_TYPE_VT:
655                 videostate = VideoProfile.STATE_BIDIRECTIONAL;
656                 break;
657             case CALL_TYPE_VOICE:
658                 videostate = VideoProfile.STATE_AUDIO_ONLY;
659                 break;
660             default:
661                 videostate = VideoProfile.STATE_AUDIO_ONLY;
662                 break;
663         }
664         return videostate;
665     }
666 
667     /**
668      * Converts from the video state values defined in {@link VideoProfile}
669      * to the call types defined in {@link ImsCallProfile}.
670      *
671      * @param videoState The video state.
672      * @return The call type.
673      */
getCallTypeFromVideoState(int videoState)674     public static int getCallTypeFromVideoState(int videoState) {
675         boolean videoTx = isVideoStateSet(videoState, VideoProfile.STATE_TX_ENABLED);
676         boolean videoRx = isVideoStateSet(videoState, VideoProfile.STATE_RX_ENABLED);
677         boolean isPaused = isVideoStateSet(videoState, VideoProfile.STATE_PAUSED);
678         if (isPaused) {
679             return ImsCallProfile.CALL_TYPE_VT_NODIR;
680         } else if (videoTx && !videoRx) {
681             return ImsCallProfile.CALL_TYPE_VT_TX;
682         } else if (!videoTx && videoRx) {
683             return ImsCallProfile.CALL_TYPE_VT_RX;
684         } else if (videoTx && videoRx) {
685             return ImsCallProfile.CALL_TYPE_VT;
686         }
687         return ImsCallProfile.CALL_TYPE_VOICE;
688     }
689 
690     /**
691      * Badly named old method, kept for compatibility.
692      * See {@link #presentationToOir(int)}.
693      * @hide
694      */
695     @UnsupportedAppUsage
presentationToOIR(int presentation)696     public static int presentationToOIR(int presentation) {
697         switch (presentation) {
698             case PhoneConstants.PRESENTATION_RESTRICTED:
699                 return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
700             case PhoneConstants.PRESENTATION_ALLOWED:
701                 return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
702             case PhoneConstants.PRESENTATION_PAYPHONE:
703                 return ImsCallProfile.OIR_PRESENTATION_PAYPHONE;
704             case PhoneConstants.PRESENTATION_UNKNOWN:
705                 return ImsCallProfile.OIR_PRESENTATION_UNKNOWN;
706             default:
707                 return ImsCallProfile.OIR_DEFAULT;
708         }
709     }
710 
711     /**
712      * Translate presentation value to OIR value
713      * @param presentation
714      * @return OIR values
715      */
presentationToOir(int presentation)716     public static int presentationToOir(int presentation) {
717         return presentationToOIR(presentation);
718     }
719 
720     /**
721      * Translate OIR value to presentation value
722      * @param oir value
723      * @return presentation value
724      * @hide
725      */
OIRToPresentation(int oir)726     public static int OIRToPresentation(int oir) {
727         switch(oir) {
728             case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
729                 return PhoneConstants.PRESENTATION_RESTRICTED;
730             case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
731                 return PhoneConstants.PRESENTATION_ALLOWED;
732             case ImsCallProfile.OIR_PRESENTATION_PAYPHONE:
733                 return PhoneConstants.PRESENTATION_PAYPHONE;
734             case ImsCallProfile.OIR_PRESENTATION_UNKNOWN:
735                 return PhoneConstants.PRESENTATION_UNKNOWN;
736             default:
737                 return PhoneConstants.PRESENTATION_UNKNOWN;
738         }
739     }
740 
741     /**
742      * Checks if video call is paused
743      * @return true if call is video paused
744      */
isVideoPaused()745     public boolean isVideoPaused() {
746         return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE;
747     }
748 
749     /**
750      * Determines if the {@link ImsCallProfile} represents a video call.
751      *
752      * @return {@code true} if the profile is for a video call, {@code false} otherwise.
753      */
isVideoCall()754     public boolean isVideoCall() {
755         return VideoProfile.isVideo(getVideoStateFromCallType(mCallType));
756     }
757 
758     /**
759      * Cleanses a {@link Bundle} to ensure that it contains only data of type:
760      * 1. Primitive data types (e.g. int, bool, and other values determined by
761      * {@link android.os.PersistableBundle#isValidType(Object)}).
762      * 2. Other Bundles.
763      * 3. {@link Parcelable} objects in the {@code android.*} namespace.
764      * @param extras the source {@link Bundle}
765      * @return where all elements are valid types the source {@link Bundle} is returned unmodified,
766      *      otherwise a copy of the {@link Bundle} with the invalid elements is returned.
767      */
maybeCleanseExtras(Bundle extras)768     private Bundle maybeCleanseExtras(Bundle extras) {
769         if (extras == null) {
770             return null;
771         }
772 
773         int startSize = extras.size();
774         Bundle filtered = extras.filterValues();
775         int endSize = filtered.size();
776         if (startSize != endSize) {
777             Log.i(TAG, "maybeCleanseExtras: " + (startSize - endSize) + " extra values were "
778                     + "removed - only primitive types and system parcelables are permitted.");
779         }
780         return filtered;
781     }
782 
783     /**
784      * Determines if a video state is set in a video state bit-mask.
785      *
786      * @param videoState The video state bit mask.
787      * @param videoStateToCheck The particular video state to check.
788      * @return True if the video state is set in the bit-mask.
789      */
isVideoStateSet(int videoState, int videoStateToCheck)790     private static boolean isVideoStateSet(int videoState, int videoStateToCheck) {
791         return (videoState & videoStateToCheck) == videoStateToCheck;
792     }
793 
794     /**
795      * Set the emergency number information. The set value is valid
796      * only if {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
797      *
798      * Reference: 3gpp 23.167, Section 6 - Functional description;
799      *            3gpp 24.503, Section 5.1.6.8.1 - General;
800      *            3gpp 22.101, Section 10 - Emergency Calls.
801      *
802      * @hide
803      */
setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency)804     public void setEmergencyCallInfo(EmergencyNumber num, boolean hasKnownUserIntentEmergency) {
805         setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
806         setEmergencyUrns(num.getEmergencyUrns());
807         setEmergencyCallRouting(num.getEmergencyCallRouting());
808         setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
809                 == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
810         setHasKnownUserIntentEmergency(hasKnownUserIntentEmergency);
811     }
812 
813     /**
814      * Set the emergency service categories. The set value is valid only if
815      * {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
816      *
817      * If valid, the value is the bitwise-OR combination of the following constants:
818      * <ol>
819      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
820      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
821      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
822      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
823      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
824      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
825      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
826      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
827      * </ol>
828      *
829      * Reference: 3gpp 23.167, Section 6 - Functional description;
830      *            3gpp 22.101, Section 10 - Emergency Calls.
831      */
832     @VisibleForTesting
setEmergencyServiceCategories( @mergencyServiceCategories int emergencyServiceCategories)833     public void setEmergencyServiceCategories(
834             @EmergencyServiceCategories int emergencyServiceCategories) {
835         mEmergencyServiceCategories = emergencyServiceCategories;
836     }
837 
838     /**
839      * Set the emergency Uniform Resource Names (URN), only valid if {@link #getServiceType}
840      * returns {@link #SERVICE_TYPE_EMERGENCY}.
841      *
842      * Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
843      *            3gpp 22.101, Section 10 - Emergency Calls.
844      */
845     @VisibleForTesting
setEmergencyUrns(@onNull List<String> emergencyUrns)846     public void setEmergencyUrns(@NonNull List<String> emergencyUrns) {
847         mEmergencyUrns = emergencyUrns;
848     }
849 
850     /**
851      * Set the emergency call routing, only valid if {@link #getServiceType} returns
852      * {@link #SERVICE_TYPE_EMERGENCY}
853      *
854      * If valid, the value is any of the following constants:
855      * <ol>
856      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
857      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
858      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
859      * </ol>
860      */
861     @VisibleForTesting
setEmergencyCallRouting(@mergencyCallRouting int emergencyCallRouting)862     public void setEmergencyCallRouting(@EmergencyCallRouting int emergencyCallRouting) {
863         mEmergencyCallRouting = emergencyCallRouting;
864     }
865 
866     /**
867      * Set if this is for testing emergency call, only valid if {@link #getServiceType} returns
868      * {@link #SERVICE_TYPE_EMERGENCY}.
869      */
870     @VisibleForTesting
setEmergencyCallTesting(boolean isTesting)871     public void setEmergencyCallTesting(boolean isTesting) {
872         mEmergencyCallTesting = isTesting;
873     }
874 
875     /**
876      * Set if we have known the user intent of the call is emergency.
877      *
878      * This is only used to specify when the dialed number is ambiguous when it can be identified
879      * as both emergency number and any other non-emergency number; e.g. in some situation, 611
880      * could be both an emergency number in a country and a non-emergency number of a carrier's
881      * customer service hotline.
882      */
883     @VisibleForTesting
setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency)884     public void setHasKnownUserIntentEmergency(boolean hasKnownUserIntentEmergency) {
885         mHasKnownUserIntentEmergency = hasKnownUserIntentEmergency;
886     }
887 
888     /**
889      * Get the emergency service categories, only valid if {@link #getServiceType} returns
890      * {@link #SERVICE_TYPE_EMERGENCY}
891      *
892      * @return the emergency service categories,
893      *
894      * If valid, the value is the bitwise-OR combination of the following constants:
895      * <ol>
896      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
897      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
898      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
899      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
900      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
901      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
902      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
903      * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
904      * </ol>
905      *
906      * Reference: 3gpp 23.167, Section 6 - Functional description;
907      *            3gpp 22.101, Section 10 - Emergency Calls.
908      */
getEmergencyServiceCategories()909     public @EmergencyServiceCategories int getEmergencyServiceCategories() {
910         return mEmergencyServiceCategories;
911     }
912 
913     /**
914      * Get the emergency Uniform Resource Names (URN), only valid if {@link #getServiceType}
915      * returns {@link #SERVICE_TYPE_EMERGENCY}.
916      *
917      * Reference: 3gpp 24.503, Section 5.1.6.8.1 - General;
918      *            3gpp 22.101, Section 10 - Emergency Calls.
919      */
getEmergencyUrns()920     public @NonNull List<String> getEmergencyUrns() {
921         return mEmergencyUrns;
922     }
923 
924     /**
925      * Get the emergency call routing, only valid if {@link #getServiceType} returns
926      * {@link #SERVICE_TYPE_EMERGENCY}
927      *
928      * If valid, the value is any of the following constants:
929      * <ol>
930      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_UNKNOWN} </li>
931      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_NORMAL} </li>
932      * <li>{@link EmergencyNumber#EMERGENCY_CALL_ROUTING_EMERGENCY} </li>
933      * </ol>
934      */
getEmergencyCallRouting()935     public @EmergencyCallRouting int getEmergencyCallRouting() {
936         return mEmergencyCallRouting;
937     }
938 
939     /**
940      * Get if the emergency call is for testing purpose.
941      */
isEmergencyCallTesting()942     public boolean isEmergencyCallTesting() {
943         return mEmergencyCallTesting;
944     }
945 
946     /**
947      * Checks if we have known the user intent of the call is emergency.
948      *
949      * This is only used to specify when the dialed number is ambiguous when it can be identified
950      * as both emergency number and any other non-emergency number; e.g. in some situation, 611
951      * could be both an emergency number in a country and a non-emergency number of a carrier's
952      * customer service hotline.
953      */
hasKnownUserIntentEmergency()954     public boolean hasKnownUserIntentEmergency() {
955         return mHasKnownUserIntentEmergency;
956     }
957 }
958