ImsPhoneConnection.java revision 44b58c8044c5fc0b271432429fc97707c4c773e1
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
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Event Constants
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DTMF_DONE = 1;
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_PAUSE_DONE = 2;
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_NEXT_POST_DIAL = 3;
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
1196bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private static final int EVENT_DTMF_DELAY_DONE = 5;
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Inner Classes
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    class MyHandler extends Handler {
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        MyHandler(Looper l) {super(l);}
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        handleMessage(Message msg) {
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (msg.what) {
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_NEXT_POST_DIAL:
1366bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DELAY_DONE:
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_PAUSE_DONE:
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    processNextPostDialChar();
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_WAKE_LOCK_TIMEOUT:
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    releaseWakeLock();
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1436bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DONE:
1446bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // We may need to add a delay specified by carrier between DTMF tones that are
1456bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // sent out.
1466bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
1476bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                            mDtmfToneDelay);
1486bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    break;
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is probably an MT call */
156f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
15708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh           ImsPhoneCall parent, boolean isUnknown) {
158c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1596bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
169d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mNumberPresentation = ImsCallProfile.OIRToPresentation(
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
171d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
1736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            updateMediaCapabilities(imsCall);
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mIsIncoming = !isUnknown;
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUusInfo = null;
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
183553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
184553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
185553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // connection is not likely to be associated with a TelephonyConnection yet).
186553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        updateExtras(imsCall);
187553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
18908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mParent.attach(this,
19008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));
1916bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
1926bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
193c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
194c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
195c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
196c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
197c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is an MO call, created when dialing */
201f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
2028bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            ImsPhoneCall parent, boolean isEmergency) {
203c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
2046bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDialString = dialString;
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //mIndex = -1;
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIsIncoming = false;
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapName = null;
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        parent.attachFake(this, ImsPhoneCall.State.DIALING);
2256bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2268bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        mIsEmergency = isEmergency;
2278bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
2286bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
229c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
230c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
231c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
232c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
233c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static boolean
240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    equalsHandlesNulls (Object a, Object b) {
241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (a == null) ? (b == null) : a.equals (b);
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
24474c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    static boolean
24574c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    equalsBaseDialString (String a, String b) {
24674c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi        return (a == null) ? (b == null) : (b != null && a.startsWith (b));
24774c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    }
24874c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi
249f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
2502e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyLocalCallCapabilities - localProfile = "+localProfile);
251f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2522e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
253f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
254f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (localProfile.mCallType) {
255f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2562e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // Fall-through
257f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
258f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2592e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
260f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
261f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
262f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
263f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
264f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
265f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
2662e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
267f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2682e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
269f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
270f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (remoteProfile.mCallType) {
271f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2722e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // fall-through
273f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
274f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2752e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
276f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
277f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
278f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
279f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
280f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public String getOrigDialString(){
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDialString;
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall getCall() {
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mParent;
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getDisconnectTime() {
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDisconnectTime;
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldingStartTime() {
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mHoldingStartTime;
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldDurationMillis() {
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (getState() != ImsPhoneCall.State.HOLDING) {
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // If not holding, return 0
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return 0;
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return SystemClock.elapsedRealtime() - mHoldingStartTime;
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void setDisconnectCause(int cause) {
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = cause;
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
31533cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    @Override
31633cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    public String getVendorDisconnectCause() {
31733cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      return null;
31833cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
31933cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCallTracker getOwner () {
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mOwner;
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall.State getState() {
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mDisconnected) {
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return ImsPhoneCall.State.DISCONNECTED;
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return super.getState();
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void hangup() throws CallStateException {
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.hangup(this);
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("disconnected");
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void separate() throws CallStateException {
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new CallStateException ("not supported");
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWaitChar() {
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WAIT) {
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WAIT but was " + mPostDialState);
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWildChar(String str) {
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WILD) {
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WILD but was " + mPostDialState);
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // make a new postDialString, with the wild char replacement string
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // at the beginning, followed by the remaining postDialString.
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        StringBuilder buf = new StringBuilder(str);
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        buf.append(mPostDialString.substring(mNextPostDialChar));
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = buf.toString();
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNextPostDialChar = 0;
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPostDialString);
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void cancelPostDial() {
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.CANCELLED);
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Called when this Connection is being hung up locally (eg, user pressed "end")
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onHangupLocal() {
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = DisconnectCause.LOCAL;
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** Called when the connection has been disconnected */
399c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
400c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean onDisconnect(int cause) {
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
4021999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
4031999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn            mCause = cause;
4041999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        }
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return onDisconnect();
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
408f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean onDisconnect() {
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //mIndex = -1;
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnectTime = System.currentTimeMillis();
415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnected = true;
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.mPhone.notifyDisconnect(this);
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mParent != null) {
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                changed = mParent.connectionDisconnected(this);
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "onDisconnect: no parent");
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
42534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            synchronized (this) {
42634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                if (mImsCall != null) mImsCall.close();
42734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                mImsCall = null;
42834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return changed;
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * An incoming or outgoing call has connected
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onConnectedInOrOut() {
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTime = System.currentTimeMillis();
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTimeReal = SystemClock.elapsedRealtime();
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDuration = 0;
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mIsIncoming) {
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // outgoing calls only
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processNextPostDialChar();
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onStartedHolding() {
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHoldingStartTime = SystemClock.elapsedRealtime();
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Performs the appropriate action for a post-dial char, but does not
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * notify application. returns false if the character is invalid and
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * should be ignored
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processPostDialChar(char c) {
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (PhoneNumberUtils.is12Key(c)) {
466d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            mOwner.sendDtmf(c, mHandler.obtainMessage(EVENT_DTMF_DONE));
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.PAUSE) {
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // From TS 22.101:
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // It continues...
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Upon the called party answering the UE shall send the DTMF digits
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // automatically to the network after a delay of 3 seconds( 20 ).
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The digits shall be sent according to the procedures and timing
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // "DTMF Control Digits Separator" shall be used by the ME to
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // distinguish between the addressing digits (i.e. the phone number)
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // and the DTMF digits. Upon subsequent occurrences of the
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // separator,
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // the UE shall pause again for 3 seconds ( 20 ) before sending
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // any further DTMF digits.
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    PAUSE_DELAY_MILLIS);
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WAIT) {
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WAIT);
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WILD) {
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WILD);
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return false;
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return true;
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
494032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan    protected void finalize() {
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processNextPostDialChar() {
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        char c = 0;
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant postDialHandler;
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState == PostDialState.CANCELLED) {
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
508d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.COMPLETE);
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // notifyMessage.arg1 is 0 on complete
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = 0;
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            boolean isValid;
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.STARTED);
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = mPostDialString.charAt(mNextPostDialChar++);
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            isValid = processPostDialChar(c);
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (!isValid) {
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Will call processNextPostDialChar
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Don't notify application
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5314567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        notifyPostDialListenersNextChar(c);
5324567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen
5334567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        // TODO: remove the following code since the handler no longer executes anything.
53493c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan        postDialHandler = mOwner.mPhone.getPostDialHandler();
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Message notifyMessage;
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (postDialHandler != null
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The AsyncResult.result is the Connection object
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            PostDialState state = mPostDialState;
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.result = this;
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.userObj = state;
545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // arg1 is the character that was/is being processed
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.arg1 = c;
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
549d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //Rlog.v(LOG_TAG,
550d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.sendToTarget();
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Set post dial state and acquire wake lock while switching to "started"
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state, the wake lock will be released if state switches out of "started"
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @param s new PostDialState
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
561a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void setPostDialState(PostDialState s) {
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.STARTED
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s == PostDialState.STARTED) {
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            acquireWakeLock();
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPostDialState == PostDialState.STARTED
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s != PostDialState.STARTED) {
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            releaseWakeLock();
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialState = s;
573d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        notifyPostDialListeners();
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    createWakeLock(Context context) {
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    acquireWakeLock() {
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "acquireWakeLock");
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock.acquire();
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
58897fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com    void
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    releaseWakeLock() {
59037800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan        if (mPartialWakeLock != null) {
59137800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan            synchronized (mPartialWakeLock) {
59237800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                if (mPartialWakeLock.isHeld()) {
59337800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    Rlog.d(LOG_TAG, "releaseWakeLock");
59437800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    mPartialWakeLock.release();
59537800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                }
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
600c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    private void fetchDtmfToneDelay(Phone phone) {
6016bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        CarrierConfigManager configMgr = (CarrierConfigManager)
6026bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
6036bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
6046bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        if (b != null) {
6056bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
6066bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        }
6076bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    }
6086bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getNumberPresentation() {
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mNumberPresentation;
612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UUSInfo getUUSInfo() {
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mUusInfo;
617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
620a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Connection getOrigConnection() {
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
62534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isMultiparty() {
626541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return mImsCall != null && mImsCall.isMultiparty();
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
629ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    /**
630ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
631ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
632ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
633ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *
634ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
635ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *      {@code false} otherwise.
636ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     */
637c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
63834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isConferenceHost() {
63934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        return mImsCall != null && mImsCall.isConferenceHost();
640ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    }
641ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
642c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
643c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean isMemberOfPeerConference() {
644c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        return !isConferenceHost();
645c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    }
646c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
64734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized ImsCall getImsCall() {
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mImsCall;
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
65134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized void setImsCall(ImsCall imsCall) {
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
655f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void changeParent(ImsPhoneCall parent) {
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
6606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
6616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *     changed, and {@code false} otherwise.
6626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
663f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.ACTIVE) {
665707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // If the state of the call is active, but there is a pending request to the RIL to hold
666707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // the call, we will skip this update.  This is really a signalling delay or failure
667707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // from the RIL, but we will prevent it from going through as we will end up erroneously
668707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // making this call active when really it should be on hold.
669707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (imsCall.isPendingHold()) {
670707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
671707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                return false;
672707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
673707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
6746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                onConnectedInOrOut();
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6786a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //mForegroundCall should be IDLE
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //when accepting WAITING call
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //before accept WAITING call,
682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //the ACTIVE call should be held ahead
683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.detach(this);
684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent = mOwner.mForegroundCall;
685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.attach(this);
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (state == ImsPhoneCall.State.HOLDING) {
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onStartedHolding();
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
691549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen        boolean updateParent = mParent.update(this, imsCall, state);
692eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
69321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
69421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateExtras = updateExtras(imsCall);
695ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
69675f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getPreciseDisconnectCause() {
701222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        return mPreciseDisconnectCause;
702222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
703222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
704222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    public void setPreciseDisconnectCause(int cause) {
705222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        mPreciseDisconnectCause = cause;
706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
707d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn
708d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    /**
709d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * Notifies this Connection of a request to disconnect a participant of the conference managed
710d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * by the connection.
711d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     *
712d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
713d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     */
714d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    @Override
715d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    public void onDisconnectConferenceParticipant(Uri endpoint) {
716d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        ImsCall imsCall = getImsCall();
717d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        if (imsCall == null) {
718d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            return;
719d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
720d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        try {
721d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            imsCall.removeParticipants(new String[]{endpoint.toString()});
722d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        } catch (ImsException e) {
723d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            // No session in place -- no change
724d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
725d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn                    "Failed to disconnect endpoint = " + endpoint);
726d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
727d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
728541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn
729541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    /**
730fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
731fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * this phone connection.
732fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     *
733fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @param conferenceConnectTime The conference connect time.
734fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
735fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public void setConferenceConnectTime(long conferenceConnectTime) {
736fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        mConferenceConnectTime = conferenceConnectTime;
737fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
738fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
739fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
740fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @return The conference connect time.
741fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
742fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public long getConferenceConnectTime() {
743fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        return mConferenceConnectTime;
744fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
745fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
746fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
747eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * Check for a change in the address display related fields for the {@link ImsCall}, and
748eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * update the {@link ImsPhoneConnection} with this information.
749eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     *
750eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @param imsCall The call to check for changes in address display fields.
751eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @return Whether the address display fields have been changed.
752eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     */
75327e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati    public boolean updateAddressDisplay(ImsCall imsCall) {
754eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (imsCall == null) {
755eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            return false;
756eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
757eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
758eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean changed = false;
759eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        ImsCallProfile callProfile = imsCall.getCallProfile();
760eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (callProfile != null) {
761eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
762eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
763eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int nump = ImsCallProfile.OIRToPresentation(
764eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
765eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int namep = ImsCallProfile.OIRToPresentation(
766eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
767eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (Phone.DEBUG_PHONE) {
768286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                Rlog.d(LOG_TAG, "callId = " + getTelecomCallId() + " address = " + Rlog.pii(LOG_TAG,
769286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        address) + " name = " + name + " nump = " + nump + " namep = " + namep);
770eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
771286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn            if (!mIsMergeInProcess) {
772286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // Only process changes to the name and address when a merge is not in process.
773286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // When call A initiated a merge with call B to form a conference C, there is a
774286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // point in time when the ImsCall transfers the conference call session into A,
775286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // at which point the ImsConferenceController creates the conference in Telecom.
776286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // For some carriers C will have a unique conference URI address.  Swapping the
777286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // conference session into A, which is about to be disconnected, to be logged to
778286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // the call log using the conference address.  To prevent this we suppress updates
779286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // to the call address while a merge is in process.
780286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (!equalsBaseDialString(mAddress, address)) {
781286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mAddress = address;
782286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
783286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
784286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (TextUtils.isEmpty(name)) {
785286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    if (!TextUtils.isEmpty(mCnapName)) {
786286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        mCnapName = "";
787286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        changed = true;
788286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    }
789286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                } else if (!name.equals(mCnapName)) {
790286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapName = name;
791286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
792286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
793286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mNumberPresentation != nump) {
794286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mNumberPresentation = nump;
795286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
796286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
797286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mCnapNamePresentation != namep) {
798286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapNamePresentation = namep;
799eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    changed = true;
800eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                }
801eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
802eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
803eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        return changed;
804eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
805eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
806eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    /**
8076a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
8086a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * update the {@link ImsPhoneConnection} with this information.
8096a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
8106a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param imsCall The call to check for changes in media capabilities.
8116a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return Whether the media capabilities have been changed.
8126a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
813d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    public boolean updateMediaCapabilities(ImsCall imsCall) {
8146a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (imsCall == null) {
8156a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return false;
8166a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
8176a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8186a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        boolean changed = false;
8196a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8206a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        try {
821e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            // The actual call profile (negotiated between local and peer).
822e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
8236a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
824e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            if (negotiatedCallProfile != null) {
825288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int oldVideoState = getVideoState();
826288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int newVideoState = ImsCallProfile
827288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);
828e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
829288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (oldVideoState != newVideoState) {
830db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
831db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // below.  When the video enters a paused state, subsequent changes to the video
832db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
833db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // we will be updating the current video state while paused to include any
834db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // changes the modem reports via the video provider.  When the video enters an
835db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // unpaused state, we will resume passing the video states from the modem as is.
836db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (VideoProfile.isPaused(oldVideoState) &&
837db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            !VideoProfile.isPaused(newVideoState)) {
838db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered un-paused state; recognize updates from now on; we want to
839db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // ensure that the new un-paused state is propagated to Telecom, so change
840db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // this now.
841db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = false;
842db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
843db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
844db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!mShouldIgnoreVideoStateChanges) {
84544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                        updateVideoState(newVideoState);
846db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        changed = true;
847db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    } else {
848db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
849db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                                "due to paused state.");
850db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
851db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
852db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!VideoProfile.isPaused(oldVideoState) &&
853db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            VideoProfile.isPaused(newVideoState)) {
854db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered pause state; ignore updates until un-paused.  We do this
855db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // after setVideoState is called above to ensure Telecom is notified that
856db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // the device has entered paused state.
857db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = true;
858db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
859e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn                }
860e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            }
861e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
862f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Check for a change in the capabilities for the call and update
863f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // {@link ImsPhoneConnection} with this information.
864f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            int capabilities = getConnectionCapabilities();
8652e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
8662e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            // Use carrier config to determine if downgrading directly to audio-only is supported.
8672e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
8682e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = addCapability(capabilities,
8692e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8702e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8712e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            } else {
8722e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = removeCapability(capabilities,
8732e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8742e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8752e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            }
8762e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
877f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current local call capabilities which might be voice or video or both.
878f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
879f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
8806a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (localCallProfile != null) {
881f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
8826a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8836a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
884f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current remote call capabilities which might be voice or video or both.
885f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
886f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
887288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (remoteCallProfile != null) {
888f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
889f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            }
890f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            if (getConnectionCapabilities() != capabilities) {
891f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                setConnectionCapabilities(capabilities);
892f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                changed = true;
893288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
894288268d5528e0df03f348e303954813cb188c55bRekha Kumar
8956a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            int newAudioQuality =
8966a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
8976a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (getAudioQuality() != newAudioQuality) {
8986a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                setAudioQuality(newAudioQuality);
8996a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                changed = true;
9006a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
9016a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        } catch (ImsException e) {
9026a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            // No session in place -- no change
9036a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
9046a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9056a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return changed;
9066a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9076a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
90844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    private void updateVideoState(int newVideoState) {
90944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        if (mImsVideoCallProviderWrapper != null) {
91044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn            mImsVideoCallProviderWrapper.onVideoStateChanged(newVideoState);
91144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        }
91244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        setVideoState(newVideoState);
91344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
91444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
915fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyRequest(android.telecom.Connection.RttTextStream textStream) {
916fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getImsCall().sendRttModifyRequest();
917fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        setCurrentRttTextStream(textStream);
918fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
919fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
920fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    /**
921fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * Sends the user's response to a remotely-issued RTT upgrade request
922fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *
923fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * @param textStream A valid {@link android.telecom.Connection.RttTextStream} if the user
924fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *                   accepts, {@code null} if not.
925fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     */
926fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyResponse(android.telecom.Connection.RttTextStream textStream) {
927fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        boolean accept = textStream != null;
928fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        ImsCall imsCall = getImsCall();
929fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
930fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        imsCall.sendRttModifyResponse(accept);
931fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        if (accept) {
932fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            setCurrentRttTextStream(textStream);
933fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            startRttTextProcessing();
934fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        } else {
935fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            Rlog.e(LOG_TAG, "sendRttModifyResponse: foreground call has no connections");
936fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        }
937fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
938fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
939fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void onRttMessageReceived(String message) {
940fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getOrCreateRttTextHandler().sendToInCall(message);
941fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
942fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
943fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void setCurrentRttTextStream(android.telecom.Connection.RttTextStream rttTextStream) {
944fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        mRttTextStream = rttTextStream;
945fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
946fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
947fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void startRttTextProcessing() {
948fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getOrCreateRttTextHandler().initialize(mRttTextStream);
949fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
950fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
951fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private ImsRttTextHandler getOrCreateRttTextHandler() {
952fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        if (mRttTextHandler != null) {
953fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            return mRttTextHandler;
954fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        }
955fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        mRttTextHandler = new ImsRttTextHandler(Looper.getMainLooper(),
956fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu                (message) -> getImsCall().sendRttMessage(message));
957fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        return mRttTextHandler;
958fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
959fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
9606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
9612e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
9622e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * The call is considered to be a WIFI call if the extra value is
9632e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
9642e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     *
9652e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * @param extras The ImsCallProfile extras.
9662e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     */
9672e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    private void updateWifiStateFromExtras(Bundle extras) {
968d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
969d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
9702e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
971d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            ImsCall call = getImsCall();
972d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            boolean isWifi = false;
973d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            if (call != null) {
974d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                isWifi = call.isWifiCall();
975d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            }
9762e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
9772e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            // Report any changes
9782e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            if (isWifi() != isWifi) {
9792e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn                setWifi(isWifi);
9802e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            }
9812e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        }
9822e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
9832e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
9842e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
98521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * Check for a change in call extras of {@link ImsCall}, and
98621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * update the {@link ImsPhoneConnection} accordingly.
98721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     *
98821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @param imsCall The call to check for changes in extras.
98921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @return Whether the extras fields have been changed.
99021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     */
99121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     boolean updateExtras(ImsCall imsCall) {
99221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (imsCall == null) {
99321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
99421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
99521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
99621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final ImsCallProfile callProfile = imsCall.getCallProfile();
99721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
99821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null && DBG) {
99921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            Rlog.d(LOG_TAG, "Call profile extras are null.");
100021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
100121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
100221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final boolean changed = !areBundlesEqual(extras, mExtras);
100321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (changed) {
10042e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            updateWifiStateFromExtras(extras);
10052e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
100621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.clear();
100721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.putAll(extras);
100821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            setConnectionExtras(mExtras);
100921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
101021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return changed;
101121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
101221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
101421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null || newExtras == null) {
101521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return extras == newExtras;
101621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
101721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
101821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras.size() != newExtras.size()) {
101921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
102021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
102121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
102221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        for(String key : extras.keySet()) {
102321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            if (key != null) {
102421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object value = extras.get(key);
102521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object newValue = newExtras.get(key);
102621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                if (!Objects.equals(value, newValue)) {
102721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                    return false;
102821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                }
102921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            }
103021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
103121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return true;
103221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
103321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
103421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    /**
10356a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
1036363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
1037363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
1038363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * there is no remote restrict cause.
10396a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
10406a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param localCallProfile The local call profile.
10416a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param remoteCallProfile The remote call profile.
10426a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return The audio quality.
10436a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
10446a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    private int getAudioQualityFromCallProfile(
10456a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
10466a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (localCallProfile == null || remoteCallProfile == null
10476a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile == null) {
10486a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return AUDIO_QUALITY_STANDARD;
10496a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
10506a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
1051363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
1052363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
1053363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1054363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
1055363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1056363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);
1057363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
1058363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
10596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
10606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile.mAudioQuality
1061363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
1062363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || isEvsCodecHighDef)
10636a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
10646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
10656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
10666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
10676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
1068541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
1069541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * use in log statements.
1070541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     *
1071541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * @return String representation of call.
1072541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     */
1073541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    @Override
1074541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    public String toString() {
1075541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        StringBuilder sb = new StringBuilder();
1076541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("[ImsPhoneConnection objId: ");
1077541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append(System.identityHashCode(this));
10781a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" telecomCallID: ");
10791a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(getTelecomCallId());
10801a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" address: ");
108177a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu        sb.append(Rlog.pii(LOG_TAG, getAddress()));
10821a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" ImsCall: ");
108334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        synchronized (this) {
108434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            if (mImsCall == null) {
108534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append("null");
108634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            } else {
108734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append(mImsCall);
108834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
1089541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        }
1090541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("]");
1091541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return sb.toString();
1092541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
10938bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1094359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    @Override
1095359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1096359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        super.setVideoProvider(videoProvider);
1097359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1098359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1099359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
1100359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1101359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1102359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
11038bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    /**
11048bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * Indicates whether current phone connection is emergency or not
11058bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * @return boolean: true if emergency, false otherwise
11068bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     */
11078bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    protected boolean isEmergency() {
11088bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        return mIsEmergency;
11098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
1110db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1111db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    /**
1112db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
1113db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * responses received.
1114db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     *
1115db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param status The status of the original request.
1116db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param requestProfile The requested video profile.
1117db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param responseProfile The response upon video profile.
1118db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
1119db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    @Override
1120db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
1121db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            VideoProfile responseProfile) {
1122db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
1123db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                mShouldIgnoreVideoStateChanges) {
1124db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int currentVideoState = getVideoState();
1125db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int newVideoState = responseProfile.getVideoState();
1126db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1127db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // If the current video state is paused, the modem will not send us any changes to
1128db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // the TX and RX bits of the video state.  Until the video is un-paused we will
1129db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // "fake out" the video state by applying the changes that the modem reports via a
1130db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // response.
1131db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1132db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // First, find out whether there was a change to the TX or RX bits:
1133db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int changedBits = currentVideoState ^ newVideoState;
1134db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
1135db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (changedBits == 0) {
1136db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                // No applicable change, bail out.
1137db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                return;
1138db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1139db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1140db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn off any existing bits that changed.
1141db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState &= ~(changedBits & currentVideoState);
1142db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn on any new bits that turned on.
1143db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState |= changedBits & newVideoState;
1144db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1145db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
1146db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
1147db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " / " +
1148db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
1149db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " while paused ; sending new videoState = " +
1150db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(currentVideoState));
1151db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            setVideoState(currentVideoState);
1152db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        }
1153db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1154359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1155359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1156359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
1157359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1158359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1159359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the pause request.
1160359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1161359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void pauseVideo(int source) {
1162359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1163359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1164359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1165359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1166359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
1167359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1168359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1169359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1170359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
1171359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1172359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1173359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the resume request.
1174359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1175359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void resumeVideo(int source) {
1176359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1177359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1178359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1179359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1180359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
1181359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1182359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1183359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1184359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Determines if a specified source has issued a pause request.
1185359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1186359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source.
1187359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @return {@code true} if the source issued a pause request, {@code false} otherwise.
1188359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1189359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public boolean wasVideoPausedFromSource(int source) {
1190359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1191359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return false;
1192359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1193359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1194359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
1195359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1196286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1197286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1198286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as in the process of being merged and inform the UI of the merge start.
1199286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1200286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeStart() {
1201286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = true;
1202286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_START, null);
1203286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
1204286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1205286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1206286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as done merging and inform the UI of the merge start.
1207286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1208286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeComplete() {
1209286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = false;
1210286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_COMPLETE, null);
1211286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
121244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
121344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToPausedState() {
121444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() | VideoProfile.STATE_PAUSED;
121544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToPausedState - setting paused bit; "
121644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
121744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
121844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
121944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
122044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToUnPausedState() {
122144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() & ~VideoProfile.STATE_PAUSED;
122244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToUnPausedState - unsetting paused bit; "
122344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
122444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
122544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
1226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1227