ImsPhoneConnection.java revision 75f96a40e73bbf262287b64f7ba79f058adac472
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
382999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunnimport com.android.ims.ImsException;
397fa8ac39602ee9841dfcb0fb5c5f4d401925f8b5Tyler Gunnimport com.android.ims.ImsStreamMediaProfile;
40db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnimport com.android.ims.internal.ImsVideoCallProviderWrapper;
41a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
43a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.UUSInfo;
46a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsCall;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsCallProfile;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkarimport java.util.Objects;
5121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
53a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
54a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
55db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnpublic class ImsPhoneConnection extends Connection implements
56db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        ImsVideoCallProviderWrapper.ImsVideoProviderWrapperCallback {
57db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
58a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final String LOG_TAG = "ImsPhoneConnection";
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
61a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
62a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneCallTracker mOwner;
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneCall mParent;
65a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mImsCall;
6621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private Bundle mExtras = new Bundle();
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDisconnected;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    int mIndex;          // index in ImsPhoneCallTracker.connections[], -1 if unassigned
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        // The GSM index is 1 + this
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    */
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * These time/timespan values are based on System.currentTimeMillis(),
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * i.e., "wall clock" time.
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private long mDisconnectTime;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private UUSInfo mUusInfo;
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Handler mHandler;
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PowerManager.WakeLock mPartialWakeLock;
85a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
86fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    // The cached connect time of the connection when it turns into a conference.
87fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    private long mConferenceConnectTime = 0;
88fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
896bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    // The cached delay to be used between DTMF tones fetched from carrier config.
906bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private int mDtmfToneDelay = 0;
916bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
928bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    private boolean mIsEmergency = false;
938bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
942e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
95db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Used to indicate that video state changes detected by
96db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * {@link #updateMediaCapabilities(ImsCall)} should be ignored.  When a video state change from
97db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * unpaused to paused occurs, we set this flag and then update the existing video state when
98db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * new {@link #onReceiveSessionModifyResponse(int, VideoProfile, VideoProfile)} callbacks come
99db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * in.  When the video un-pauses we continue receiving the video state updates.
100db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
101db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    private boolean mShouldIgnoreVideoStateChanges = false;
102db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Event Constants
104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DTMF_DONE = 1;
105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_PAUSE_DONE = 2;
106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_NEXT_POST_DIAL = 3;
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
1086bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private static final int EVENT_DTMF_DELAY_DONE = 5;
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Inner Classes
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    class MyHandler extends Handler {
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        MyHandler(Looper l) {super(l);}
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        handleMessage(Message msg) {
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (msg.what) {
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_NEXT_POST_DIAL:
1256bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DELAY_DONE:
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_PAUSE_DONE:
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    processNextPostDialChar();
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_WAKE_LOCK_TIMEOUT:
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    releaseWakeLock();
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1326bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DONE:
1336bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // We may need to add a delay specified by carrier between DTMF tones that are
1346bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // sent out.
1356bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
1366bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                            mDtmfToneDelay);
1376bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    break;
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is probably an MT call */
145f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
14608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh           ImsPhoneCall parent, boolean isUnknown) {
147c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1486bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
158d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mNumberPresentation = ImsCallProfile.OIRToPresentation(
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
160d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
1626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            updateMediaCapabilities(imsCall);
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
16808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mIsIncoming = !isUnknown;
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUusInfo = null;
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
172553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
173553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
174553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // connection is not likely to be associated with a TelephonyConnection yet).
175553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        updateExtras(imsCall);
176553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
17808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mParent.attach(this,
17908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));
1806bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
1816bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is an MO call, created when dialing */
185f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
1868bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            ImsPhoneCall parent, boolean isEmergency) {
187c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1886bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDialString = dialString;
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //mIndex = -1;
200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIsIncoming = false;
202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapName = null;
203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        parent.attachFake(this, ImsPhoneCall.State.DIALING);
2096bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2108bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        mIsEmergency = isEmergency;
2118bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
2126bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static boolean
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    equalsHandlesNulls (Object a, Object b) {
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (a == null) ? (b == null) : a.equals (b);
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
223f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
2242e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyLocalCallCapabilities - localProfile = "+localProfile);
225f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2262e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
227f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
228f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (localProfile.mCallType) {
229f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2302e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // Fall-through
231f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
232f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2332e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
234f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
235f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
236f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
237f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
238f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
239f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
2402e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
241f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2422e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
243f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
244f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (remoteProfile.mCallType) {
245f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2462e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // fall-through
247f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
248f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2492e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
250f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
251f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
252f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
253f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
254f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public String getOrigDialString(){
257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDialString;
258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall getCall() {
262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mParent;
263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getDisconnectTime() {
267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDisconnectTime;
268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldingStartTime() {
272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mHoldingStartTime;
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldDurationMillis() {
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (getState() != ImsPhoneCall.State.HOLDING) {
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // If not holding, return 0
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return 0;
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return SystemClock.elapsedRealtime() - mHoldingStartTime;
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void setDisconnectCause(int cause) {
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = cause;
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
28933cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    @Override
29033cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    public String getVendorDisconnectCause() {
29133cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      return null;
29233cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
29333cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCallTracker getOwner () {
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mOwner;
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall.State getState() {
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mDisconnected) {
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return ImsPhoneCall.State.DISCONNECTED;
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return super.getState();
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void hangup() throws CallStateException {
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.hangup(this);
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("disconnected");
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void separate() throws CallStateException {
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new CallStateException ("not supported");
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWaitChar() {
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WAIT) {
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WAIT but was " + mPostDialState);
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWildChar(String str) {
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WILD) {
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WILD but was " + mPostDialState);
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // make a new postDialString, with the wild char replacement string
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // at the beginning, followed by the remaining postDialString.
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        StringBuilder buf = new StringBuilder(str);
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        buf.append(mPostDialString.substring(mNextPostDialChar));
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = buf.toString();
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNextPostDialChar = 0;
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPostDialString);
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void cancelPostDial() {
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.CANCELLED);
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Called when this Connection is being hung up locally (eg, user pressed "end")
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onHangupLocal() {
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = DisconnectCause.LOCAL;
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** Called when the connection has been disconnected */
373c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
374c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean onDisconnect(int cause) {
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
3761999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
3771999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn            mCause = cause;
3781999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        }
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return onDisconnect();
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
382f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean onDisconnect() {
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //mIndex = -1;
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnectTime = System.currentTimeMillis();
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnected = true;
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.mPhone.notifyDisconnect(this);
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mParent != null) {
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                changed = mParent.connectionDisconnected(this);
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "onDisconnect: no parent");
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mImsCall != null) mImsCall.close();
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mImsCall = null;
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return changed;
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * An incoming or outgoing call has connected
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onConnectedInOrOut() {
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTime = System.currentTimeMillis();
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTimeReal = SystemClock.elapsedRealtime();
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDuration = 0;
414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mIsIncoming) {
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // outgoing calls only
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processNextPostDialChar();
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onStartedHolding() {
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHoldingStartTime = SystemClock.elapsedRealtime();
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Performs the appropriate action for a post-dial char, but does not
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * notify application. returns false if the character is invalid and
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * should be ignored
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processPostDialChar(char c) {
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (PhoneNumberUtils.is12Key(c)) {
438d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            mOwner.sendDtmf(c, mHandler.obtainMessage(EVENT_DTMF_DONE));
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.PAUSE) {
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // From TS 22.101:
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // It continues...
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Upon the called party answering the UE shall send the DTMF digits
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // automatically to the network after a delay of 3 seconds( 20 ).
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The digits shall be sent according to the procedures and timing
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // "DTMF Control Digits Separator" shall be used by the ME to
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // distinguish between the addressing digits (i.e. the phone number)
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // and the DTMF digits. Upon subsequent occurrences of the
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // separator,
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // the UE shall pause again for 3 seconds ( 20 ) before sending
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // any further DTMF digits.
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    PAUSE_DELAY_MILLIS);
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WAIT) {
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WAIT);
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WILD) {
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WILD);
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return false;
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return true;
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
466032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan    protected void finalize() {
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processNextPostDialChar() {
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        char c = 0;
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant postDialHandler;
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState == PostDialState.CANCELLED) {
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
480d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.COMPLETE);
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // notifyMessage.arg1 is 0 on complete
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = 0;
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            boolean isValid;
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.STARTED);
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = mPostDialString.charAt(mNextPostDialChar++);
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            isValid = processPostDialChar(c);
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (!isValid) {
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Will call processNextPostDialChar
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Don't notify application
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5034567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        notifyPostDialListenersNextChar(c);
5044567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen
5054567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        // TODO: remove the following code since the handler no longer executes anything.
50693c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan        postDialHandler = mOwner.mPhone.getPostDialHandler();
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Message notifyMessage;
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (postDialHandler != null
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The AsyncResult.result is the Connection object
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            PostDialState state = mPostDialState;
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.result = this;
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.userObj = state;
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // arg1 is the character that was/is being processed
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.arg1 = c;
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
521d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //Rlog.v(LOG_TAG,
522d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.sendToTarget();
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Set post dial state and acquire wake lock while switching to "started"
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state, the wake lock will be released if state switches out of "started"
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @param s new PostDialState
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void setPostDialState(PostDialState s) {
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.STARTED
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s == PostDialState.STARTED) {
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            acquireWakeLock();
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPostDialState == PostDialState.STARTED
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s != PostDialState.STARTED) {
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            releaseWakeLock();
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialState = s;
545d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        notifyPostDialListeners();
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    createWakeLock(Context context) {
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    acquireWakeLock() {
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "acquireWakeLock");
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock.acquire();
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
56097fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com    void
561a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    releaseWakeLock() {
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized(mPartialWakeLock) {
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPartialWakeLock.isHeld()) {
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "releaseWakeLock");
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPartialWakeLock.release();
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
570c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    private void fetchDtmfToneDelay(Phone phone) {
5716bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        CarrierConfigManager configMgr = (CarrierConfigManager)
5726bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
5736bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
5746bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        if (b != null) {
5756bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
5766bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        }
5776bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    }
5786bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getNumberPresentation() {
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mNumberPresentation;
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UUSInfo getUUSInfo() {
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mUusInfo;
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Connection getOrigConnection() {
591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public boolean isMultiparty() {
596541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return mImsCall != null && mImsCall.isMultiparty();
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
599ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    /**
600ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
601ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
602ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
603ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *
604ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
605ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *      {@code false} otherwise.
606ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     */
607c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
608ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    public boolean isConferenceHost() {
609ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        if (mImsCall == null) {
610ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            return false;
611ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        }
612ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        return mImsCall.isConferenceHost();
613ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    }
614ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
615c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
616c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean isMemberOfPeerConference() {
617c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        return !isConferenceHost();
618c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    }
619c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
620f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsCall getImsCall() {
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mImsCall;
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
624f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void setImsCall(ImsCall imsCall) {
625a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
628f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void changeParent(ImsPhoneCall parent) {
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6326a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
6336a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
6346a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *     changed, and {@code false} otherwise.
6356a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
636f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.ACTIVE) {
638707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // If the state of the call is active, but there is a pending request to the RIL to hold
639707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // the call, we will skip this update.  This is really a signalling delay or failure
640707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // from the RIL, but we will prevent it from going through as we will end up erroneously
641707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // making this call active when really it should be on hold.
642707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (imsCall.isPendingHold()) {
643707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
644707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                return false;
645707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
646707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
6476a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                onConnectedInOrOut();
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6516a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //mForegroundCall should be IDLE
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //when accepting WAITING call
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //before accept WAITING call,
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //the ACTIVE call should be held ahead
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.detach(this);
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent = mOwner.mForegroundCall;
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.attach(this);
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (state == ImsPhoneCall.State.HOLDING) {
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onStartedHolding();
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
664549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen        boolean updateParent = mParent.update(this, imsCall, state);
665eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
66621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
66721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateExtras = updateExtras(imsCall);
668ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
66975f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getPreciseDisconnectCause() {
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return 0;
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
676d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn
677d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    /**
678d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * Notifies this Connection of a request to disconnect a participant of the conference managed
679d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * by the connection.
680d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     *
681d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
682d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     */
683d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    @Override
684d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    public void onDisconnectConferenceParticipant(Uri endpoint) {
685d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        ImsCall imsCall = getImsCall();
686d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        if (imsCall == null) {
687d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            return;
688d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
689d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        try {
690d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            imsCall.removeParticipants(new String[]{endpoint.toString()});
691d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        } catch (ImsException e) {
692d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            // No session in place -- no change
693d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
694d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn                    "Failed to disconnect endpoint = " + endpoint);
695d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
696d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
697541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn
698541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    /**
699fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
700fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * this phone connection.
701fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     *
702fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @param conferenceConnectTime The conference connect time.
703fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
704fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public void setConferenceConnectTime(long conferenceConnectTime) {
705fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        mConferenceConnectTime = conferenceConnectTime;
706fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
707fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
708fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
709fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @return The conference connect time.
710fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
711fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public long getConferenceConnectTime() {
712fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        return mConferenceConnectTime;
713fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
714fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
715fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
716eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * Check for a change in the address display related fields for the {@link ImsCall}, and
717eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * update the {@link ImsPhoneConnection} with this information.
718eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     *
719eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @param imsCall The call to check for changes in address display fields.
720eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @return Whether the address display fields have been changed.
721eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     */
72227e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati    public boolean updateAddressDisplay(ImsCall imsCall) {
723eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (imsCall == null) {
724eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            return false;
725eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
726eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
727eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean changed = false;
728eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        ImsCallProfile callProfile = imsCall.getCallProfile();
729eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (callProfile != null) {
730eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
731eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
732eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int nump = ImsCallProfile.OIRToPresentation(
733eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
734eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int namep = ImsCallProfile.OIRToPresentation(
735eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
736eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (Phone.DEBUG_PHONE) {
73777a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu                Rlog.d(LOG_TAG, "address = " + Rlog.pii(LOG_TAG, address) + " name = " + name +
738eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                        " nump = " + nump + " namep = " + namep);
739eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
740eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if(equalsHandlesNulls(mAddress, address)) {
741eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mAddress = address;
742eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
743eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
744eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (TextUtils.isEmpty(name)) {
745eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                if (!TextUtils.isEmpty(mCnapName)) {
746eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    mCnapName = "";
747eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    changed = true;
748eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                }
749eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            } else if (!name.equals(mCnapName)) {
750eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mCnapName = name;
751eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
752eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
753eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (mNumberPresentation != nump) {
754eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mNumberPresentation = nump;
755eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
756eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
757eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (mCnapNamePresentation != namep) {
758eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mCnapNamePresentation = namep;
759eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
760eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
761eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
762eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        return changed;
763eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
764eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
765eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    /**
7666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
7676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * update the {@link ImsPhoneConnection} with this information.
7686a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
7696a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param imsCall The call to check for changes in media capabilities.
7706a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return Whether the media capabilities have been changed.
7716a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
772d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    public boolean updateMediaCapabilities(ImsCall imsCall) {
7736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (imsCall == null) {
7746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return false;
7756a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
7766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
7776a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        boolean changed = false;
7786a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
7796a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        try {
780e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            // The actual call profile (negotiated between local and peer).
781e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
7826a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
783e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            if (negotiatedCallProfile != null) {
784288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int oldVideoState = getVideoState();
785288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int newVideoState = ImsCallProfile
786288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);
787e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
788288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (oldVideoState != newVideoState) {
789db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
790db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // below.  When the video enters a paused state, subsequent changes to the video
791db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
792db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // we will be updating the current video state while paused to include any
793db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // changes the modem reports via the video provider.  When the video enters an
794db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // unpaused state, we will resume passing the video states from the modem as is.
795db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (VideoProfile.isPaused(oldVideoState) &&
796db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            !VideoProfile.isPaused(newVideoState)) {
797db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered un-paused state; recognize updates from now on; we want to
798db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // ensure that the new un-paused state is propagated to Telecom, so change
799db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // this now.
800db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = false;
801db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
802db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
803db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!mShouldIgnoreVideoStateChanges) {
804db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        setVideoState(newVideoState);
805db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        changed = true;
806db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    } else {
807db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
808db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                                "due to paused state.");
809db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
810db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
811db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!VideoProfile.isPaused(oldVideoState) &&
812db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            VideoProfile.isPaused(newVideoState)) {
813db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered pause state; ignore updates until un-paused.  We do this
814db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // after setVideoState is called above to ensure Telecom is notified that
815db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // the device has entered paused state.
816db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = true;
817db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
818e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn                }
819e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            }
820e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
821f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Check for a change in the capabilities for the call and update
822f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // {@link ImsPhoneConnection} with this information.
823f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            int capabilities = getConnectionCapabilities();
8242e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
8252e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            // Use carrier config to determine if downgrading directly to audio-only is supported.
8262e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
8272e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = addCapability(capabilities,
8282e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8292e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8302e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            } else {
8312e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = removeCapability(capabilities,
8322e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8332e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8342e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            }
8352e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
836f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current local call capabilities which might be voice or video or both.
837f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
838f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
8396a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (localCallProfile != null) {
840f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
8416a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8426a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
843f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current remote call capabilities which might be voice or video or both.
844f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
845f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
846288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (remoteCallProfile != null) {
847f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
848f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            }
849f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            if (getConnectionCapabilities() != capabilities) {
850f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                setConnectionCapabilities(capabilities);
851f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                changed = true;
852288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
853288268d5528e0df03f348e303954813cb188c55bRekha Kumar
8546a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            int newAudioQuality =
8556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
8566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (getAudioQuality() != newAudioQuality) {
8576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                setAudioQuality(newAudioQuality);
8586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                changed = true;
8596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        } catch (ImsException e) {
8616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            // No session in place -- no change
8626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
8636a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return changed;
8656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
8666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
8682e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
8692e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * The call is considered to be a WIFI call if the extra value is
8702e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
8712e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     *
8722e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * @param extras The ImsCallProfile extras.
8732e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     */
8742e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    private void updateWifiStateFromExtras(Bundle extras) {
875d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
876d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
8772e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
878d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            ImsCall call = getImsCall();
879d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            boolean isWifi = false;
880d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            if (call != null) {
881d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                isWifi = call.isWifiCall();
882d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            }
8832e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
8842e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            // Report any changes
8852e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            if (isWifi() != isWifi) {
8862e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn                setWifi(isWifi);
8872e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            }
8882e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        }
8892e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
8902e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
8912e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
89221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * Check for a change in call extras of {@link ImsCall}, and
89321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * update the {@link ImsPhoneConnection} accordingly.
89421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     *
89521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @param imsCall The call to check for changes in extras.
89621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @return Whether the extras fields have been changed.
89721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     */
89821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     boolean updateExtras(ImsCall imsCall) {
89921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (imsCall == null) {
90021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
90121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
90221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
90321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final ImsCallProfile callProfile = imsCall.getCallProfile();
90421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
90521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null && DBG) {
90621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            Rlog.d(LOG_TAG, "Call profile extras are null.");
90721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
90821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
90921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final boolean changed = !areBundlesEqual(extras, mExtras);
91021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (changed) {
9112e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            updateWifiStateFromExtras(extras);
9122e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
91321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.clear();
91421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.putAll(extras);
91521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            setConnectionExtras(mExtras);
91621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
91721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return changed;
91821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
91921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
92021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
92121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null || newExtras == null) {
92221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return extras == newExtras;
92321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
92421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
92521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras.size() != newExtras.size()) {
92621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
92721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
92821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
92921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        for(String key : extras.keySet()) {
93021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            if (key != null) {
93121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object value = extras.get(key);
93221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object newValue = newExtras.get(key);
93321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                if (!Objects.equals(value, newValue)) {
93421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                    return false;
93521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                }
93621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            }
93721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
93821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return true;
93921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
94021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
94121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    /**
9426a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
943363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
944363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
945363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * there is no remote restrict cause.
9466a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
9476a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param localCallProfile The local call profile.
9486a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param remoteCallProfile The remote call profile.
9496a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return The audio quality.
9506a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
9516a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    private int getAudioQualityFromCallProfile(
9526a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
9536a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (localCallProfile == null || remoteCallProfile == null
9546a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile == null) {
9556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return AUDIO_QUALITY_STANDARD;
9566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
9576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
958363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
959363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
960363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
961363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
962363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
963363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);
964363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
965363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
9666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
9676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile.mAudioQuality
968363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
969363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || isEvsCodecHighDef)
9706a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
9716a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
9726a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
975541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
976541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * use in log statements.
977541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     *
978541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * @return String representation of call.
979541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     */
980541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    @Override
981541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    public String toString() {
982541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        StringBuilder sb = new StringBuilder();
983541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("[ImsPhoneConnection objId: ");
984541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append(System.identityHashCode(this));
9851a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" telecomCallID: ");
9861a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(getTelecomCallId());
9871a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" address: ");
98877a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu        sb.append(Rlog.pii(LOG_TAG, getAddress()));
9891a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" ImsCall: ");
990541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        if (mImsCall == null) {
991541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn            sb.append("null");
992541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        } else {
993541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn            sb.append(mImsCall);
994541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        }
995541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("]");
996541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return sb.toString();
997541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
9988bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
9998bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    /**
10008bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * Indicates whether current phone connection is emergency or not
10018bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * @return boolean: true if emergency, false otherwise
10028bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     */
10038bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    protected boolean isEmergency() {
10048bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        return mIsEmergency;
10058bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
1006db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1007db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    /**
1008db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
1009db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * responses received.
1010db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     *
1011db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param status The status of the original request.
1012db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param requestProfile The requested video profile.
1013db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param responseProfile The response upon video profile.
1014db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
1015db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    @Override
1016db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
1017db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            VideoProfile responseProfile) {
1018db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
1019db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                mShouldIgnoreVideoStateChanges) {
1020db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int currentVideoState = getVideoState();
1021db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int newVideoState = responseProfile.getVideoState();
1022db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1023db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // If the current video state is paused, the modem will not send us any changes to
1024db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // the TX and RX bits of the video state.  Until the video is un-paused we will
1025db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // "fake out" the video state by applying the changes that the modem reports via a
1026db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // response.
1027db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1028db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // First, find out whether there was a change to the TX or RX bits:
1029db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int changedBits = currentVideoState ^ newVideoState;
1030db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
1031db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (changedBits == 0) {
1032db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                // No applicable change, bail out.
1033db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                return;
1034db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1035db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1036db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn off any existing bits that changed.
1037db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState &= ~(changedBits & currentVideoState);
1038db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn on any new bits that turned on.
1039db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState |= changedBits & newVideoState;
1040db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1041db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
1042db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
1043db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " / " +
1044db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
1045db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " while paused ; sending new videoState = " +
1046db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(currentVideoState));
1047db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            setVideoState(currentVideoState);
1048db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        }
1049db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1050a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1051