ImsPhoneConnection.java revision 34310e958f52099ce3a2e74a8e3c4f631a241529
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
103359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    private ImsVideoCallProviderWrapper mImsVideoCallProviderWrapper;
104359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
105222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    private int mPreciseDisconnectCause = 0;
106222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Event Constants
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DTMF_DONE = 1;
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_PAUSE_DONE = 2;
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_NEXT_POST_DIAL = 3;
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
1126bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private static final int EVENT_DTMF_DELAY_DONE = 5;
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Inner Classes
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    class MyHandler extends Handler {
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        MyHandler(Looper l) {super(l);}
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        handleMessage(Message msg) {
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (msg.what) {
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_NEXT_POST_DIAL:
1296bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DELAY_DONE:
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_PAUSE_DONE:
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    processNextPostDialChar();
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_WAKE_LOCK_TIMEOUT:
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    releaseWakeLock();
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1366bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DONE:
1376bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // We may need to add a delay specified by carrier between DTMF tones that are
1386bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // sent out.
1396bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
1406bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                            mDtmfToneDelay);
1416bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    break;
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is probably an MT call */
149f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
15008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh           ImsPhoneCall parent, boolean isUnknown) {
151c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1526bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
162d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mNumberPresentation = ImsCallProfile.OIRToPresentation(
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
164d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
1666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            updateMediaCapabilities(imsCall);
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mIsIncoming = !isUnknown;
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUusInfo = null;
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
176553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
177553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
178553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // connection is not likely to be associated with a TelephonyConnection yet).
179553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        updateExtras(imsCall);
180553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
18208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mParent.attach(this,
18308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));
1846bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
1856bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
186c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
187c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
188c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
189c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
190c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is an MO call, created when dialing */
194f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
1958bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            ImsPhoneCall parent, boolean isEmergency) {
196c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1976bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDialString = dialString;
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //mIndex = -1;
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIsIncoming = false;
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapName = null;
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        parent.attachFake(this, ImsPhoneCall.State.DIALING);
2186bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2198bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        mIsEmergency = isEmergency;
2208bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
2216bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
222c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
223c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
224c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
225c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
226c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static boolean
233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    equalsHandlesNulls (Object a, Object b) {
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (a == null) ? (b == null) : a.equals (b);
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
237f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
2382e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyLocalCallCapabilities - localProfile = "+localProfile);
239f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2402e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
241f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
242f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (localProfile.mCallType) {
243f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2442e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // Fall-through
245f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
246f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2472e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
248f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
249f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
250f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
251f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
252f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
253f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
2542e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
255f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2562e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
257f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
258f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (remoteProfile.mCallType) {
259f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2602e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // fall-through
261f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
262f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2632e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
264f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
265f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
266f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
267f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
268f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public String getOrigDialString(){
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDialString;
272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall getCall() {
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mParent;
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getDisconnectTime() {
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDisconnectTime;
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldingStartTime() {
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mHoldingStartTime;
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldDurationMillis() {
291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (getState() != ImsPhoneCall.State.HOLDING) {
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // If not holding, return 0
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return 0;
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return SystemClock.elapsedRealtime() - mHoldingStartTime;
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void setDisconnectCause(int cause) {
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = cause;
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
30333cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    @Override
30433cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    public String getVendorDisconnectCause() {
30533cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      return null;
30633cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
30733cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCallTracker getOwner () {
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mOwner;
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall.State getState() {
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mDisconnected) {
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return ImsPhoneCall.State.DISCONNECTED;
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return super.getState();
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void hangup() throws CallStateException {
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.hangup(this);
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("disconnected");
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void separate() throws CallStateException {
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new CallStateException ("not supported");
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWaitChar() {
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WAIT) {
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WAIT but was " + mPostDialState);
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWildChar(String str) {
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WILD) {
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WILD but was " + mPostDialState);
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // make a new postDialString, with the wild char replacement string
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // at the beginning, followed by the remaining postDialString.
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        StringBuilder buf = new StringBuilder(str);
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        buf.append(mPostDialString.substring(mNextPostDialChar));
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = buf.toString();
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNextPostDialChar = 0;
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPostDialString);
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void cancelPostDial() {
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.CANCELLED);
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Called when this Connection is being hung up locally (eg, user pressed "end")
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onHangupLocal() {
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = DisconnectCause.LOCAL;
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** Called when the connection has been disconnected */
387c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
388c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean onDisconnect(int cause) {
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
3901999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
3911999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn            mCause = cause;
3921999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        }
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return onDisconnect();
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
396f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean onDisconnect() {
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //mIndex = -1;
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnectTime = System.currentTimeMillis();
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnected = true;
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.mPhone.notifyDisconnect(this);
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mParent != null) {
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                changed = mParent.connectionDisconnected(this);
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "onDisconnect: no parent");
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
41334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            synchronized (this) {
41434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                if (mImsCall != null) mImsCall.close();
41534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                mImsCall = null;
41634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return changed;
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * An incoming or outgoing call has connected
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onConnectedInOrOut() {
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTime = System.currentTimeMillis();
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTimeReal = SystemClock.elapsedRealtime();
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDuration = 0;
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mIsIncoming) {
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // outgoing calls only
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processNextPostDialChar();
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onStartedHolding() {
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHoldingStartTime = SystemClock.elapsedRealtime();
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Performs the appropriate action for a post-dial char, but does not
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * notify application. returns false if the character is invalid and
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * should be ignored
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processPostDialChar(char c) {
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (PhoneNumberUtils.is12Key(c)) {
454d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            mOwner.sendDtmf(c, mHandler.obtainMessage(EVENT_DTMF_DONE));
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.PAUSE) {
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // From TS 22.101:
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // It continues...
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Upon the called party answering the UE shall send the DTMF digits
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // automatically to the network after a delay of 3 seconds( 20 ).
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The digits shall be sent according to the procedures and timing
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // "DTMF Control Digits Separator" shall be used by the ME to
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // distinguish between the addressing digits (i.e. the phone number)
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // and the DTMF digits. Upon subsequent occurrences of the
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // separator,
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // the UE shall pause again for 3 seconds ( 20 ) before sending
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // any further DTMF digits.
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    PAUSE_DELAY_MILLIS);
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WAIT) {
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WAIT);
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WILD) {
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WILD);
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return false;
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return true;
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
482032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan    protected void finalize() {
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processNextPostDialChar() {
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        char c = 0;
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant postDialHandler;
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState == PostDialState.CANCELLED) {
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
496d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.COMPLETE);
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // notifyMessage.arg1 is 0 on complete
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = 0;
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            boolean isValid;
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.STARTED);
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = mPostDialString.charAt(mNextPostDialChar++);
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            isValid = processPostDialChar(c);
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (!isValid) {
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Will call processNextPostDialChar
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Don't notify application
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5194567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        notifyPostDialListenersNextChar(c);
5204567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen
5214567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        // TODO: remove the following code since the handler no longer executes anything.
52293c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan        postDialHandler = mOwner.mPhone.getPostDialHandler();
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Message notifyMessage;
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (postDialHandler != null
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The AsyncResult.result is the Connection object
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            PostDialState state = mPostDialState;
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.result = this;
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.userObj = state;
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // arg1 is the character that was/is being processed
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.arg1 = c;
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
537d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //Rlog.v(LOG_TAG,
538d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.sendToTarget();
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Set post dial state and acquire wake lock while switching to "started"
545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state, the wake lock will be released if state switches out of "started"
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @param s new PostDialState
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void setPostDialState(PostDialState s) {
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.STARTED
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s == PostDialState.STARTED) {
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            acquireWakeLock();
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPostDialState == PostDialState.STARTED
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s != PostDialState.STARTED) {
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            releaseWakeLock();
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialState = s;
561d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        notifyPostDialListeners();
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    createWakeLock(Context context) {
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    acquireWakeLock() {
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "acquireWakeLock");
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock.acquire();
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
57697fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com    void
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    releaseWakeLock() {
578b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan        if (mPartialWakeLock != null) {
579b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan            synchronized (mPartialWakeLock) {
580b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan                if (mPartialWakeLock.isHeld()) {
581b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan                    Rlog.d(LOG_TAG, "releaseWakeLock");
582b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan                    mPartialWakeLock.release();
583b1fdcf01045090315c5b91d7539007d79f34c9ecAmit Mahajan                }
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
588c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    private void fetchDtmfToneDelay(Phone phone) {
5896bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        CarrierConfigManager configMgr = (CarrierConfigManager)
5906bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
5916bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
5926bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        if (b != null) {
5936bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
5946bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        }
5956bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    }
5966bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getNumberPresentation() {
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mNumberPresentation;
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UUSInfo getUUSInfo() {
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mUusInfo;
605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Connection getOrigConnection() {
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
61334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isMultiparty() {
614541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return mImsCall != null && mImsCall.isMultiparty();
615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
617ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    /**
618ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
619ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
620ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
621ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *
622ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
623ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *      {@code false} otherwise.
624ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     */
625c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
62634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isConferenceHost() {
62734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        return mImsCall != null && mImsCall.isConferenceHost();
628ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    }
629ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
630c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
631c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean isMemberOfPeerConference() {
632c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        return !isConferenceHost();
633c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    }
634c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
63534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized ImsCall getImsCall() {
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mImsCall;
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
63934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized void setImsCall(ImsCall imsCall) {
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
643f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void changeParent(ImsPhoneCall parent) {
644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6476a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
6486a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
6496a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *     changed, and {@code false} otherwise.
6506a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
651f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.ACTIVE) {
653707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // If the state of the call is active, but there is a pending request to the RIL to hold
654707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // the call, we will skip this update.  This is really a signalling delay or failure
655707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // from the RIL, but we will prevent it from going through as we will end up erroneously
656707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // making this call active when really it should be on hold.
657707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (imsCall.isPendingHold()) {
658707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
659707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                return false;
660707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
661707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
6626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                onConnectedInOrOut();
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
667a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //mForegroundCall should be IDLE
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //when accepting WAITING call
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //before accept WAITING call,
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //the ACTIVE call should be held ahead
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.detach(this);
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent = mOwner.mForegroundCall;
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.attach(this);
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (state == ImsPhoneCall.State.HOLDING) {
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onStartedHolding();
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
679549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen        boolean updateParent = mParent.update(this, imsCall, state);
680eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
68121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
68221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateExtras = updateExtras(imsCall);
683ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
68475f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getPreciseDisconnectCause() {
689222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        return mPreciseDisconnectCause;
690222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
691222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
692222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    public void setPreciseDisconnectCause(int cause) {
693222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        mPreciseDisconnectCause = cause;
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
695d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn
696d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    /**
697d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * Notifies this Connection of a request to disconnect a participant of the conference managed
698d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * by the connection.
699d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     *
700d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
701d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     */
702d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    @Override
703d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    public void onDisconnectConferenceParticipant(Uri endpoint) {
704d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        ImsCall imsCall = getImsCall();
705d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        if (imsCall == null) {
706d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            return;
707d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
708d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        try {
709d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            imsCall.removeParticipants(new String[]{endpoint.toString()});
710d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        } catch (ImsException e) {
711d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            // No session in place -- no change
712d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
713d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn                    "Failed to disconnect endpoint = " + endpoint);
714d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
715d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
716541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn
717541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    /**
718fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
719fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * this phone connection.
720fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     *
721fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @param conferenceConnectTime The conference connect time.
722fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
723fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public void setConferenceConnectTime(long conferenceConnectTime) {
724fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        mConferenceConnectTime = conferenceConnectTime;
725fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
726fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
727fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
728fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @return The conference connect time.
729fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
730fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public long getConferenceConnectTime() {
731fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        return mConferenceConnectTime;
732fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
733fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
734fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
735eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * Check for a change in the address display related fields for the {@link ImsCall}, and
736eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * update the {@link ImsPhoneConnection} with this information.
737eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     *
738eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @param imsCall The call to check for changes in address display fields.
739eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @return Whether the address display fields have been changed.
740eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     */
74127e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati    public boolean updateAddressDisplay(ImsCall imsCall) {
742eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (imsCall == null) {
743eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            return false;
744eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
745eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
746eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean changed = false;
747eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        ImsCallProfile callProfile = imsCall.getCallProfile();
748eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (callProfile != null) {
749eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
750eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
751eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int nump = ImsCallProfile.OIRToPresentation(
752eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
753eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int namep = ImsCallProfile.OIRToPresentation(
754eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
755eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (Phone.DEBUG_PHONE) {
75677a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu                Rlog.d(LOG_TAG, "address = " + Rlog.pii(LOG_TAG, address) + " name = " + name +
757eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                        " nump = " + nump + " namep = " + namep);
758eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
759eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if(equalsHandlesNulls(mAddress, address)) {
760eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mAddress = address;
761eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
762eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
763eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (TextUtils.isEmpty(name)) {
764eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                if (!TextUtils.isEmpty(mCnapName)) {
765eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    mCnapName = "";
766eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    changed = true;
767eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                }
768eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            } else if (!name.equals(mCnapName)) {
769eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mCnapName = name;
770eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
771eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
772eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (mNumberPresentation != nump) {
773eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mNumberPresentation = nump;
774eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
775eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
776eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (mCnapNamePresentation != namep) {
777eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                mCnapNamePresentation = namep;
778eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                changed = true;
779eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
780eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
781eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        return changed;
782eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
783eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
784eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    /**
7856a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
7866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * update the {@link ImsPhoneConnection} with this information.
7876a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
7886a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param imsCall The call to check for changes in media capabilities.
7896a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return Whether the media capabilities have been changed.
7906a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
791d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    public boolean updateMediaCapabilities(ImsCall imsCall) {
7926a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (imsCall == null) {
7936a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return false;
7946a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
7956a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
7966a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        boolean changed = false;
7976a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
7986a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        try {
799e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            // The actual call profile (negotiated between local and peer).
800e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
8016a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
802e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            if (negotiatedCallProfile != null) {
803288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int oldVideoState = getVideoState();
804288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int newVideoState = ImsCallProfile
805288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);
806e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
807288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (oldVideoState != newVideoState) {
808db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
809db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // below.  When the video enters a paused state, subsequent changes to the video
810db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
811db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // we will be updating the current video state while paused to include any
812db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // changes the modem reports via the video provider.  When the video enters an
813db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // unpaused state, we will resume passing the video states from the modem as is.
814db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (VideoProfile.isPaused(oldVideoState) &&
815db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            !VideoProfile.isPaused(newVideoState)) {
816db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered un-paused state; recognize updates from now on; we want to
817db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // ensure that the new un-paused state is propagated to Telecom, so change
818db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // this now.
819db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = false;
820db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
821db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
822db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!mShouldIgnoreVideoStateChanges) {
823db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        setVideoState(newVideoState);
824db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        changed = true;
825db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    } else {
826db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
827db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                                "due to paused state.");
828db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
829db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
830db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!VideoProfile.isPaused(oldVideoState) &&
831db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            VideoProfile.isPaused(newVideoState)) {
832db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered pause state; ignore updates until un-paused.  We do this
833db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // after setVideoState is called above to ensure Telecom is notified that
834db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // the device has entered paused state.
835db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = true;
836db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
837e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn                }
838e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            }
839e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
840f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Check for a change in the capabilities for the call and update
841f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // {@link ImsPhoneConnection} with this information.
842f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            int capabilities = getConnectionCapabilities();
8432e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
8442e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            // Use carrier config to determine if downgrading directly to audio-only is supported.
8452e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
8462e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = addCapability(capabilities,
8472e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8482e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8492e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            } else {
8502e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = removeCapability(capabilities,
8512e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
8522e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
8532e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            }
8542e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
855f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current local call capabilities which might be voice or video or both.
856f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
857f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
8586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (localCallProfile != null) {
859f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
8606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
862f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current remote call capabilities which might be voice or video or both.
863f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
864f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
865288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (remoteCallProfile != null) {
866f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
867f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            }
868f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            if (getConnectionCapabilities() != capabilities) {
869f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                setConnectionCapabilities(capabilities);
870f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                changed = true;
871288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
872288268d5528e0df03f348e303954813cb188c55bRekha Kumar
8736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            int newAudioQuality =
8746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
8756a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (getAudioQuality() != newAudioQuality) {
8766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                setAudioQuality(newAudioQuality);
8776a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                changed = true;
8786a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
8796a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        } catch (ImsException e) {
8806a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            // No session in place -- no change
8816a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
8826a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8836a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return changed;
8846a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
8856a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
8872e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
8882e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * The call is considered to be a WIFI call if the extra value is
8892e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
8902e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     *
8912e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * @param extras The ImsCallProfile extras.
8922e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     */
8932e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    private void updateWifiStateFromExtras(Bundle extras) {
894d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
895d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
8962e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
897d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            ImsCall call = getImsCall();
898d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            boolean isWifi = false;
899d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            if (call != null) {
900d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                isWifi = call.isWifiCall();
901d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            }
9022e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
9032e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            // Report any changes
9042e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            if (isWifi() != isWifi) {
9052e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn                setWifi(isWifi);
9062e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            }
9072e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        }
9082e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
9092e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
9102e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
91121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * Check for a change in call extras of {@link ImsCall}, and
91221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * update the {@link ImsPhoneConnection} accordingly.
91321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     *
91421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @param imsCall The call to check for changes in extras.
91521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @return Whether the extras fields have been changed.
91621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     */
91721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     boolean updateExtras(ImsCall imsCall) {
91821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (imsCall == null) {
91921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
92021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
92121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
92221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final ImsCallProfile callProfile = imsCall.getCallProfile();
92321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
92421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null && DBG) {
92521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            Rlog.d(LOG_TAG, "Call profile extras are null.");
92621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
92721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
92821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final boolean changed = !areBundlesEqual(extras, mExtras);
92921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (changed) {
9302e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            updateWifiStateFromExtras(extras);
9312e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
93221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.clear();
93321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.putAll(extras);
93421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            setConnectionExtras(mExtras);
93521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
93621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return changed;
93721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
93821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
93921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
94021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null || newExtras == null) {
94121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return extras == newExtras;
94221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
94321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
94421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras.size() != newExtras.size()) {
94521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
94621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
94721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
94821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        for(String key : extras.keySet()) {
94921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            if (key != null) {
95021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object value = extras.get(key);
95121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object newValue = newExtras.get(key);
95221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                if (!Objects.equals(value, newValue)) {
95321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                    return false;
95421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                }
95521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            }
95621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
95721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return true;
95821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
95921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
96021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    /**
9616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
962363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
963363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
964363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * there is no remote restrict cause.
9656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
9666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param localCallProfile The local call profile.
9676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param remoteCallProfile The remote call profile.
9686a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return The audio quality.
9696a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
9706a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    private int getAudioQualityFromCallProfile(
9716a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
9726a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (localCallProfile == null || remoteCallProfile == null
9736a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile == null) {
9746a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return AUDIO_QUALITY_STANDARD;
9756a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
9766a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
977363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
978363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
979363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
980363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
981363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
982363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);
983363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
984363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
9856a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
9866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile.mAudioQuality
987363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
988363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || isEvsCodecHighDef)
9896a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
9906a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
9916a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9926a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9936a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
994541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
995541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * use in log statements.
996541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     *
997541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * @return String representation of call.
998541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     */
999541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    @Override
1000541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    public String toString() {
1001541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        StringBuilder sb = new StringBuilder();
1002541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("[ImsPhoneConnection objId: ");
1003541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append(System.identityHashCode(this));
10041a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" telecomCallID: ");
10051a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(getTelecomCallId());
10061a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" address: ");
100777a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu        sb.append(Rlog.pii(LOG_TAG, getAddress()));
10081a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" ImsCall: ");
100934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        synchronized (this) {
101034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            if (mImsCall == null) {
101134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append("null");
101234310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            } else {
101334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append(mImsCall);
101434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
1015541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        }
1016541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("]");
1017541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return sb.toString();
1018541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
10198bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1020359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    @Override
1021359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1022359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        super.setVideoProvider(videoProvider);
1023359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1024359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1025359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
1026359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1027359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1028359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
10298bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    /**
10308bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * Indicates whether current phone connection is emergency or not
10318bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * @return boolean: true if emergency, false otherwise
10328bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     */
10338bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    protected boolean isEmergency() {
10348bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        return mIsEmergency;
10358bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
1036db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1037db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    /**
1038db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
1039db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * responses received.
1040db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     *
1041db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param status The status of the original request.
1042db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param requestProfile The requested video profile.
1043db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param responseProfile The response upon video profile.
1044db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
1045db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    @Override
1046db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
1047db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            VideoProfile responseProfile) {
1048db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
1049db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                mShouldIgnoreVideoStateChanges) {
1050db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int currentVideoState = getVideoState();
1051db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int newVideoState = responseProfile.getVideoState();
1052db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1053db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // If the current video state is paused, the modem will not send us any changes to
1054db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // the TX and RX bits of the video state.  Until the video is un-paused we will
1055db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // "fake out" the video state by applying the changes that the modem reports via a
1056db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // response.
1057db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1058db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // First, find out whether there was a change to the TX or RX bits:
1059db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int changedBits = currentVideoState ^ newVideoState;
1060db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
1061db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (changedBits == 0) {
1062db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                // No applicable change, bail out.
1063db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                return;
1064db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1065db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1066db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn off any existing bits that changed.
1067db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState &= ~(changedBits & currentVideoState);
1068db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn on any new bits that turned on.
1069db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState |= changedBits & newVideoState;
1070db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1071db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
1072db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
1073db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " / " +
1074db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
1075db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " while paused ; sending new videoState = " +
1076db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(currentVideoState));
1077db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            setVideoState(currentVideoState);
1078db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        }
1079db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1080359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1081359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1082359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
1083359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1084359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1085359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the pause request.
1086359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1087359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void pauseVideo(int source) {
1088359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1089359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1090359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1091359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1092359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
1093359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1094359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1095359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1096359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
1097359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1098359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1099359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the resume request.
1100359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1101359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void resumeVideo(int source) {
1102359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1103359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1104359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1105359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1106359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
1107359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1108359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1109359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1110359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Determines if a specified source has issued a pause request.
1111359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1112359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source.
1113359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @return {@code true} if the source issued a pause request, {@code false} otherwise.
1114359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1115359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public boolean wasVideoPausedFromSource(int source) {
1116359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1117359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return false;
1118359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1119359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1120359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
1121359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1123