ImsPhoneConnection.java revision c58281f18e760c39c2fedba61453eae7bfdda349
1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Copyright (C) 2013 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony.imsphone;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
20d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunnimport android.net.Uri;
21a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
2208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport android.os.Bundle;
23a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
24a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Looper;
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
266bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusimport android.os.PersistableBundle;
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.PowerManager;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemClock;
30db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnimport android.telecom.VideoProfile;
316bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusimport android.telephony.CarrierConfigManager;
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
352e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunnimport android.telephony.ServiceState;
36eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganeshimport android.text.TextUtils;
37a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
38286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunnimport com.android.ims.ImsCall;
39286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunnimport com.android.ims.ImsCallProfile;
402999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunnimport com.android.ims.ImsException;
417fa8ac39602ee9841dfcb0fb5c5f4d401925f8b5Tyler Gunnimport com.android.ims.ImsStreamMediaProfile;
42db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnimport com.android.ims.internal.ImsVideoCallProviderWrapper;
43a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
46a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.UUSInfo;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkarimport java.util.Objects;
5021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
51a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
53a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
54db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnpublic class ImsPhoneConnection extends Connection implements
55db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        ImsVideoCallProviderWrapper.ImsVideoProviderWrapperCallback {
56db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
57a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final String LOG_TAG = "ImsPhoneConnection";
58a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
61a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
62a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneCallTracker mOwner;
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneCall mParent;
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mImsCall;
6521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private Bundle mExtras = new Bundle();
66a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDisconnected;
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    int mIndex;          // index in ImsPhoneCallTracker.connections[], -1 if unassigned
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        // The GSM index is 1 + this
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    */
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * These time/timespan values are based on System.currentTimeMillis(),
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * i.e., "wall clock" time.
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private long mDisconnectTime;
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UUSInfo mUusInfo;
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Handler mHandler;
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PowerManager.WakeLock mPartialWakeLock;
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
85fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    // The cached connect time of the connection when it turns into a conference.
86fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    private long mConferenceConnectTime = 0;
87fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
886bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    // The cached delay to be used between DTMF tones fetched from carrier config.
896bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private int mDtmfToneDelay = 0;
906bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
918bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    private boolean mIsEmergency = false;
928bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
932e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
94db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Used to indicate that video state changes detected by
95db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * {@link #updateMediaCapabilities(ImsCall)} should be ignored.  When a video state change from
96db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * unpaused to paused occurs, we set this flag and then update the existing video state when
97db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * new {@link #onReceiveSessionModifyResponse(int, VideoProfile, VideoProfile)} callbacks come
98db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * in.  When the video un-pauses we continue receiving the video state updates.
99db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
100db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    private boolean mShouldIgnoreVideoStateChanges = false;
101db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
102359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    private ImsVideoCallProviderWrapper mImsVideoCallProviderWrapper;
103359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
104222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    private int mPreciseDisconnectCause = 0;
105222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
106fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private ImsRttTextHandler mRttTextHandler;
107fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private android.telecom.Connection.RttTextStream mRttTextStream;
108fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
109286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
110286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Used to indicate that this call is in the midst of being merged into a conference.
111286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
112286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    private boolean mIsMergeInProcess = false;
113286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
11463fa599fef0383b41f85e1fc3a38d33c4434e24aTyler Gunn    /**
1157a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * Used as an override to determine whether video is locally available for this call.
1167a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * This allows video availability to be overridden in the case that the modem says video is
1177a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * currently available, but mobile data is off and the carrier is metering data for video
1187a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * calls.
1197a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     */
1207a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    private boolean mIsVideoEnabled = true;
1217a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Event Constants
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DTMF_DONE = 1;
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_PAUSE_DONE = 2;
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_NEXT_POST_DIAL = 3;
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
1276bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private static final int EVENT_DTMF_DELAY_DONE = 5;
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Inner Classes
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    class MyHandler extends Handler {
136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        MyHandler(Looper l) {super(l);}
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        handleMessage(Message msg) {
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (msg.what) {
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_NEXT_POST_DIAL:
1446bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DELAY_DONE:
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_PAUSE_DONE:
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    processNextPostDialChar();
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_WAKE_LOCK_TIMEOUT:
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    releaseWakeLock();
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1516bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DONE:
1526bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // We may need to add a delay specified by carrier between DTMF tones that are
1536bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // sent out.
1546bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
1556bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                            mDtmfToneDelay);
1566bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    break;
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is probably an MT call */
164f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
16508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh           ImsPhoneCall parent, boolean isUnknown) {
166c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1676bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
177d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mNumberPresentation = ImsCallProfile.OIRToPresentation(
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
179d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
1816a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            updateMediaCapabilities(imsCall);
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
18708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mIsIncoming = !isUnknown;
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUusInfo = null;
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
191553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
192553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
193553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // connection is not likely to be associated with a TelephonyConnection yet).
194553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        updateExtras(imsCall);
195553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
19708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mParent.attach(this,
19808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));
1996bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2006bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
201c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
202c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
203c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
204c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
205c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is an MO call, created when dialing */
209f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
2108bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            ImsPhoneCall parent, boolean isEmergency) {
211c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
2126bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDialString = dialString;
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //mIndex = -1;
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIsIncoming = false;
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapName = null;
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        parent.attachFake(this, ImsPhoneCall.State.DIALING);
2336bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2348bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        mIsEmergency = isEmergency;
2358bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
2366bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
237c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
238c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
239c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
240c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
241c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static boolean
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    equalsHandlesNulls (Object a, Object b) {
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (a == null) ? (b == null) : a.equals (b);
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
25274c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    static boolean
25374c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    equalsBaseDialString (String a, String b) {
25474c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi        return (a == null) ? (b == null) : (b != null && a.startsWith (b));
25574c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    }
25674c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi
2577a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    private int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
2587a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        Rlog.i(LOG_TAG, "applyLocalCallCapabilities - localProfile = " + localProfile);
259f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2602e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
261f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
2627a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        if (!mIsVideoEnabled) {
2637a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            Rlog.i(LOG_TAG, "applyLocalCallCapabilities - disabling video (overidden)");
2647a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            return capabilities;
2657a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        }
266f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (localProfile.mCallType) {
267f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2682e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // Fall-through
269f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
270f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2712e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
272f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
273f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
274f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
275f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
276f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
277f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
2782e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
279f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2802e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
281f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
282f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (remoteProfile.mCallType) {
283f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2842e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // fall-through
285f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
286f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2872e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
288f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
289f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
290f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
291f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
292f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public String getOrigDialString(){
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDialString;
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall getCall() {
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mParent;
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getDisconnectTime() {
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDisconnectTime;
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldingStartTime() {
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mHoldingStartTime;
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldDurationMillis() {
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (getState() != ImsPhoneCall.State.HOLDING) {
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // If not holding, return 0
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return 0;
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return SystemClock.elapsedRealtime() - mHoldingStartTime;
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void setDisconnectCause(int cause) {
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = cause;
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
32733cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    @Override
32833cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    public String getVendorDisconnectCause() {
32933cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      return null;
33033cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
33133cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCallTracker getOwner () {
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mOwner;
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall.State getState() {
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mDisconnected) {
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return ImsPhoneCall.State.DISCONNECTED;
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return super.getState();
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void hangup() throws CallStateException {
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.hangup(this);
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("disconnected");
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void separate() throws CallStateException {
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new CallStateException ("not supported");
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWaitChar() {
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WAIT) {
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WAIT but was " + mPostDialState);
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWildChar(String str) {
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WILD) {
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WILD but was " + mPostDialState);
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // make a new postDialString, with the wild char replacement string
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // at the beginning, followed by the remaining postDialString.
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        StringBuilder buf = new StringBuilder(str);
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        buf.append(mPostDialString.substring(mNextPostDialChar));
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = buf.toString();
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNextPostDialChar = 0;
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPostDialString);
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void cancelPostDial() {
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.CANCELLED);
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Called when this Connection is being hung up locally (eg, user pressed "end")
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onHangupLocal() {
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = DisconnectCause.LOCAL;
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** Called when the connection has been disconnected */
411c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
412c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean onDisconnect(int cause) {
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
4141999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
4151999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn            mCause = cause;
4161999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        }
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return onDisconnect();
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
420f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean onDisconnect() {
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //mIndex = -1;
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnectTime = System.currentTimeMillis();
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnected = true;
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.mPhone.notifyDisconnect(this);
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mParent != null) {
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                changed = mParent.connectionDisconnected(this);
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "onDisconnect: no parent");
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
43734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            synchronized (this) {
43834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                if (mImsCall != null) mImsCall.close();
43934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                mImsCall = null;
44034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return changed;
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * An incoming or outgoing call has connected
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onConnectedInOrOut() {
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTime = System.currentTimeMillis();
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTimeReal = SystemClock.elapsedRealtime();
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDuration = 0;
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mIsIncoming) {
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // outgoing calls only
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processNextPostDialChar();
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onStartedHolding() {
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHoldingStartTime = SystemClock.elapsedRealtime();
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Performs the appropriate action for a post-dial char, but does not
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * notify application. returns false if the character is invalid and
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * should be ignored
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processPostDialChar(char c) {
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (PhoneNumberUtils.is12Key(c)) {
478d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            mOwner.sendDtmf(c, mHandler.obtainMessage(EVENT_DTMF_DONE));
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.PAUSE) {
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // From TS 22.101:
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // It continues...
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Upon the called party answering the UE shall send the DTMF digits
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // automatically to the network after a delay of 3 seconds( 20 ).
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The digits shall be sent according to the procedures and timing
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // "DTMF Control Digits Separator" shall be used by the ME to
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // distinguish between the addressing digits (i.e. the phone number)
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // and the DTMF digits. Upon subsequent occurrences of the
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // separator,
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // the UE shall pause again for 3 seconds ( 20 ) before sending
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // any further DTMF digits.
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    PAUSE_DELAY_MILLIS);
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WAIT) {
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WAIT);
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WILD) {
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WILD);
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return false;
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return true;
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
506032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan    protected void finalize() {
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processNextPostDialChar() {
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        char c = 0;
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant postDialHandler;
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState == PostDialState.CANCELLED) {
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
520d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.COMPLETE);
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // notifyMessage.arg1 is 0 on complete
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = 0;
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            boolean isValid;
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.STARTED);
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = mPostDialString.charAt(mNextPostDialChar++);
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            isValid = processPostDialChar(c);
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (!isValid) {
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Will call processNextPostDialChar
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Don't notify application
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5434567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        notifyPostDialListenersNextChar(c);
5444567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen
5454567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        // TODO: remove the following code since the handler no longer executes anything.
54693c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan        postDialHandler = mOwner.mPhone.getPostDialHandler();
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Message notifyMessage;
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (postDialHandler != null
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The AsyncResult.result is the Connection object
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            PostDialState state = mPostDialState;
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.result = this;
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.userObj = state;
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // arg1 is the character that was/is being processed
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.arg1 = c;
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
561d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //Rlog.v(LOG_TAG,
562d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.sendToTarget();
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Set post dial state and acquire wake lock while switching to "started"
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state, the wake lock will be released if state switches out of "started"
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @param s new PostDialState
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void setPostDialState(PostDialState s) {
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.STARTED
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s == PostDialState.STARTED) {
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            acquireWakeLock();
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPostDialState == PostDialState.STARTED
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s != PostDialState.STARTED) {
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            releaseWakeLock();
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialState = s;
585d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        notifyPostDialListeners();
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    createWakeLock(Context context) {
590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    acquireWakeLock() {
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "acquireWakeLock");
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock.acquire();
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
60097fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com    void
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    releaseWakeLock() {
60237800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan        if (mPartialWakeLock != null) {
60337800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan            synchronized (mPartialWakeLock) {
60437800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                if (mPartialWakeLock.isHeld()) {
60537800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    Rlog.d(LOG_TAG, "releaseWakeLock");
60637800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    mPartialWakeLock.release();
60737800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                }
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
612c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    private void fetchDtmfToneDelay(Phone phone) {
6136bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        CarrierConfigManager configMgr = (CarrierConfigManager)
6146bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
6156bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
6166bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        if (b != null) {
6176bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
6186bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        }
6196bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    }
6206bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getNumberPresentation() {
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mNumberPresentation;
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
625a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UUSInfo getUUSInfo() {
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mUusInfo;
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Connection getOrigConnection() {
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
63734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isMultiparty() {
638541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return mImsCall != null && mImsCall.isMultiparty();
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
641ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    /**
642ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
643ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
644ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
645ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *
646ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
647ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *      {@code false} otherwise.
648ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     */
649c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
65034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isConferenceHost() {
65134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        return mImsCall != null && mImsCall.isConferenceHost();
652ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    }
653ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
654c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
655c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean isMemberOfPeerConference() {
656c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        return !isConferenceHost();
657c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    }
658c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
65934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized ImsCall getImsCall() {
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mImsCall;
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
66334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized void setImsCall(ImsCall imsCall) {
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
667f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void changeParent(ImsPhoneCall parent) {
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6716a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
6726a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
6736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *     changed, and {@code false} otherwise.
6746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
675f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.ACTIVE) {
677707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // If the state of the call is active, but there is a pending request to the RIL to hold
678707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // the call, we will skip this update.  This is really a signalling delay or failure
679707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // from the RIL, but we will prevent it from going through as we will end up erroneously
680707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // making this call active when really it should be on hold.
681707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (imsCall.isPendingHold()) {
682707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
683707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                return false;
684707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
685707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
6866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                onConnectedInOrOut();
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6906a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //mForegroundCall should be IDLE
692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //when accepting WAITING call
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //before accept WAITING call,
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //the ACTIVE call should be held ahead
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.detach(this);
696a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent = mOwner.mForegroundCall;
697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.attach(this);
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (state == ImsPhoneCall.State.HOLDING) {
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onStartedHolding();
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
703549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen        boolean updateParent = mParent.update(this, imsCall, state);
704eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
70521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
70621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateExtras = updateExtras(imsCall);
707ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
70875f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getPreciseDisconnectCause() {
713222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        return mPreciseDisconnectCause;
714222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
715222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
716222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    public void setPreciseDisconnectCause(int cause) {
717222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        mPreciseDisconnectCause = cause;
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
719d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn
720d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    /**
721d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * Notifies this Connection of a request to disconnect a participant of the conference managed
722d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * by the connection.
723d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     *
724d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
725d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     */
726d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    @Override
727d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    public void onDisconnectConferenceParticipant(Uri endpoint) {
728d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        ImsCall imsCall = getImsCall();
729d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        if (imsCall == null) {
730d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            return;
731d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
732d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        try {
733d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            imsCall.removeParticipants(new String[]{endpoint.toString()});
734d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        } catch (ImsException e) {
735d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            // No session in place -- no change
736d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
737d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn                    "Failed to disconnect endpoint = " + endpoint);
738d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
739d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
740541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn
741541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    /**
742fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
743fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * this phone connection.
744fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     *
745fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @param conferenceConnectTime The conference connect time.
746fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
747fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public void setConferenceConnectTime(long conferenceConnectTime) {
748fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        mConferenceConnectTime = conferenceConnectTime;
749fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
750fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
751fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
752fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @return The conference connect time.
753fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
754fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public long getConferenceConnectTime() {
755fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        return mConferenceConnectTime;
756fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
757fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
758fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
759eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * Check for a change in the address display related fields for the {@link ImsCall}, and
760eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * update the {@link ImsPhoneConnection} with this information.
761eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     *
762eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @param imsCall The call to check for changes in address display fields.
763eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @return Whether the address display fields have been changed.
764eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     */
76527e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati    public boolean updateAddressDisplay(ImsCall imsCall) {
766eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (imsCall == null) {
767eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            return false;
768eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
769eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
770eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean changed = false;
771eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        ImsCallProfile callProfile = imsCall.getCallProfile();
772eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn        if (callProfile != null && isIncoming()) {
773eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // Only look for changes to the address for incoming calls.  The originating identity
774eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // can change for outgoing calls due to, for example, a call being forwarded to
775eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // voicemail.  This address change does not need to be presented to the user.
776eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
777eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
778eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int nump = ImsCallProfile.OIRToPresentation(
779eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
780eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int namep = ImsCallProfile.OIRToPresentation(
781eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
782eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (Phone.DEBUG_PHONE) {
783eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn                Rlog.d(LOG_TAG, "updateAddressDisplay: callId = " + getTelecomCallId()
784c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng                        + " address = " + Rlog.pii(LOG_TAG, address) + " name = "
785c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng                        + Rlog.pii(LOG_TAG, name) + " nump = " + nump + " namep = " + namep);
786eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
787286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn            if (!mIsMergeInProcess) {
788286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // Only process changes to the name and address when a merge is not in process.
789286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // When call A initiated a merge with call B to form a conference C, there is a
790286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // point in time when the ImsCall transfers the conference call session into A,
791286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // at which point the ImsConferenceController creates the conference in Telecom.
792286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // For some carriers C will have a unique conference URI address.  Swapping the
793286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // conference session into A, which is about to be disconnected, to be logged to
794286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // the call log using the conference address.  To prevent this we suppress updates
795286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // to the call address while a merge is in process.
796286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (!equalsBaseDialString(mAddress, address)) {
797286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mAddress = address;
798286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
799286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
800286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (TextUtils.isEmpty(name)) {
801286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    if (!TextUtils.isEmpty(mCnapName)) {
802286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        mCnapName = "";
803286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        changed = true;
804286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    }
805286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                } else if (!name.equals(mCnapName)) {
806286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapName = name;
807286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
808286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
809286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mNumberPresentation != nump) {
810286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mNumberPresentation = nump;
811286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
812286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
813286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mCnapNamePresentation != namep) {
814286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapNamePresentation = namep;
815eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    changed = true;
816eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                }
817eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
818eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
819eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        return changed;
820eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
821eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
822eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    /**
8236a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
8246a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * update the {@link ImsPhoneConnection} with this information.
8256a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
8266a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param imsCall The call to check for changes in media capabilities.
8276a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return Whether the media capabilities have been changed.
8286a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
829d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    public boolean updateMediaCapabilities(ImsCall imsCall) {
8306a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (imsCall == null) {
8316a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return false;
8326a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
8336a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8346a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        boolean changed = false;
8356a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8366a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        try {
837e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            // The actual call profile (negotiated between local and peer).
838e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
8396a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
840e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            if (negotiatedCallProfile != null) {
841288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int oldVideoState = getVideoState();
842288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int newVideoState = ImsCallProfile
843288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);
844e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
845288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (oldVideoState != newVideoState) {
846db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
847db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // below.  When the video enters a paused state, subsequent changes to the video
848db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
849db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // we will be updating the current video state while paused to include any
850db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // changes the modem reports via the video provider.  When the video enters an
851db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // unpaused state, we will resume passing the video states from the modem as is.
852db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (VideoProfile.isPaused(oldVideoState) &&
853db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            !VideoProfile.isPaused(newVideoState)) {
854db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered un-paused state; recognize updates from now on; we want to
855db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // ensure that the new un-paused state is propagated to Telecom, so change
856db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // this now.
857db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = false;
858db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
859db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
860db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!mShouldIgnoreVideoStateChanges) {
86144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                        updateVideoState(newVideoState);
862db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        changed = true;
863db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    } else {
864db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
865db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                                "due to paused state.");
866db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
867db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
868db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!VideoProfile.isPaused(oldVideoState) &&
869db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            VideoProfile.isPaused(newVideoState)) {
870db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered pause state; ignore updates until un-paused.  We do this
871db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // after setVideoState is called above to ensure Telecom is notified that
872db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // the device has entered paused state.
873db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = true;
874db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
875e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn                }
876e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            }
877e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
878f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Check for a change in the capabilities for the call and update
879f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // {@link ImsPhoneConnection} with this information.
880f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            int capabilities = getConnectionCapabilities();
8812e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
8822e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            // Use carrier config to determine if downgrading directly to audio-only is supported.
8832e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
8842e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = addCapability(capabilities,
8852e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8862e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8872e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            } else {
8882e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = removeCapability(capabilities,
8892e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8902e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8912e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            }
8922e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
893f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current local call capabilities which might be voice or video or both.
894f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
895f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
8966a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (localCallProfile != null) {
897f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
8986a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8996a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
900f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current remote call capabilities which might be voice or video or both.
901f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
902f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
903288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (remoteCallProfile != null) {
904f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
905f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            }
906f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            if (getConnectionCapabilities() != capabilities) {
907f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                setConnectionCapabilities(capabilities);
908f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                changed = true;
909288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
910288268d5528e0df03f348e303954813cb188c55bRekha Kumar
9116a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            int newAudioQuality =
9126a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
9136a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (getAudioQuality() != newAudioQuality) {
9146a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                setAudioQuality(newAudioQuality);
9156a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                changed = true;
9166a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
9176a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        } catch (ImsException e) {
9186a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            // No session in place -- no change
9196a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
9206a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9216a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return changed;
9226a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9236a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
92444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    private void updateVideoState(int newVideoState) {
92544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        if (mImsVideoCallProviderWrapper != null) {
92644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn            mImsVideoCallProviderWrapper.onVideoStateChanged(newVideoState);
92744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        }
92844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        setVideoState(newVideoState);
92944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
93044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
931fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyRequest(android.telecom.Connection.RttTextStream textStream) {
932fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getImsCall().sendRttModifyRequest();
933fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        setCurrentRttTextStream(textStream);
934fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
935fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
936fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    /**
937fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * Sends the user's response to a remotely-issued RTT upgrade request
938fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *
939fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * @param textStream A valid {@link android.telecom.Connection.RttTextStream} if the user
940fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *                   accepts, {@code null} if not.
941fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     */
942fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyResponse(android.telecom.Connection.RttTextStream textStream) {
943fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        boolean accept = textStream != null;
944fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        ImsCall imsCall = getImsCall();
945fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
946fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        imsCall.sendRttModifyResponse(accept);
947fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        if (accept) {
948fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            setCurrentRttTextStream(textStream);
949fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            startRttTextProcessing();
950fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        } else {
951fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            Rlog.e(LOG_TAG, "sendRttModifyResponse: foreground call has no connections");
952fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        }
953fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
954fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
955fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void onRttMessageReceived(String message) {
956fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getOrCreateRttTextHandler().sendToInCall(message);
957fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
958fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
959fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void setCurrentRttTextStream(android.telecom.Connection.RttTextStream rttTextStream) {
960fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        mRttTextStream = rttTextStream;
961fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
962fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
963fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void startRttTextProcessing() {
964fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getOrCreateRttTextHandler().initialize(mRttTextStream);
965fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
966fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
967fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private ImsRttTextHandler getOrCreateRttTextHandler() {
968fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        if (mRttTextHandler != null) {
969fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            return mRttTextHandler;
970fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        }
971fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        mRttTextHandler = new ImsRttTextHandler(Looper.getMainLooper(),
972fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu                (message) -> getImsCall().sendRttMessage(message));
973fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        return mRttTextHandler;
974fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
975fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
9766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
9772e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
9782e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * The call is considered to be a WIFI call if the extra value is
9792e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
9802e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     *
9812e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * @param extras The ImsCallProfile extras.
9822e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     */
9832e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    private void updateWifiStateFromExtras(Bundle extras) {
984d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
985d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
9862e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
987d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            ImsCall call = getImsCall();
988d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            boolean isWifi = false;
989d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            if (call != null) {
990d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                isWifi = call.isWifiCall();
991d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            }
9922e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
9932e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            // Report any changes
9942e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            if (isWifi() != isWifi) {
9952e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn                setWifi(isWifi);
9962e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            }
9972e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        }
9982e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
9992e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
10002e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
100121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * Check for a change in call extras of {@link ImsCall}, and
100221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * update the {@link ImsPhoneConnection} accordingly.
100321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     *
100421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @param imsCall The call to check for changes in extras.
100521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @return Whether the extras fields have been changed.
100621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     */
100721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     boolean updateExtras(ImsCall imsCall) {
100821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (imsCall == null) {
100921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
101021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
101121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final ImsCallProfile callProfile = imsCall.getCallProfile();
101321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
101421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null && DBG) {
101521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            Rlog.d(LOG_TAG, "Call profile extras are null.");
101621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
101721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final boolean changed = !areBundlesEqual(extras, mExtras);
101921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (changed) {
10202e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            updateWifiStateFromExtras(extras);
10212e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
102221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.clear();
102321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.putAll(extras);
102421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            setConnectionExtras(mExtras);
102521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
102621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return changed;
102721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
102821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
102921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
103021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null || newExtras == null) {
103121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return extras == newExtras;
103221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
103321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
103421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras.size() != newExtras.size()) {
103521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
103621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
103721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
103821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        for(String key : extras.keySet()) {
103921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            if (key != null) {
104021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object value = extras.get(key);
104121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object newValue = newExtras.get(key);
104221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                if (!Objects.equals(value, newValue)) {
104321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                    return false;
104421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                }
104521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            }
104621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
104721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return true;
104821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
104921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
105021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    /**
10516a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
1052363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
1053363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
1054363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * there is no remote restrict cause.
10556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
10566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param localCallProfile The local call profile.
10576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param remoteCallProfile The remote call profile.
10586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return The audio quality.
10596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
10606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    private int getAudioQualityFromCallProfile(
10616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
10626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (localCallProfile == null || remoteCallProfile == null
10636a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile == null) {
10646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return AUDIO_QUALITY_STANDARD;
10656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
10666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
1067363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
1068363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
1069363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1070363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
1071363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1072363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);
1073363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
1074363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
10756a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
10766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile.mAudioQuality
1077363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
1078363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || isEvsCodecHighDef)
10796a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
10806a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
10816a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
10826a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
10836a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
1084541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
1085541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * use in log statements.
1086541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     *
1087541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * @return String representation of call.
1088541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     */
1089541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    @Override
1090541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    public String toString() {
1091541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        StringBuilder sb = new StringBuilder();
1092541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("[ImsPhoneConnection objId: ");
1093541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append(System.identityHashCode(this));
10941a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" telecomCallID: ");
10951a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(getTelecomCallId());
10961a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" address: ");
109777a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu        sb.append(Rlog.pii(LOG_TAG, getAddress()));
10981a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" ImsCall: ");
109934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        synchronized (this) {
110034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            if (mImsCall == null) {
110134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append("null");
110234310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            } else {
110334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append(mImsCall);
110434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
1105541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        }
1106541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("]");
1107541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return sb.toString();
1108541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
11098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1110359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    @Override
1111359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1112359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        super.setVideoProvider(videoProvider);
1113359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1114359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1115359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
1116359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1117359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1118359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
11198bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    /**
11208bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * Indicates whether current phone connection is emergency or not
11218bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * @return boolean: true if emergency, false otherwise
11228bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     */
11238bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    protected boolean isEmergency() {
11248bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        return mIsEmergency;
11258bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
1126db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1127db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    /**
1128db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
1129db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * responses received.
1130db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     *
1131db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param status The status of the original request.
1132db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param requestProfile The requested video profile.
1133db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param responseProfile The response upon video profile.
1134db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
1135db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    @Override
1136db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
1137db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            VideoProfile responseProfile) {
1138db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
1139db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                mShouldIgnoreVideoStateChanges) {
1140db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int currentVideoState = getVideoState();
1141db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int newVideoState = responseProfile.getVideoState();
1142db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1143db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // If the current video state is paused, the modem will not send us any changes to
1144db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // the TX and RX bits of the video state.  Until the video is un-paused we will
1145db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // "fake out" the video state by applying the changes that the modem reports via a
1146db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // response.
1147db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1148db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // First, find out whether there was a change to the TX or RX bits:
1149db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int changedBits = currentVideoState ^ newVideoState;
1150db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
1151db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (changedBits == 0) {
1152db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                // No applicable change, bail out.
1153db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                return;
1154db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1155db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1156db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn off any existing bits that changed.
1157db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState &= ~(changedBits & currentVideoState);
1158db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn on any new bits that turned on.
1159db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState |= changedBits & newVideoState;
1160db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1161db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
1162db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
1163db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " / " +
1164db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
1165db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " while paused ; sending new videoState = " +
1166db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(currentVideoState));
1167db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            setVideoState(currentVideoState);
1168db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        }
1169db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1170359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1171359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1172359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
1173359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1174359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1175359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the pause request.
1176359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1177359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void pauseVideo(int source) {
1178359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1179359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1180359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1181359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1182359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
1183359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1184359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1185359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1186359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
1187359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1188359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1189359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the resume request.
1190359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1191359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void resumeVideo(int source) {
1192359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1193359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1194359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1195359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1196359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
1197359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1198359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1199359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1200359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Determines if a specified source has issued a pause request.
1201359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1202359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source.
1203359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @return {@code true} if the source issued a pause request, {@code false} otherwise.
1204359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1205359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public boolean wasVideoPausedFromSource(int source) {
1206359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1207359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return false;
1208359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1209359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1210359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
1211359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1212286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1213286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1214286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as in the process of being merged and inform the UI of the merge start.
1215286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1216286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeStart() {
1217286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = true;
1218286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_START, null);
1219286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
1220286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1221286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1222286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as done merging and inform the UI of the merge start.
1223286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1224286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeComplete() {
1225286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = false;
1226286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_COMPLETE, null);
1227286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
122844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
122944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToPausedState() {
123044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() | VideoProfile.STATE_PAUSED;
123144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToPausedState - setting paused bit; "
123244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
123344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
12346dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn        mShouldIgnoreVideoStateChanges = true;
123544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
123644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
123744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToUnPausedState() {
123844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() & ~VideoProfile.STATE_PAUSED;
123944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToUnPausedState - unsetting paused bit; "
124044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
124144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
12426dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn        mShouldIgnoreVideoStateChanges = false;
124344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
12447a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
12457a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    public void handleDataEnabledChange(boolean isDataEnabled) {
12467a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        mIsVideoEnabled = isDataEnabled;
12477a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        Rlog.i(LOG_TAG, "handleDataEnabledChange: isDataEnabled=" + isDataEnabled
12487a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                + "; updating local video availability.");
12497a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        updateMediaCapabilities(getImsCall());
12507a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        if (mImsVideoCallProviderWrapper != null) {
12517a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            mImsVideoCallProviderWrapper.setIsVideoEnabled(
12527a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                    hasCapabilities(Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
12537a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        }
125465cd15597c5e611184a3f4c8ead5f42644fc00d6Tyler Gunn    }
1255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1256