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