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;
268a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebingerimport android.os.Messenger;
276bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusimport android.os.PersistableBundle;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.PowerManager;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemClock;
31db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnimport android.telecom.VideoProfile;
326bb557b243f3fc9984b82319026519608ada2c9cRoshan Piusimport android.telephony.CarrierConfigManager;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
362e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunnimport android.telephony.ServiceState;
37baece8c63121b5e3660ecc716bcff87f73f791ffHall Liuimport android.telephony.ims.ImsCallProfile;
38baece8c63121b5e3660ecc716bcff87f73f791ffHall Liuimport android.telephony.ims.ImsStreamMediaProfile;
39eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganeshimport android.text.TextUtils;
40a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
41286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunnimport com.android.ims.ImsCall;
422999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunnimport com.android.ims.ImsException;
43db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunnimport com.android.ims.internal.ImsVideoCallProviderWrapper;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
46a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.UUSInfo;
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;
838a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebinger    private Messenger mHandlerMessenger;
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
85a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PowerManager.WakeLock mPartialWakeLock;
86a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
87fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    // The cached connect time of the connection when it turns into a conference.
88fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    private long mConferenceConnectTime = 0;
89fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
906bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    // The cached delay to be used between DTMF tones fetched from carrier config.
916bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private int mDtmfToneDelay = 0;
926bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
938bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    private boolean mIsEmergency = false;
948bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
952e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
96db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Used to indicate that video state changes detected by
97db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * {@link #updateMediaCapabilities(ImsCall)} should be ignored.  When a video state change from
98db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * unpaused to paused occurs, we set this flag and then update the existing video state when
99db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * new {@link #onReceiveSessionModifyResponse(int, VideoProfile, VideoProfile)} callbacks come
100db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * in.  When the video un-pauses we continue receiving the video state updates.
101db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
102db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    private boolean mShouldIgnoreVideoStateChanges = false;
103db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
104359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    private ImsVideoCallProviderWrapper mImsVideoCallProviderWrapper;
105359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
106222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    private int mPreciseDisconnectCause = 0;
107222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
108fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private ImsRttTextHandler mRttTextHandler;
109fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    private android.telecom.Connection.RttTextStream mRttTextStream;
1103d28f89927137ce03128a0244a698ca5162e8165Hall Liu    // This reflects the RTT status as reported to us by the IMS stack via the media profile.
1113d28f89927137ce03128a0244a698ca5162e8165Hall Liu    private boolean mIsRttEnabledForCall = false;
112fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
113286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
114286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Used to indicate that this call is in the midst of being merged into a conference.
115286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
116286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    private boolean mIsMergeInProcess = false;
117286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
11863fa599fef0383b41f85e1fc3a38d33c4434e24aTyler Gunn    /**
1197a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * Used as an override to determine whether video is locally available for this call.
1207a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * This allows video availability to be overridden in the case that the modem says video is
1217a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * currently available, but mobile data is off and the carrier is metering data for video
1227a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     * calls.
1237a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn     */
1247a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    private boolean mIsVideoEnabled = true;
1257a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Event Constants
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DTMF_DONE = 1;
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_PAUSE_DONE = 2;
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_NEXT_POST_DIAL = 3;
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
1316bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    private static final int EVENT_DTMF_DELAY_DONE = 5;
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;
136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Inner Classes
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    class MyHandler extends Handler {
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        MyHandler(Looper l) {super(l);}
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        handleMessage(Message msg) {
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (msg.what) {
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_NEXT_POST_DIAL:
1486bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DELAY_DONE:
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_PAUSE_DONE:
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    processNextPostDialChar();
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case EVENT_WAKE_LOCK_TIMEOUT:
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    releaseWakeLock();
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1556bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                case EVENT_DTMF_DONE:
1566bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // We may need to add a delay specified by carrier between DTMF tones that are
1576bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    // sent out.
1586bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
1596bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                            mDtmfToneDelay);
1606bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    break;
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is probably an MT call */
168f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
16908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh           ImsPhoneCall parent, boolean isUnknown) {
170c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
1716bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
1768a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebinger        mHandlerMessenger = new Messenger(mHandler);
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
182d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mNumberPresentation = ImsCallProfile.OIRToPresentation(
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
184d325833e9248c05305b1edabb1d8efc827803f75Jing Zhao            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
1866a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            updateMediaCapabilities(imsCall);
187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mIsIncoming = !isUnknown;
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mUusInfo = null;
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
196553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
197553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
198553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        // connection is not likely to be associated with a TelephonyConnection yet).
199553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn        updateExtras(imsCall);
200553db651cd5a51eedde0259d5a25e91700ef96c5Tyler Gunn
201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
20208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        mParent.attach(this,
20308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));
2046bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2056bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
206c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
207c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
208c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
209c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
210c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** This is an MO call, created when dialing */
214f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
2158bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            ImsPhoneCall parent, boolean isEmergency) {
216c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        super(PhoneConstants.PHONE_TYPE_IMS);
2176bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        createWakeLock(phone.getContext());
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        acquireWakeLock();
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mOwner = ct;
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandler = new MyHandler(mOwner.getLooper());
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDialString = dialString;
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //mIndex = -1;
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mIsIncoming = false;
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapName = null;
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCreateTime = System.currentTimeMillis();
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        parent.attachFake(this, ImsPhoneCall.State.DIALING);
2386bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
2398bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        mIsEmergency = isEmergency;
2408bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
2416bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        fetchDtmfToneDelay(phone);
242c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu
243c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        if (phone.getContext().getResources().getBoolean(
244c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
245c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu            setAudioModeIsVoip(true);
246c6e763fa8aa1121f9c5aef16368115b06e31c6a2Jimmy Wu        }
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static boolean
253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    equalsHandlesNulls (Object a, Object b) {
254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return (a == null) ? (b == null) : a.equals (b);
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
25774c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    static boolean
25874c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    equalsBaseDialString (String a, String b) {
25974c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi        return (a == null) ? (b == null) : (b != null && a.startsWith (b));
26074c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi    }
26174c8509aede6fe748904e75c156049b4f1ba5e28Hanada Masafumi
2627a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    private int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
2637a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        Rlog.i(LOG_TAG, "applyLocalCallCapabilities - localProfile = " + localProfile);
264f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2652e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
266f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
2677a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        if (!mIsVideoEnabled) {
2687a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            Rlog.i(LOG_TAG, "applyLocalCallCapabilities - disabling video (overidden)");
2697a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            return capabilities;
2707a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        }
271f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (localProfile.mCallType) {
272f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2732e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // Fall-through
274f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
275f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2762e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
277f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
278f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
279f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
280f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
281f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
282f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
2832e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
284f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        capabilities = removeCapability(capabilities,
2852e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
286f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
287f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        switch (remoteProfile.mCallType) {
288f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VT:
2892e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                // fall-through
290f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
291f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = addCapability(capabilities,
2922e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
293f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                break;
294f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        }
295f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn        return capabilities;
296f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn    }
297f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public String getOrigDialString(){
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDialString;
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall getCall() {
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mParent;
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getDisconnectTime() {
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDisconnectTime;
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldingStartTime() {
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mHoldingStartTime;
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public long getHoldDurationMillis() {
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (getState() != ImsPhoneCall.State.HOLDING) {
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // If not holding, return 0
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return 0;
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return SystemClock.elapsedRealtime() - mHoldingStartTime;
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void setDisconnectCause(int cause) {
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = cause;
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
33233cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    @Override
33333cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    public String getVendorDisconnectCause() {
33433cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu      return null;
33533cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu    }
33633cfb500a7cf192adfc5ca06792fe3847073b6c1Chao Liu
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCallTracker getOwner () {
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mOwner;
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public ImsPhoneCall.State getState() {
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mDisconnected) {
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return ImsPhoneCall.State.DISCONNECTED;
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return super.getState();
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
3514611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain    public void deflect(String number) throws CallStateException {
3524611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain        if (mParent.getState().isRinging()) {
3534611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain            try {
3544611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                if (mImsCall != null) {
3554611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                    mImsCall.deflect(number);
3564611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                } else {
3574611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                    throw new CallStateException("no valid ims call to deflect");
3584611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                }
3594611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain            } catch (ImsException e) {
3604611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain                throw new CallStateException("cannot deflect call");
3614611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain            }
3624611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain        } else {
3634611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain            throw new CallStateException("phone not ringing");
3644611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain        }
3654611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain    }
3664611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain
3674611e65ec532915b3a6968459d68e5a2dc3a08c8Pooja Jain    @Override
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void hangup() throws CallStateException {
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.hangup(this);
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("disconnected");
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void separate() throws CallStateException {
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        throw new CallStateException ("not supported");
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWaitChar() {
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WAIT) {
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WAIT but was " + mPostDialState);
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void proceedAfterWildChar(String str) {
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.WILD) {
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "getPostDialState() to be WILD but was " + mPostDialState);
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.STARTED);
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // make a new postDialString, with the wild char replacement string
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // at the beginning, followed by the remaining postDialString.
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        StringBuilder buf = new StringBuilder(str);
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        buf.append(mPostDialString.substring(mNextPostDialChar));
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialString = buf.toString();
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mNextPostDialChar = 0;
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPostDialString);
414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        processNextPostDialChar();
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void cancelPostDial() {
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setPostDialState(PostDialState.CANCELLED);
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Called when this Connection is being hung up locally (eg, user pressed "end")
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onHangupLocal() {
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mCause = DisconnectCause.LOCAL;
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /** Called when the connection has been disconnected */
433c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
434c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean onDisconnect(int cause) {
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
4361999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
4371999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn            mCause = cause;
4381999b9772eb9b3a230bd2520ffebb152544eaba9Tyler Gunn        }
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return onDisconnect();
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
442f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean onDisconnect() {
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mDisconnected) {
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //mIndex = -1;
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnectTime = System.currentTimeMillis();
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mDisconnected = true;
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mOwner.mPhone.notifyDisconnect(this);
45347b078c27bfb57477a4ff1ce12abc4e9632c1dd5Tyler Gunn            notifyDisconnect(mCause);
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mParent != null) {
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                changed = mParent.connectionDisconnected(this);
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.d(LOG_TAG, "onDisconnect: no parent");
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
46034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            synchronized (this) {
46134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                if (mImsCall != null) mImsCall.close();
46234310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                mImsCall = null;
46334310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return changed;
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * An incoming or outgoing call has connected
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onConnectedInOrOut() {
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTime = System.currentTimeMillis();
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnectTimeReal = SystemClock.elapsedRealtime();
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDuration = 0;
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (Phone.DEBUG_PHONE) {
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!mIsIncoming) {
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // outgoing calls only
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processNextPostDialChar();
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    onStartedHolding() {
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHoldingStartTime = SystemClock.elapsedRealtime();
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Performs the appropriate action for a post-dial char, but does not
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * notify application. returns false if the character is invalid and
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * should be ignored
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processPostDialChar(char c) {
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (PhoneNumberUtils.is12Key(c)) {
5018a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebinger            Message dtmfComplete = mHandler.obtainMessage(EVENT_DTMF_DONE);
5028a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebinger            dtmfComplete.replyTo = mHandlerMessenger;
5038a5c54f8ba1793a89bb8e18e819d1fc5b85bc1bfBrad Ebinger            mOwner.sendDtmf(c, dtmfComplete);
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.PAUSE) {
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // From TS 22.101:
506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // It continues...
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Upon the called party answering the UE shall send the DTMF digits
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // automatically to the network after a delay of 3 seconds( 20 ).
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The digits shall be sent according to the procedures and timing
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // "DTMF Control Digits Separator" shall be used by the ME to
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // distinguish between the addressing digits (i.e. the phone number)
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // and the DTMF digits. Upon subsequent occurrences of the
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // separator,
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // the UE shall pause again for 3 seconds ( 20 ) before sending
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // any further DTMF digits.
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    PAUSE_DELAY_MILLIS);
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WAIT) {
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WAIT);
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (c == PhoneNumberUtils.WILD) {
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.WILD);
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return false;
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return true;
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
531032d73c15281387a97cdb91c6f0c7c3a1b1b230eAmit Mahajan    protected void finalize() {
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        releaseWakeLock();
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    processNextPostDialChar() {
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        char c = 0;
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant postDialHandler;
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState == PostDialState.CANCELLED) {
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
545d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.COMPLETE);
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // notifyMessage.arg1 is 0 on complete
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = 0;
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            boolean isValid;
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setPostDialState(PostDialState.STARTED);
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            c = mPostDialString.charAt(mNextPostDialChar++);
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            isValid = processPostDialChar(c);
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (!isValid) {
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Will call processNextPostDialChar
561a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // Don't notify application
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5684567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        notifyPostDialListenersNextChar(c);
5694567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen
5704567a0789e9966929c71af9a2c3866582c85c9e0Nancy Chen        // TODO: remove the following code since the handler no longer executes anything.
57193c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan        postDialHandler = mOwner.mPhone.getPostDialHandler();
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Message notifyMessage;
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (postDialHandler != null
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // The AsyncResult.result is the Connection object
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            PostDialState state = mPostDialState;
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.result = this;
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ar.userObj = state;
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // arg1 is the character that was/is being processed
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.arg1 = c;
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
586d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //Rlog.v(LOG_TAG,
587d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            notifyMessage.sendToTarget();
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Set post dial state and acquire wake lock while switching to "started"
594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state, the wake lock will be released if state switches out of "started"
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * @param s new PostDialState
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void setPostDialState(PostDialState s) {
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mPostDialState != PostDialState.STARTED
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s == PostDialState.STARTED) {
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            acquireWakeLock();
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPostDialState == PostDialState.STARTED
605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && s != PostDialState.STARTED) {
606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            releaseWakeLock();
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPostDialState = s;
610d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee        notifyPostDialListeners();
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    createWakeLock(Context context) {
615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
620a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    acquireWakeLock() {
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "acquireWakeLock");
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPartialWakeLock.acquire();
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
62597fba207643a87dd718395010a98ded3e809a3d7Libin.Tang@motorola.com    void
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    releaseWakeLock() {
62737800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan        if (mPartialWakeLock != null) {
62837800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan            synchronized (mPartialWakeLock) {
62937800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                if (mPartialWakeLock.isHeld()) {
63037800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    Rlog.d(LOG_TAG, "releaseWakeLock");
63137800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                    mPartialWakeLock.release();
63237800d3cdb300fca83462d95221a05bbef21a951Amit Mahajan                }
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
637c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    private void fetchDtmfToneDelay(Phone phone) {
6386bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        CarrierConfigManager configMgr = (CarrierConfigManager)
6396bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
6406bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
6416bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        if (b != null) {
6426bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
6436bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius        }
6446bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius    }
6456bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getNumberPresentation() {
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mNumberPresentation;
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public UUSInfo getUUSInfo() {
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mUusInfo;
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public Connection getOrigConnection() {
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
66234310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isMultiparty() {
663541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return mImsCall != null && mImsCall.isMultiparty();
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
666ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    /**
667ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
668ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
669ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * {@link ImsCall} is a member of a conference hosted on another device.
670ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *
671ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     * @return {@code true} if this call is the origin of the conference call it is a member of,
672ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     *      {@code false} otherwise.
673ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn     */
674c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
67534310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized boolean isConferenceHost() {
67634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        return mImsCall != null && mImsCall.isConferenceHost();
677ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn    }
678ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
679c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    @Override
680c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    public boolean isMemberOfPeerConference() {
681c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan        return !isConferenceHost();
682c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan    }
683c2b66d57e16623dffc2fe6d02ded4f24c014b6c8Amit Mahajan
68434310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized ImsCall getImsCall() {
685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mImsCall;
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
68834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu    public synchronized void setImsCall(ImsCall imsCall) {
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mImsCall = imsCall;
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
692f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void changeParent(ImsPhoneCall parent) {
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mParent = parent;
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6966a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
6976a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
6986a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *     changed, and {@code false} otherwise.
6996a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
700f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.ACTIVE) {
702707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // If the state of the call is active, but there is a pending request to the RIL to hold
703707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // the call, we will skip this update.  This is really a signalling delay or failure
704707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // from the RIL, but we will prevent it from going through as we will end up erroneously
705707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            // making this call active when really it should be on hold.
706707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (imsCall.isPendingHold()) {
707707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
708707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                return false;
709707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
710707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
7116a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                onConnectedInOrOut();
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7156a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
716a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //mForegroundCall should be IDLE
717a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //when accepting WAITING call
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //before accept WAITING call,
719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //the ACTIVE call should be held ahead
720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.detach(this);
721a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent = mOwner.mForegroundCall;
722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mParent.attach(this);
723a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (state == ImsPhoneCall.State.HOLDING) {
725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onStartedHolding();
726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
728549148fb25d8b38c2bd1207c1a21027c6621932bEtan Cohen        boolean updateParent = mParent.update(this, imsCall, state);
729eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
73021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
73121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        boolean updateExtras = updateExtras(imsCall);
732ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
73375f96a40e73bbf262287b64f7ba79f058adac472Brad Ebinger        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public int getPreciseDisconnectCause() {
738222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        return mPreciseDisconnectCause;
739222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
740222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
741222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    public void setPreciseDisconnectCause(int cause) {
742222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        mPreciseDisconnectCause = cause;
743a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
744d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn
745d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    /**
746d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * Notifies this Connection of a request to disconnect a participant of the conference managed
747d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * by the connection.
748d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     *
749d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
750d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn     */
751d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    @Override
752d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    public void onDisconnectConferenceParticipant(Uri endpoint) {
753d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        ImsCall imsCall = getImsCall();
754d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        if (imsCall == null) {
755d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            return;
756d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
757d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        try {
758d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            imsCall.removeParticipants(new String[]{endpoint.toString()});
759d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        } catch (ImsException e) {
760d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            // No session in place -- no change
761d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
762d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn                    "Failed to disconnect endpoint = " + endpoint);
763d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn        }
764d7f4ed8ac190763dce7e57b737caa44654b4592aTyler Gunn    }
765541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn
766541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    /**
767fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
768fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * this phone connection.
769fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     *
770fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @param conferenceConnectTime The conference connect time.
771fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
772fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public void setConferenceConnectTime(long conferenceConnectTime) {
773fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        mConferenceConnectTime = conferenceConnectTime;
774fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
775fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
776fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
777fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     * @return The conference connect time.
778fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn     */
779fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    public long getConferenceConnectTime() {
780fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        return mConferenceConnectTime;
781fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    }
782fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
783fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn    /**
784eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * Check for a change in the address display related fields for the {@link ImsCall}, and
785eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * update the {@link ImsPhoneConnection} with this information.
786eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     *
787eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @param imsCall The call to check for changes in address display fields.
788eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     * @return Whether the address display fields have been changed.
789eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh     */
79027e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati    public boolean updateAddressDisplay(ImsCall imsCall) {
791eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        if (imsCall == null) {
792eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            return false;
793eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
794eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
795eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        boolean changed = false;
796eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        ImsCallProfile callProfile = imsCall.getCallProfile();
797eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn        if (callProfile != null && isIncoming()) {
798eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // Only look for changes to the address for incoming calls.  The originating identity
799eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // can change for outgoing calls due to, for example, a call being forwarded to
800eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn            // voicemail.  This address change does not need to be presented to the user.
801eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
802eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
803eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int nump = ImsCallProfile.OIRToPresentation(
804eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
805eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            int namep = ImsCallProfile.OIRToPresentation(
806eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
807eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            if (Phone.DEBUG_PHONE) {
808eb7465409290618ca5d7b5f8ba2ffabba2d936d9Tyler Gunn                Rlog.d(LOG_TAG, "updateAddressDisplay: callId = " + getTelecomCallId()
809c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng                        + " address = " + Rlog.pii(LOG_TAG, address) + " name = "
810c58281f18e760c39c2fedba61453eae7bfdda349Xinying.Deng                        + Rlog.pii(LOG_TAG, name) + " nump = " + nump + " namep = " + namep);
811eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
812286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn            if (!mIsMergeInProcess) {
813286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // Only process changes to the name and address when a merge is not in process.
814286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // When call A initiated a merge with call B to form a conference C, there is a
815286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // point in time when the ImsCall transfers the conference call session into A,
816286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // at which point the ImsConferenceController creates the conference in Telecom.
817286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // For some carriers C will have a unique conference URI address.  Swapping the
818286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // conference session into A, which is about to be disconnected, to be logged to
819286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // the call log using the conference address.  To prevent this we suppress updates
820286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                // to the call address while a merge is in process.
821286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (!equalsBaseDialString(mAddress, address)) {
822286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mAddress = address;
823286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
824286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
825286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (TextUtils.isEmpty(name)) {
826286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    if (!TextUtils.isEmpty(mCnapName)) {
827286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        mCnapName = "";
828286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                        changed = true;
829286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    }
830286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                } else if (!name.equals(mCnapName)) {
831286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapName = name;
832286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
833286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
834286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mNumberPresentation != nump) {
835286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mNumberPresentation = nump;
836286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    changed = true;
837286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                }
838286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                if (mCnapNamePresentation != namep) {
839286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn                    mCnapNamePresentation = namep;
840eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                    changed = true;
841eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh                }
842eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh            }
843eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        }
844eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh        return changed;
845eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    }
846eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh
847eeeb1cb65e41778fa78abcaba93a9e4ebe351ec6Shriram Ganesh    /**
8486a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
8496a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * update the {@link ImsPhoneConnection} with this information.
8506a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
8516a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param imsCall The call to check for changes in media capabilities.
8526a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return Whether the media capabilities have been changed.
8536a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
854d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    public boolean updateMediaCapabilities(ImsCall imsCall) {
8556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (imsCall == null) {
8566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return false;
8576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
8586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        boolean changed = false;
8606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
8616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        try {
862e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            // The actual call profile (negotiated between local and peer).
863e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();
8646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
865e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            if (negotiatedCallProfile != null) {
866288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int oldVideoState = getVideoState();
867288268d5528e0df03f348e303954813cb188c55bRekha Kumar                int newVideoState = ImsCallProfile
868288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);
869e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
870288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (oldVideoState != newVideoState) {
871db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
872db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // below.  When the video enters a paused state, subsequent changes to the video
873db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
874db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // we will be updating the current video state while paused to include any
875db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // changes the modem reports via the video provider.  When the video enters an
876db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    // unpaused state, we will resume passing the video states from the modem as is.
877db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (VideoProfile.isPaused(oldVideoState) &&
878db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            !VideoProfile.isPaused(newVideoState)) {
879db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered un-paused state; recognize updates from now on; we want to
880db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // ensure that the new un-paused state is propagated to Telecom, so change
881db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // this now.
882db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = false;
883db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
884db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
885db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!mShouldIgnoreVideoStateChanges) {
88644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                        updateVideoState(newVideoState);
887db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        changed = true;
888db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    } else {
889db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
890db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                                "due to paused state.");
891db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
892db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
893db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    if (!VideoProfile.isPaused(oldVideoState) &&
894db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            VideoProfile.isPaused(newVideoState)) {
895db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // Video entered pause state; ignore updates until un-paused.  We do this
896db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // after setVideoState is called above to ensure Telecom is notified that
897db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        // the device has entered paused state.
898db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                        mShouldIgnoreVideoStateChanges = true;
899db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    }
900e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn                }
90173225469bc0503fe961b2791fa37c855c8243217Hall Liu
90273225469bc0503fe961b2791fa37c855c8243217Hall Liu                if (negotiatedCallProfile.mMediaProfile != null) {
9033d28f89927137ce03128a0244a698ca5162e8165Hall Liu                    mIsRttEnabledForCall = negotiatedCallProfile.mMediaProfile.isRttCall();
90473225469bc0503fe961b2791fa37c855c8243217Hall Liu
9053d28f89927137ce03128a0244a698ca5162e8165Hall Liu                    if (mIsRttEnabledForCall && mRttTextHandler == null) {
90673225469bc0503fe961b2791fa37c855c8243217Hall Liu                        Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT on, profile="
90773225469bc0503fe961b2791fa37c855c8243217Hall Liu                                + negotiatedCallProfile);
90873225469bc0503fe961b2791fa37c855c8243217Hall Liu                        startRttTextProcessing();
90973225469bc0503fe961b2791fa37c855c8243217Hall Liu                        onRttInitiated();
91073225469bc0503fe961b2791fa37c855c8243217Hall Liu                        changed = true;
9113d28f89927137ce03128a0244a698ca5162e8165Hall Liu                    } else if (!mIsRttEnabledForCall && mRttTextHandler != null) {
91273225469bc0503fe961b2791fa37c855c8243217Hall Liu                        Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT off, profile="
91373225469bc0503fe961b2791fa37c855c8243217Hall Liu                                + negotiatedCallProfile);
91473225469bc0503fe961b2791fa37c855c8243217Hall Liu                        mRttTextHandler.tearDown();
91573225469bc0503fe961b2791fa37c855c8243217Hall Liu                        mRttTextHandler = null;
91673225469bc0503fe961b2791fa37c855c8243217Hall Liu                        onRttTerminated();
91773225469bc0503fe961b2791fa37c855c8243217Hall Liu                        changed = true;
91873225469bc0503fe961b2791fa37c855c8243217Hall Liu                    }
91973225469bc0503fe961b2791fa37c855c8243217Hall Liu                }
920e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn            }
921e70972cf6a3b48df1f7d036877eb28529e606ca9Tyler Gunn
922f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Check for a change in the capabilities for the call and update
923f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // {@link ImsPhoneConnection} with this information.
924f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            int capabilities = getConnectionCapabilities();
9252e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
9262e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            // Use carrier config to determine if downgrading directly to audio-only is supported.
9272e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
9282e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = addCapability(capabilities,
9292e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
9302e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
9312e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            } else {
9322e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                capabilities = removeCapability(capabilities,
9332e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
9342e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
9352e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn            }
9362e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
937f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current local call capabilities which might be voice or video or both.
938f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
939f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
9406a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (localCallProfile != null) {
941f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
9426a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
9436a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
944f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            // Get the current remote call capabilities which might be voice or video or both.
945f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
946f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
947288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (remoteCallProfile != null) {
948f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
949f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            }
950f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn            if (getConnectionCapabilities() != capabilities) {
951f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                setConnectionCapabilities(capabilities);
952f83df11772fcf7f2aae0d9179b4d36eba92ad74eTyler Gunn                changed = true;
953288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
954288268d5528e0df03f348e303954813cb188c55bRekha Kumar
9556a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            int newAudioQuality =
9566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
9576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            if (getAudioQuality() != newAudioQuality) {
9586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                setAudioQuality(newAudioQuality);
9596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                changed = true;
9606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            }
9616a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        } catch (ImsException e) {
9626a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            // No session in place -- no change
9636a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
9646a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
9656a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return changed;
9666a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
9676a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
96844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    private void updateVideoState(int newVideoState) {
96944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        if (mImsVideoCallProviderWrapper != null) {
97044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn            mImsVideoCallProviderWrapper.onVideoStateChanged(newVideoState);
97144b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        }
97244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        setVideoState(newVideoState);
97344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
97444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
975fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyRequest(android.telecom.Connection.RttTextStream textStream) {
976fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        getImsCall().sendRttModifyRequest();
977fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        setCurrentRttTextStream(textStream);
978fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
979fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
980fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    /**
981fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * Sends the user's response to a remotely-issued RTT upgrade request
982fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *
983fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     * @param textStream A valid {@link android.telecom.Connection.RttTextStream} if the user
984fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     *                   accepts, {@code null} if not.
985fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu     */
986fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void sendRttModifyResponse(android.telecom.Connection.RttTextStream textStream) {
987fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        boolean accept = textStream != null;
988fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        ImsCall imsCall = getImsCall();
989fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
990fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        imsCall.sendRttModifyResponse(accept);
991fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        if (accept) {
992fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            setCurrentRttTextStream(textStream);
993fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        } else {
994fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu            Rlog.e(LOG_TAG, "sendRttModifyResponse: foreground call has no connections");
995fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        }
996fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
997fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
998fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void onRttMessageReceived(String message) {
999670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        synchronized (this) {
1000670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            if (mRttTextHandler == null) {
1001670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                Rlog.w(LOG_TAG, "onRttMessageReceived: RTT text handler not available."
1002670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                        + " Attempting to create one.");
1003670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                if (mRttTextStream == null) {
1004670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                    Rlog.e(LOG_TAG, "onRttMessageReceived:"
1005670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                            + " Unable to process incoming message. No textstream available");
1006670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                    return;
1007670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                }
1008670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                createRttTextHandler();
1009670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            }
1010670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        }
1011670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        mRttTextHandler.sendToInCall(message);
1012fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
1013fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
1014fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void setCurrentRttTextStream(android.telecom.Connection.RttTextStream rttTextStream) {
1015670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        synchronized (this) {
1016670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            mRttTextStream = rttTextStream;
1017670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            if (mRttTextHandler == null && mIsRttEnabledForCall) {
1018670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                Rlog.i(LOG_TAG, "setCurrentRttTextStream: Creating a text handler");
1019670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                createRttTextHandler();
1020670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            }
1021670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        }
1022fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
1023fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
102473225469bc0503fe961b2791fa37c855c8243217Hall Liu    public boolean hasRttTextStream() {
102573225469bc0503fe961b2791fa37c855c8243217Hall Liu        return mRttTextStream != null;
102673225469bc0503fe961b2791fa37c855c8243217Hall Liu    }
102773225469bc0503fe961b2791fa37c855c8243217Hall Liu
10283d28f89927137ce03128a0244a698ca5162e8165Hall Liu    public boolean isRttEnabledForCall() {
10293d28f89927137ce03128a0244a698ca5162e8165Hall Liu        return mIsRttEnabledForCall;
10303d28f89927137ce03128a0244a698ca5162e8165Hall Liu    }
10313d28f89927137ce03128a0244a698ca5162e8165Hall Liu
1032fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    public void startRttTextProcessing() {
1033670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        synchronized (this) {
1034670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            if (mRttTextStream == null) {
1035670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                Rlog.w(LOG_TAG, "startRttTextProcessing: no RTT text stream. Ignoring.");
1036670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                return;
1037670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            }
1038670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            if (mRttTextHandler != null) {
1039670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                Rlog.w(LOG_TAG, "startRttTextProcessing: RTT text handler already exists");
1040670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu                return;
1041670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            }
1042670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu            createRttTextHandler();
104373225469bc0503fe961b2791fa37c855c8243217Hall Liu        }
1044fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
1045fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
1046670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu    // Make sure to synchronize on ImsPhoneConnection.this before calling.
1047670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu    private void createRttTextHandler() {
1048fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu        mRttTextHandler = new ImsRttTextHandler(Looper.getMainLooper(),
1049fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu                (message) -> getImsCall().sendRttMessage(message));
1050670f3a47cde0e3410f756927f00d03ee2ef881dcHall Liu        mRttTextHandler.initialize(mRttTextStream);
1051fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu    }
1052fa88fc1de20ddb819975d78c98e4c0d6b27e225aHall Liu
10536a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
10542e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
10552e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * The call is considered to be a WIFI call if the extra value is
10562e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
10572e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     *
10582e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     * @param extras The ImsCallProfile extras.
10592e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn     */
10602e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    private void updateWifiStateFromExtras(Bundle extras) {
1061d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
1062d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {
10632e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
1064d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            ImsCall call = getImsCall();
1065d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            boolean isWifi = false;
1066d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            if (call != null) {
1067d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger                isWifi = call.isWifiCall();
1068d0a85e9d7e52ecd5de9f7063361d9b01d2493627Brad Ebinger            }
10692e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
10702e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            // Report any changes
10712e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            if (isWifi() != isWifi) {
10722e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn                setWifi(isWifi);
10732e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            }
10742e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn        }
10752e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    }
10762e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
10772e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn    /**
107821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * Check for a change in call extras of {@link ImsCall}, and
107921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * update the {@link ImsPhoneConnection} accordingly.
108021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     *
108121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @param imsCall The call to check for changes in extras.
108221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     * @return Whether the extras fields have been changed.
108321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     */
108421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar     boolean updateExtras(ImsCall imsCall) {
108521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (imsCall == null) {
108621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
108721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
108821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
108921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final ImsCallProfile callProfile = imsCall.getCallProfile();
109021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
109121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null && DBG) {
109221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            Rlog.d(LOG_TAG, "Call profile extras are null.");
109321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
109421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
109521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        final boolean changed = !areBundlesEqual(extras, mExtras);
109621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (changed) {
10972e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn            updateWifiStateFromExtras(extras);
10982e66c6325d321e41b8851da9a4596f7a745c7b1eTyler Gunn
109921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.clear();
110021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            mExtras.putAll(extras);
110121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            setConnectionExtras(mExtras);
110221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
110321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return changed;
110421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
110521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
110621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
110721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras == null || newExtras == null) {
110821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return extras == newExtras;
110921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
111021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
111121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        if (extras.size() != newExtras.size()) {
111221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            return false;
111321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
111421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
111521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        for(String key : extras.keySet()) {
111621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            if (key != null) {
111721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object value = extras.get(key);
111821048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                final Object newValue = newExtras.get(key);
111921048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                if (!Objects.equals(value, newValue)) {
112021048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                    return false;
112121048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar                }
112221048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            }
112321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        }
112421048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar        return true;
112521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    }
112621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar
112721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar    /**
11286a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
1129363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
1130363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
1131363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty     * there is no remote restrict cause.
11326a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     *
11336a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param localCallProfile The local call profile.
11346a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @param remoteCallProfile The remote call profile.
11356a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     * @return The audio quality.
11366a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee     */
11376a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    private int getAudioQualityFromCallProfile(
11386a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
11396a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        if (localCallProfile == null || remoteCallProfile == null
11406a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile == null) {
11416a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee            return AUDIO_QUALITY_STANDARD;
11426a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        }
11436a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
1144363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
1145363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
1146363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1147363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
1148363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || localCallProfile.mMediaProfile.mAudioQuality
1149363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);
1150363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty
1151363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
11526a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
11536a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                || localCallProfile.mMediaProfile.mAudioQuality
1154363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
1155363911ade99b8c798fd1c6ef545d253b8c35a001Dheeraj Shetty                || isEvsCodecHighDef)
11566a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
11576a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
11586a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    }
11596a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee
11606a0fa4105fa8104a09b33a3403df5ae2711e0083Andrew Lee    /**
1161541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
1162541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * use in log statements.
1163541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     *
1164541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     * @return String representation of call.
1165541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn     */
1166541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    @Override
1167541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    public String toString() {
1168541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        StringBuilder sb = new StringBuilder();
1169541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("[ImsPhoneConnection objId: ");
1170541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append(System.identityHashCode(this));
11711a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" telecomCallID: ");
11721a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(getTelecomCallId());
11731a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" address: ");
117477a1f167b962ceaf7972d246f4c23e17772d1c69fionaxu        sb.append(Rlog.pii(LOG_TAG, getAddress()));
11751a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        sb.append(" ImsCall: ");
117634310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu        synchronized (this) {
117734310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            if (mImsCall == null) {
117834310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append("null");
117934310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            } else {
118034310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu                sb.append(mImsCall);
118134310e958f52099ce3a2e74a8e3c4f631a241529Hall Liu            }
1182541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        }
1183541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        sb.append("]");
1184541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn        return sb.toString();
1185541accbd8e08fac77faa1c60d14533b1a5a36347Tyler Gunn    }
11868bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1187359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    @Override
1188359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
1189359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        super.setVideoProvider(videoProvider);
1190359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1191359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1192359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
1193359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1194359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1195359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
11968bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    /**
11978bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * Indicates whether current phone connection is emergency or not
11988bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     * @return boolean: true if emergency, false otherwise
11998bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan     */
12008bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    protected boolean isEmergency() {
12018bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        return mIsEmergency;
12028bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan    }
1203db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1204db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    /**
1205db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
1206db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * responses received.
1207db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     *
1208db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param status The status of the original request.
1209db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param requestProfile The requested video profile.
1210db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     * @param responseProfile The response upon video profile.
1211db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn     */
1212db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    @Override
1213db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
1214db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            VideoProfile responseProfile) {
1215db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
1216db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                mShouldIgnoreVideoStateChanges) {
1217db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int currentVideoState = getVideoState();
1218db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int newVideoState = responseProfile.getVideoState();
1219db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1220db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // If the current video state is paused, the modem will not send us any changes to
1221db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // the TX and RX bits of the video state.  Until the video is un-paused we will
1222db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // "fake out" the video state by applying the changes that the modem reports via a
1223db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // response.
1224db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1225db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // First, find out whether there was a change to the TX or RX bits:
1226db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            int changedBits = currentVideoState ^ newVideoState;
1227db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
1228db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (changedBits == 0) {
1229db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                // No applicable change, bail out.
1230db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                return;
1231db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1232db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1233db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn off any existing bits that changed.
1234db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState &= ~(changedBits & currentVideoState);
1235db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            // Turn on any new bits that turned on.
1236db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            currentVideoState |= changedBits & newVideoState;
1237db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1238db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
1239db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
1240db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " / " +
1241db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
1242db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    " while paused ; sending new videoState = " +
1243db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    VideoProfile.videoStateToString(currentVideoState));
1244db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            setVideoState(currentVideoState);
1245db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn        }
1246db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn    }
1247359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1248359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1249359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
1250359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1251359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1252359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the pause request.
1253359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1254359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void pauseVideo(int source) {
1255359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1256359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1257359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1258359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1259359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
1260359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1261359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1262359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1263359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
1264359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * other than the InCall UI.
1265359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1266359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source of the resume request.
1267359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1268359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public void resumeVideo(int source) {
1269359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1270359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return;
1271359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1272359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1273359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
1274359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1275359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1276359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    /**
1277359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * Determines if a specified source has issued a pause request.
1278359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     *
1279359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @param source The source.
1280359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     * @return {@code true} if the source issued a pause request, {@code false} otherwise.
1281359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn     */
1282359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    public boolean wasVideoPausedFromSource(int source) {
1283359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        if (mImsVideoCallProviderWrapper == null) {
1284359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn            return false;
1285359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        }
1286359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn
1287359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn        return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
1288359c182111879b821c0b7eba6d5fa52194293212Tyler Gunn    }
1289286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1290286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1291286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as in the process of being merged and inform the UI of the merge start.
1292286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1293286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeStart() {
1294286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = true;
1295286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_START, null);
1296286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
1297286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn
1298286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    /**
1299286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     * Mark the call as done merging and inform the UI of the merge start.
1300286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn     */
1301286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    public void handleMergeComplete() {
1302286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        mIsMergeInProcess = false;
1303286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_COMPLETE, null);
1304286e95aa9cd740c6d8e9fd32aeefeceaf0c81695Tyler Gunn    }
130544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
130644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToPausedState() {
130744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() | VideoProfile.STATE_PAUSED;
130844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToPausedState - setting paused bit; "
130944b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
131044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
13116dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn        mShouldIgnoreVideoStateChanges = true;
131244b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
131344b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn
131444b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    public void changeToUnPausedState() {
131544b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        int newVideoState = getVideoState() & ~VideoProfile.STATE_PAUSED;
131644b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToUnPausedState - unsetting paused bit; "
131744b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
131844b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn        updateVideoState(newVideoState);
13196dee0e40c77ac373820e7e266ff372a481e30befTyler Gunn        mShouldIgnoreVideoStateChanges = false;
132044b58c8044c5fc0b271432429fc97707c4c773e1Tyler Gunn    }
13217a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn
13227a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn    public void handleDataEnabledChange(boolean isDataEnabled) {
13237a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        mIsVideoEnabled = isDataEnabled;
13247a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        Rlog.i(LOG_TAG, "handleDataEnabledChange: isDataEnabled=" + isDataEnabled
13257a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                + "; updating local video availability.");
13267a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        updateMediaCapabilities(getImsCall());
13277a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        if (mImsVideoCallProviderWrapper != null) {
13287a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn            mImsVideoCallProviderWrapper.setIsVideoEnabled(
13297a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn                    hasCapabilities(Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
13307a411d4797fb60914f5f6230bde24fc25b12f920Tyler Gunn        }
133165cd15597c5e611184a3f4c8ead5f42644fc00d6Tyler Gunn    }
1332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1333