1/*
2 * Copyright (c) 2013 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
17package com.android.ims;
18
19import android.os.Bundle;
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.telecom.VideoProfile;
23
24import com.android.internal.telephony.PhoneConstants;
25
26/**
27 * Parcelable object to handle IMS call profile.
28 * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
29 * It provides the service and call type, the additional information related to the call.
30 *
31 * @hide
32 */
33public class ImsCallProfile implements Parcelable {
34    private static final String TAG = "ImsCallProfile";
35
36    /**
37     * Service types
38     */
39    /**
40     * It is for a special case. It helps that the application can make a call
41     * without IMS connection (not registered).
42     * In the moment of the call initiation, the device try to connect to the IMS network
43     * and initiates the call.
44     */
45    public static final int SERVICE_TYPE_NONE = 0;
46    /**
47     * It is a default type and can be selected when the device is connected to the IMS network.
48     */
49    public static final int SERVICE_TYPE_NORMAL = 1;
50    /**
51     * It is for an emergency call.
52     */
53    public static final int SERVICE_TYPE_EMERGENCY = 2;
54
55    /**
56     * Call types
57     */
58    /**
59     * IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
60     */
61    public static final int CALL_TYPE_VOICE_N_VIDEO = 1;
62    /**
63     * IR.92 (Voice only)
64     */
65    public static final int CALL_TYPE_VOICE = 2;
66    /**
67     * VT to support IR.92 & IR.94 (voice + video upgrade/downgrade)
68     */
69    public static final int CALL_TYPE_VIDEO_N_VOICE = 3;
70    /**
71     * Video Telephony (audio / video two way)
72     */
73    public static final int CALL_TYPE_VT = 4;
74    /**
75     * Video Telephony (audio two way / video TX one way)
76     */
77    public static final int CALL_TYPE_VT_TX = 5;
78    /**
79     * Video Telephony (audio two way / video RX one way)
80     */
81    public static final int CALL_TYPE_VT_RX = 6;
82    /**
83     * Video Telephony (audio two way / video inactive)
84     */
85    public static final int CALL_TYPE_VT_NODIR = 7;
86    /**
87     * VideoShare (video two way)
88     */
89    public static final int CALL_TYPE_VS = 8;
90    /**
91     * VideoShare (video TX one way)
92     */
93    public static final int CALL_TYPE_VS_TX = 9;
94    /**
95     * VideoShare (video RX one way)
96     */
97    public static final int CALL_TYPE_VS_RX = 10;
98
99    /**
100     * Extra properties for IMS call.
101     */
102    /**
103     * Boolean extra properties - "true" / "false"
104     *  conference : Indicates if the session is for the conference call or not.
105     *  e_call : Indicates if the session is for the emergency call or not.
106     *  vms : Indicates if the session is connected to the voice mail system or not.
107     *  call_mode_changeable : Indicates if the session is able to upgrade/downgrade
108     *      the video during voice call.
109     *  conference_avail : Indicates if the session can be extended to the conference.
110     */
111    public static final String EXTRA_CONFERENCE = "conference";
112    public static final String EXTRA_E_CALL = "e_call";
113    public static final String EXTRA_VMS = "vms";
114    public static final String EXTRA_CALL_MODE_CHANGEABLE = "call_mode_changeable";
115    public static final String EXTRA_CONFERENCE_AVAIL = "conference_avail";
116
117    // Extra string for internal use only. OEMs should not use
118    // this for packing extras.
119    public static final String EXTRA_OEM_EXTRAS = "OemCallExtras";
120
121    /**
122     * Integer extra properties
123     *  oir : Rule for originating identity (number) presentation, MO/MT.
124     *      {@link ImsCallProfile#OIR_DEFAULT}
125     *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
126     *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
127     *  cnap : Rule for calling name presentation
128     *      {@link ImsCallProfile#OIR_DEFAULT}
129     *      {@link ImsCallProfile#OIR_PRESENTATION_RESTRICTED}
130     *      {@link ImsCallProfile#OIR_PRESENTATION_NOT_RESTRICTED}
131     *  dialstring : To identify the Ims call type, MO
132     *      {@link ImsCallProfile#DIALSTRING_NORMAL_CALL}
133     *      {@link ImsCallProfile#DIALSTRING_SS_CONF}
134     *      {@link ImsCallProfile#DIALSTRING_USSD}
135     */
136    public static final String EXTRA_OIR = "oir";
137    public static final String EXTRA_CNAP = "cnap";
138    public static final String EXTRA_DIALSTRING = "dialstring";
139
140    /**
141     * Values for EXTRA_OIR / EXTRA_CNAP
142     */
143    public static final int OIR_DEFAULT = 0;    // "user subscription default value"
144    public static final int OIR_PRESENTATION_RESTRICTED = 1;
145    public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2;
146    public static final int OIR_PRESENTATION_UNKNOWN = 3;
147    public static final int OIR_PRESENTATION_PAYPHONE = 4;
148
149    /**
150     * Values for EXTRA_DIALSTRING
151     */
152    // default (normal call)
153    public static final int DIALSTRING_NORMAL = 0;
154    // Call for SIP-based user configuration
155    public static final int DIALSTRING_SS_CONF = 1;
156    // Call for USSD message
157    public static final int DIALSTRING_USSD = 2;
158
159    /**
160     * Values for causes that restrict call types
161     */
162    // Default cause not restricted at peer and HD is supported
163    public static final int CALL_RESTRICT_CAUSE_NONE = 0;
164    // Service not supported by RAT at peer
165    public static final int CALL_RESTRICT_CAUSE_RAT = 1;
166    // Service Disabled at peer
167    public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
168    // HD is not supported
169    public static final int CALL_RESTRICT_CAUSE_HD = 3;
170
171    /**
172     * String extra properties
173     *  oi : Originating identity (number), MT only
174     *  cna : Calling name
175     *  ussd : For network-initiated USSD, MT only
176     *  remote_uri : Connected user identity (it can be used for the conference)
177     *  ChildNum: Child number info.
178     *  Codec: Codec info.
179     *  DisplayText: Display text for the call.
180     *  AdditionalCallInfo: Additional call info.
181     *  CallPull: Boolean value specifying if the call is a pulled call.
182     */
183    public static final String EXTRA_OI = "oi";
184    public static final String EXTRA_CNA = "cna";
185    public static final String EXTRA_USSD = "ussd";
186    public static final String EXTRA_REMOTE_URI = "remote_uri";
187    public static final String EXTRA_CHILD_NUMBER = "ChildNum";
188    public static final String EXTRA_CODEC = "Codec";
189    public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
190    public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
191    public static final String EXTRA_IS_CALL_PULL = "CallPull";
192
193    /**
194     * Extra key which the RIL can use to indicate the radio technology used for a call.
195     * Valid values are:
196     * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE},
197     * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}, and the other defined
198     * {@code RIL_RADIO_TECHNOLOGY_*} constants.
199     * Note: Despite the fact the {@link android.telephony.ServiceState} values are integer
200     * constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
201     * "14" vs (int) 14).
202     * Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
203     *      updateWifiStateFromExtras(Bundle)} to determine whether to set the
204     * {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
205     */
206    public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
207
208    /**
209     * Similar to {@link #EXTRA_CALL_RAT_TYPE}, except with a lowercase 'c'.  Used to ensure
210     * compatibility with modems that are non-compliant with the {@link #EXTRA_CALL_RAT_TYPE}
211     * extra key.  Should be removed when the non-compliant modems are fixed.
212     * @hide
213     */
214    public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
215
216    public int mServiceType;
217    public int mCallType;
218    public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
219    public Bundle mCallExtras;
220    public ImsStreamMediaProfile mMediaProfile;
221
222    public ImsCallProfile(Parcel in) {
223        readFromParcel(in);
224    }
225
226    public ImsCallProfile() {
227        mServiceType = SERVICE_TYPE_NORMAL;
228        mCallType = CALL_TYPE_VOICE_N_VIDEO;
229        mCallExtras = new Bundle();
230        mMediaProfile = new ImsStreamMediaProfile();
231    }
232
233    public ImsCallProfile(int serviceType, int callType) {
234        mServiceType = serviceType;
235        mCallType = callType;
236        mCallExtras = new Bundle();
237        mMediaProfile = new ImsStreamMediaProfile();
238    }
239
240    public String getCallExtra(String name) {
241        return getCallExtra(name, "");
242    }
243
244    public String getCallExtra(String name, String defaultValue) {
245        if (mCallExtras == null) {
246            return defaultValue;
247        }
248
249        return mCallExtras.getString(name, defaultValue);
250    }
251
252    public boolean getCallExtraBoolean(String name) {
253        return getCallExtraBoolean(name, false);
254    }
255
256    public boolean getCallExtraBoolean(String name, boolean defaultValue) {
257        if (mCallExtras == null) {
258            return defaultValue;
259        }
260
261        return mCallExtras.getBoolean(name, defaultValue);
262    }
263
264    public int getCallExtraInt(String name) {
265        return getCallExtraInt(name, -1);
266    }
267
268    public int getCallExtraInt(String name, int defaultValue) {
269        if (mCallExtras == null) {
270            return defaultValue;
271        }
272
273        return mCallExtras.getInt(name, defaultValue);
274    }
275
276    public void setCallExtra(String name, String value) {
277        if (mCallExtras != null) {
278            mCallExtras.putString(name, value);
279        }
280    }
281
282    public void setCallExtraBoolean(String name, boolean value) {
283        if (mCallExtras != null) {
284            mCallExtras.putBoolean(name, value);
285        }
286    }
287
288    public void setCallExtraInt(String name, int value) {
289        if (mCallExtras != null) {
290            mCallExtras.putInt(name, value);
291        }
292    }
293
294    public void updateCallType(ImsCallProfile profile) {
295        mCallType = profile.mCallType;
296    }
297
298    public void updateCallExtras(ImsCallProfile profile) {
299        mCallExtras.clear();
300        mCallExtras = (Bundle) profile.mCallExtras.clone();
301    }
302
303    @Override
304    public String toString() {
305        return "{ serviceType=" + mServiceType +
306                ", callType=" + mCallType +
307                ", restrictCause=" + mRestrictCause +
308                ", mediaProfile=" + mMediaProfile.toString() + " }";
309    }
310
311    @Override
312    public int describeContents() {
313        return 0;
314    }
315
316    @Override
317    public void writeToParcel(Parcel out, int flags) {
318        out.writeInt(mServiceType);
319        out.writeInt(mCallType);
320        out.writeParcelable(mCallExtras, 0);
321        out.writeParcelable(mMediaProfile, 0);
322    }
323
324    private void readFromParcel(Parcel in) {
325        mServiceType = in.readInt();
326        mCallType = in.readInt();
327        mCallExtras = in.readParcelable(null);
328        mMediaProfile = in.readParcelable(null);
329    }
330
331    public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
332        @Override
333        public ImsCallProfile createFromParcel(Parcel in) {
334            return new ImsCallProfile(in);
335        }
336
337        @Override
338        public ImsCallProfile[] newArray(int size) {
339            return new ImsCallProfile[size];
340        }
341    };
342
343    /**
344     * Converts from the call types defined in {@link com.android.ims.ImsCallProfile} to the
345     * video state values defined in {@link VideoProfile}.
346     *
347     * @param callProfile The call profile.
348     * @return The video state.
349     */
350    public static int getVideoStateFromImsCallProfile(ImsCallProfile callProfile) {
351        int videostate = getVideoStateFromCallType(callProfile.mCallType);
352        if (callProfile.isVideoPaused() && !VideoProfile.isAudioOnly(videostate)) {
353            videostate |= VideoProfile.STATE_PAUSED;
354        } else {
355            videostate &= ~VideoProfile.STATE_PAUSED;
356        }
357        return videostate;
358    }
359
360    /**
361     * Translates a {@link ImsCallProfile} {@code CALL_TYPE_*} constant into a video state.
362     * @param callType The call type.
363     * @return The video state.
364     */
365    public static int getVideoStateFromCallType(int callType) {
366        int videostate = VideoProfile.STATE_AUDIO_ONLY;
367        switch (callType) {
368            case CALL_TYPE_VT_TX:
369                videostate = VideoProfile.STATE_TX_ENABLED;
370                break;
371            case CALL_TYPE_VT_RX:
372                videostate = VideoProfile.STATE_RX_ENABLED;
373                break;
374            case CALL_TYPE_VT:
375                videostate = VideoProfile.STATE_BIDIRECTIONAL;
376                break;
377            case CALL_TYPE_VOICE:
378                videostate = VideoProfile.STATE_AUDIO_ONLY;
379                break;
380            default:
381                videostate = VideoProfile.STATE_AUDIO_ONLY;
382                break;
383        }
384        return videostate;
385    }
386
387    /**
388     * Converts from the video state values defined in {@link VideoProfile}
389     * to the call types defined in {@link ImsCallProfile}.
390     *
391     * @param videoState The video state.
392     * @return The call type.
393     */
394    public static int getCallTypeFromVideoState(int videoState) {
395        boolean videoTx = isVideoStateSet(videoState, VideoProfile.STATE_TX_ENABLED);
396        boolean videoRx = isVideoStateSet(videoState, VideoProfile.STATE_RX_ENABLED);
397        boolean isPaused = isVideoStateSet(videoState, VideoProfile.STATE_PAUSED);
398        if (isPaused) {
399            return ImsCallProfile.CALL_TYPE_VT_NODIR;
400        } else if (videoTx && !videoRx) {
401            return ImsCallProfile.CALL_TYPE_VT_TX;
402        } else if (!videoTx && videoRx) {
403            return ImsCallProfile.CALL_TYPE_VT_RX;
404        } else if (videoTx && videoRx) {
405            return ImsCallProfile.CALL_TYPE_VT;
406        }
407        return ImsCallProfile.CALL_TYPE_VOICE;
408    }
409
410    /**
411     * Translate presentation value to OIR value
412     * @param presentation
413     * @return OIR valuse
414     */
415    public static int presentationToOIR(int presentation) {
416        switch (presentation) {
417            case PhoneConstants.PRESENTATION_RESTRICTED:
418                return ImsCallProfile.OIR_PRESENTATION_RESTRICTED;
419            case PhoneConstants.PRESENTATION_ALLOWED:
420                return ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED;
421            case PhoneConstants.PRESENTATION_PAYPHONE:
422                return ImsCallProfile.OIR_PRESENTATION_PAYPHONE;
423            case PhoneConstants.PRESENTATION_UNKNOWN:
424                return ImsCallProfile.OIR_PRESENTATION_UNKNOWN;
425            default:
426                return ImsCallProfile.OIR_DEFAULT;
427        }
428    }
429
430    /**
431     * Translate OIR value to presentation value
432     * @param oir value
433     * @return presentation value
434     */
435    public static int OIRToPresentation(int oir) {
436        switch(oir) {
437            case ImsCallProfile.OIR_PRESENTATION_RESTRICTED:
438                return PhoneConstants.PRESENTATION_RESTRICTED;
439            case ImsCallProfile.OIR_PRESENTATION_NOT_RESTRICTED:
440                return PhoneConstants.PRESENTATION_ALLOWED;
441            case ImsCallProfile.OIR_PRESENTATION_PAYPHONE:
442                return PhoneConstants.PRESENTATION_PAYPHONE;
443            case ImsCallProfile.OIR_PRESENTATION_UNKNOWN:
444                return PhoneConstants.PRESENTATION_UNKNOWN;
445            default:
446                return PhoneConstants.PRESENTATION_UNKNOWN;
447        }
448    }
449
450    /**
451     * Checks if video call is paused
452     * @return true if call is video paused
453     */
454    public boolean isVideoPaused() {
455        return mMediaProfile.mVideoDirection == ImsStreamMediaProfile.DIRECTION_INACTIVE;
456    }
457
458    /**
459     * Determines if the {@link ImsCallProfile} represents a video call.
460     *
461     * @return {@code true} if the profile is for a video call, {@code false} otherwise.
462     */
463    public boolean isVideoCall() {
464        return VideoProfile.isVideo(getVideoStateFromCallType(mCallType));
465    }
466
467    /**
468     * Determines if a video state is set in a video state bit-mask.
469     *
470     * @param videoState The video state bit mask.
471     * @param videoStateToCheck The particular video state to check.
472     * @return True if the video state is set in the bit-mask.
473     */
474    private static boolean isVideoStateSet(int videoState, int videoStateToCheck) {
475        return (videoState & videoStateToCheck) == videoStateToCheck;
476    }
477}
478