ImsPhoneCallTracker.java revision 2e7e09e79c04f34034bebea8f5d86606bb584577
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
1904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.io.FileDescriptor;
2004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.io.PrintWriter;
2104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.util.ArrayList;
2248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yuimport java.util.HashMap;
2304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.util.List;
2448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yuimport java.util.Map;
2591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunnimport java.util.regex.Pattern;
2604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.app.PendingIntent;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.BroadcastReceiver;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Intent;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.IntentFilter;
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.SharedPreferences;
33508daf6f8286407cf34e32750148fad120009c13Tyler Gunnimport android.net.ConnectivityManager;
34508daf6f8286407cf34e32750148fad120009c13Tyler Gunnimport android.net.NetworkInfo;
35d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajanimport android.net.Uri;
36a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
37df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordonimport android.os.Bundle;
38a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
39a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
40d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.os.PersistableBundle;
41a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.RegistrantList;
43ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport android.os.RemoteException;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemProperties;
45b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganeshimport android.provider.Settings;
46d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.telephony.CarrierConfigManager;
472e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunnimport android.telephony.TelephonyManager;
48d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.text.TextUtils;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.preference.PreferenceManager;
50fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunnimport android.telecom.ConferenceParticipant;
51dc2b5d1c32cad5269106d00fd106bd64097238f4Tyler Gunnimport android.telecom.VideoProfile;
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
53a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
54a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
5504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport android.telephony.ServiceState;
568560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunnimport android.telephony.SubscriptionManager;
5791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunnimport android.util.ArrayMap;
5891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunnimport android.util.Pair;
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCall;
6104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCallProfile;
62cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.comimport com.android.ims.ImsConfig;
639746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiakimport com.android.ims.ImsConfigListener;
6404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsConnectionStateListener;
6504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsEcbm;
6604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsException;
6704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsManager;
6893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnimport com.android.ims.ImsMultiEndpoint;
6904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsReasonInfo;
7004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsServiceClass;
7108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.ims.ImsSuppServiceNotification;
7204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsUtInterface;
73ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.IImsVideoCallProvider;
74ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.ImsVideoCallProviderWrapper;
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Call;
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallTracker;
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandException;
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandsInterface;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
835054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiakimport com.android.internal.telephony.TelephonyEventLog;
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.TelephonyProperties;
852f9f55d539817926542b7db63a41d76badded853Tyler Gunnimport com.android.internal.telephony.dataconnection.DataEnabledSettings;
8608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.internal.telephony.gsm.SuppServiceNotification;
87a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
88a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
89a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
90a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
9193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnpublic class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
92a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ImsPhoneCallTracker";
93a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
9491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public interface PhoneStateListener {
9591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        void onPhoneStateChanged(PhoneConstants.State oldState, PhoneConstants.State newState);
9691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
9791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
98a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
100707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // When true, dumps the state of ImsPhoneCallTracker after changes to foreground and background
101707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // calls.  This is helpful for debugging.
102707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    private static final boolean VERBOSE_STATE_LOGGING = false; /* stopship if true */
103707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
104915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold    //Indices map to ImsConfig.FeatureConstants
105164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private boolean[] mImsFeatureEnabled = {false, false, false, false, false, false};
106164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private final String[] mImsFeatureStrings = {"VoLTE", "ViLTE", "VoWiFi", "ViWiFi",
107164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            "UTLTE", "UTWiFi"};
108cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
1095054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak    private TelephonyEventLog mEventLog;
1105054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onReceive(Context context, Intent intent) {
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (intent.getAction().equals(ImsManager.ACTION_IMS_INCOMING_CALL)) {
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (DBG) log("onReceive : incoming call intent");
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mImsManager == null) return;
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mServiceId < 0) return;
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Network initiated USSD will be treated by mImsUssdListener
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    boolean isUssd = intent.getBooleanExtra(ImsManager.EXTRA_USSD, false);
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (isUssd) {
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (DBG) log("onReceive : USSD");
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mUssdSession = mImsManager.takeCall(mServiceId, intent, mImsUssdListener);
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mUssdSession != null) {
1282999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                            mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        return;
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
13308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    boolean isUnknown = intent.getBooleanExtra(ImsManager.EXTRA_IS_UNKNOWN_CALL,
13408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            false);
13508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (DBG) {
13608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        log("onReceive : isUnknown = " + isUnknown +
13708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " fg = " + mForegroundCall.getState() +
13808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " bg = " + mBackgroundCall.getState());
13908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
14008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
14108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Normal MT/Unknown call
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);
1436bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone, imsCall,
14408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            ImsPhoneCallTracker.this,
14508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            (isUnknown? mForegroundCall: mRingingCall), isUnknown);
14637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
14737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    // If there is an active call.
14837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    if (mForegroundCall.hasConnections()) {
14937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        ImsCall activeCall = mForegroundCall.getFirstConnection().getImsCall();
15037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        boolean answeringWillDisconnect =
15137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                                shouldDisconnectActiveCallOnAnswer(activeCall, imsCall);
15237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        conn.setActiveCallDisconnectedOnAnswer(answeringWillDisconnect);
15337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    }
1548582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                    conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    addConnection(conn);
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
157288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    setVideoCallProvider(conn, imsCall);
158ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
1595054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallReceive(imsCall.getSession());
1605054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
16108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (isUnknown) {
16208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyUnknownConnection(conn);
16308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    } else {
16408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) ||
16508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE)) {
16608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            conn.update(imsCall, ImsPhoneCall.State.WAITING);
16708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        }
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
16908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyNewRingingConnection(conn);
17008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyIncomingRing();
17108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    updatePhoneState();
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyPreciseCallStateChanged();
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (ImsException e) {
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    loge("onReceive : exception " + e);
177ea8cb63201520592011a92849ad3661d22776c87Andrew Lee                } catch (RemoteException e) {
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1798560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            } else if (intent.getAction().equals(
1808560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
1818560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
1828560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1838560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                if (subId == mPhone.getSubId()) {
18437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    cacheCarrierConfiguration(subId);
1858560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    log("onReceive : Updating mAllowEmergencyVideoCalls = " +
1868560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                            mAllowEmergencyVideoCalls);
1878560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                }
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS = 7;
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5;
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_HANGUP_PENDINGMO = 18;
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_RESUME_BACKGROUND = 19;
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DIAL_PENDINGMO = 20;
200e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private static final int EVENT_EXIT_ECBM_BEFORE_PENDINGMO = 21;
20148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private static final int EVENT_VT_DATA_USAGE_UPDATE = 22;
202a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private static final int EVENT_DATA_ENABLED_CHANGED = 23;
203c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private static final int EVENT_GET_IMS_SERVICE = 24;
204508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private static final int EVENT_CHECK_FOR_WIFI_HANDOVER = 25;
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int TIMEOUT_HANGUP_PENDINGMO = 500;
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
208c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    // The number of times we will try to connect to the ImsService before giving up.
209c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private static final int NUM_IMS_SERVICE_RETRIES = 10;
210c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    // The number of milliseconds in between each try.
211c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private static final int TIME_BETWEEN_IMS_SERVICE_RETRIES_MS = 400; // ms
212c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger
213508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private static final int HANDOVER_TO_WIFI_TIMEOUT_MS = 60000; // ms
214508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ArrayList<ImsPhoneConnection> mConnections = new ArrayList<ImsPhoneConnection>();
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallEndedRegistrants = new RegistrantList();
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallStartedRegistrants = new RegistrantList();
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
220ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mRingingCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_RINGING);
221ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mForegroundCall = new ImsPhoneCall(this,
22275ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_FOREGROUND);
223ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this,
22475ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_BACKGROUND);
225ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mHandoverCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_HANDOVER);
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
22748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // Hold aggregated video call data usage for each video call since boot.
22848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // The ImsCall's call id is the key of the map.
22948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>();
23048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private volatile long mTotalVtDataUsage = 0;
23148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneConnection mPendingMO;
233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mClirMode = CommandsInterface.CLIR_DEFAULT;
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Object mSyncHold = new Object();
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mUssdSession = null;
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Message mPendingUssd = null;
238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhone mPhone;
240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDesiredMute = false;    // false = mute off
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mOnHoldToneStarted = false;
243ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn    private int mOnHoldToneId = -1;
244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2459f5345c094210aa5d6606b7705a85a7bc17e831dAmit Mahajan    private PhoneConstants.State mState = PhoneConstants.State.IDLE;
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
247c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private int mImsServiceRetryCount;
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsManager mImsManager;
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mServiceId = -1;
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
25304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean mIsInEmergencyCall = false;
25404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
25504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private int pendingCallClirMode;
256288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private int mPendingCallVideoState;
257c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private Bundle mPendingIntentExtras;
25804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean pendingCallInEcm = false;
259276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private boolean mSwitchingFgAndBgCalls = false;
260276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private ImsCall mCallExpectedToResume = null;
2618560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    private boolean mAllowEmergencyVideoCalls = false;
26204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
26337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
26491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Listeners to changes in the phone state.  Intended for use by other interested IMS components
26591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * without the need to register a full blown {@link android.telephony.PhoneStateListener}.
26691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
26791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private List<PhoneStateListener> mPhoneStateListeners = new ArrayList<>();
26891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
26991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
27037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if video calls which have been downgraded to an
27137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * audio call should be treated as if they are still video calls.
27237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
27337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mTreatDowngradedVideoCallsAsVideoCalls = false;
27437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
27537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
27637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if an ongoing video call over wifi should be
27737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * dropped when an audio call is answered.
27837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
27937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mDropVideoCallWhenAnsweringAudioCall = false;
28037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
2818582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    /**
2828582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * Carrier configuration option which determines whether adding a call during a video call
2838582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * should be allowed.
2848582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     */
2858582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    private boolean mAllowAddCallDuringVideoCall = true;
2868582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu
28791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
288508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * Carrier configuration option which determines whether to notify the connection if a handover
289508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * to wifi fails.
290508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     */
291508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private boolean mNotifyVtHandoverToWifiFail = false;
292508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
293508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    /**
2942e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * Carrier configuration option which determines whether the carrier supports downgrading a
2952e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * TX/RX/TX-RX video call directly to an audio-only call.
2962e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     */
2972e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    private boolean mSupportDowngradeVtToAudio = false;
2982e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
2992e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    /**
30091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Carrier configuration option which defines a mapping from pairs of
30191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * {@link ImsReasonInfo#getCode()} and {@link ImsReasonInfo#getExtraMessage()} values to a new
30291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * {@code ImsReasonInfo#CODE_*} value.
30391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
30491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * See {@link CarrierConfigManager#KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY}.
30591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
30691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private Map<Pair<Integer, String>, Integer> mImsReasonCodeMap = new ArrayMap<>();
30791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Events
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
31375ba09a17a669f4906268088a769836aa87d8241fionaxu    public ImsPhoneCallTracker(ImsPhone phone) {
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        this.mPhone = phone;
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
3167a1c1b02c8603c2bf2f3b401facb389528180eedPavel Zhamaitsiak        mEventLog = new TelephonyEventLog(mPhone.getPhoneId());
3175054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        IntentFilter intentfilter = new IntentFilter();
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
3208560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().registerReceiver(mReceiver, intentfilter);
32237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        cacheCarrierConfiguration(mPhone.getSubId());
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
324a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        mPhone.getDefaultPhone().registerForDataEnabledChanged(
325a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                this, EVENT_DATA_ENABLED_CHANGED, null);
326a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
327c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mImsServiceRetryCount = 0;
328c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // Send a message to connect to the Ims Service and open a connection through
329c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // getImsService().
330c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        sendEmptyMessage(EVENT_GET_IMS_SERVICE);
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PendingIntent createIncomingCallPendingIntent() {
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
335a89314bcc94c43512299131609feea0c2c8167cfLibin.Tang@motorola.com        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                PendingIntent.FLAG_UPDATE_CURRENT);
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
340c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private void getImsService() throws ImsException {
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("getImsService");
34253dde7e076954c250e55d156cc1df1202c3a8a9eEtan Cohen        mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId());
343c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mServiceId = mImsManager.open(ImsServiceClass.MMTEL,
344c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                createIncomingCallPendingIntent(),
345c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                mImsConnectionStateListener);
34604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
347c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mImsManager.setImsConfigListener(mImsConfigListener);
3489746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
349c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // Get the ECBM interface and set IMSPhone's listener object for notifications
350c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        getEcbmInterface().setEcbmStateListener(mPhone.getImsEcbmStateListener());
351c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        if (mPhone.isInEcm()) {
352c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            // Call exit ECBM which will invoke onECBMExited
353c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            mPhone.exitEmergencyCallbackMode();
354c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        }
355c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        int mPreferredTtyMode = Settings.Secure.getInt(
356c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            mPhone.getContext().getContentResolver(),
357c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            Settings.Secure.PREFERRED_TTY_MODE,
358c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            Phone.TTY_MODE_OFF);
359c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, mPreferredTtyMode, null);
360c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger
361c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        ImsMultiEndpoint multiEndpoint = getMultiEndpointInterface();
362c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        if (multiEndpoint != null) {
363c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            multiEndpoint.setExternalCallStateListener(
364c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    mPhone.getExternalCallTracker().getExternalCallStateListener());
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dispose");
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.dispose();
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.dispose();
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.dispose();
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.dispose();
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().unregisterReceiver(mReceiver);
377a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        mPhone.unregisterForDataEnabledChanged(this);
378c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        removeMessages(EVENT_GET_IMS_SERVICE);
379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void finalize() {
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("ImsPhoneCallTracker finalized");
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Methods
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Public Methods
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.add(r);
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.remove(h);
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.add(r);
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.remove(h);
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
41175ba09a17a669f4906268088a769836aa87d8241fionaxu    public Connection dial(String dialString, int videoState, Bundle intentExtras) throws
41275ba09a17a669f4906268088a769836aa87d8241fionaxu            CallStateException {
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
4141a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        int oirMode = sp.getInt(Phone.CLIR_KEY, CommandsInterface.CLIR_DEFAULT);
415df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon        return dial(dialString, oirMode, videoState, intentExtras);
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * oirMode is one of the CLIR_ constants
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    synchronized Connection
422df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon    dial(String dialString, int clirMode, int videoState, Bundle intentExtras)
423df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon            throws CallStateException {
424e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
42504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(dialString);
42604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dial clirMode=" + clirMode);
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // note that this triggers call state changed notif
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("service not available");
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!canDial()) {
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot dial in current state");
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
44004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (isPhoneInEcmMode && isEmergencyNumber) {
44104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            handleEcmTimer(ImsPhone.CANCEL_ECM_TIMER);
44204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
44304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
4448560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // If the call is to an emergency number and the carrier does not support video emergency
4458560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // calls, dial as an audio-only call.
446025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        if (isEmergencyNumber && VideoProfile.isVideo(videoState) &&
4478560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                !mAllowEmergencyVideoCalls) {
4488560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            loge("dial: carrier does not support video emergency calls; downgrade to audio-only");
4498560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            videoState = VideoProfile.STATE_AUDIO_ONLY;
4508560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
4518560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean holdBeforeDial = false;
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // The new call must be assigned to the foreground call.
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // That call must be idle, so place anything that's
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // there on hold
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we should have failed in !canDial() above before we get here
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot dial in current state");
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // foreground call is empty for the newly dialed connection
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            holdBeforeDial = true;
464288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache the video state for pending MO call.
465288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
466c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            mPendingIntentExtras = intentExtras;
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mClirMode = clirMode;
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mSyncHold) {
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (holdBeforeDial) {
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                fgState = mForegroundCall.getState();
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                bgState = mBackgroundCall.getState();
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call failed
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (fgState == ImsPhoneCall.State.ACTIVE) {
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("cannot dial in current state");
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call succeeded
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (bgState == ImsPhoneCall.State.HOLDING) {
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    holdBeforeDial = false;
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4916bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mPendingMO = new ImsPhoneConnection(mPhone,
4928bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    checkForTestEmergencyNumber(dialString), this, mForegroundCall,
4938bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyNumber);
49457d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade            mPendingMO.setVideoState(videoState);
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        addConnection(mPendingMO);
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!holdBeforeDial) {
49904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
500c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, clirMode, videoState, intentExtras);
50104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            } else {
50204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                try {
50304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    getEcbmInterface().exitEmergencyCallbackMode();
50404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                } catch (ImsException e) {
50504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    e.printStackTrace();
50604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    throw new CallStateException("service not available");
50704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
50804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
50904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallClirMode = clirMode;
510288268d5528e0df03f348e303954813cb188c55bRekha Kumar                mPendingCallVideoState = videoState;
51104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallInEcm = true;
51204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mPendingMO;
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5218560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    /**
52237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Caches frequently used carrier configuration items locally.
5238560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     *
5248560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     * @param subId The sub id.
5258560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     */
52637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private void cacheCarrierConfiguration(int subId) {
5278560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
5288560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
5298560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfigManager == null) {
53037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: No carrier config service found.");
53137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
5328560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
5338560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
534025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
5358560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfig == null) {
53637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: Empty carrier config.");
53737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
5388560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
5398560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
54037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mAllowEmergencyVideoCalls =
54137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
54237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mTreatDowngradedVideoCallsAsVideoCalls =
54337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
54437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL);
54537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mDropVideoCallWhenAnsweringAudioCall =
54637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
54737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL);
5488582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu        mAllowAddCallDuringVideoCall =
5498582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                carrierConfig.getBoolean(
5508582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                        CarrierConfigManager.KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL);
551508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        mNotifyVtHandoverToWifiFail = carrierConfig.getBoolean(
552508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                CarrierConfigManager.KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL);
5532e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        mSupportDowngradeVtToAudio = carrierConfig.getBoolean(
5542e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                CarrierConfigManager.KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL);
55591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
55691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        String[] mappings = carrierConfig
55791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                .getStringArray(CarrierConfigManager.KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY);
55891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        if (mappings != null && mappings.length > 0) {
55991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            for (String mapping : mappings) {
56091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                String[] values = mapping.split(Pattern.quote("|"));
56191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                if (values.length != 3) {
56291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    continue;
56391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                }
56491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
56591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                try {
56691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    int fromCode = Integer.parseInt(values[0]);
56791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    String message = values[1];
56891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    int toCode = Integer.parseInt(values[2]);
56991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
57091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    mImsReasonCodeMap.put(new Pair<>(fromCode, message), toCode);
57191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    log("Loaded ImsReasonInfo mapping : fromCode = " + fromCode + " ; message = " +
57291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                            message + " ; toCode = " + toCode);
57391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                } catch (NumberFormatException nfe) {
57491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    loge("Invalid ImsReasonInfo mapping found: " + mapping);
57591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                }
57691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            }
57791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        } else {
57891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            log("No carrier ImsReasonInfo mappings defined.");
57991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
5808560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    }
5818560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
58204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private void handleEcmTimer(int action) {
58304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        mPhone.handleTimerInEmergencyCallbackMode(action);
58404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        switch (action) {
58504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.CANCEL_ECM_TIMER:
58604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
58704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.RESTART_ECM_TIMER:
58804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
58904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            default:
59004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                log("handleEcmTimer, unsupported action " + action);
59104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
59204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
59304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
594c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private void dialInternal(ImsPhoneConnection conn, int clirMode, int videoState,
595c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            Bundle intentExtras) {
596c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getAddress()== null || conn.getAddress().length() == 0
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Phone number is invalid
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Always unmute when initiating a new call
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setMute(false);
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
6126bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
61364e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
61464e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
61564e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        conn.setVideoState(videoState);
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { conn.getAddress() };
619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
6206bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                    serviceType, callType);
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
623c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // Translate call subject intent-extra from Telecom-specific extra key to the
624c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // ImsCallProfile key.
625c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            if (intentExtras != null) {
626c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                if (intentExtras.containsKey(android.telecom.TelecomManager.EXTRA_CALL_SUBJECT)) {
627c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                    intentExtras.putString(ImsCallProfile.EXTRA_DISPLAY_TEXT,
6285c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                            cleanseInstantLetteringMessage(intentExtras.getString(
629d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                                    android.telecom.TelecomManager.EXTRA_CALL_SUBJECT))
630d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                    );
631c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                }
632c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
63367f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                if (intentExtras.containsKey(ImsCallProfile.EXTRA_IS_CALL_PULL)) {
63467f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                    profile.mCallExtras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL,
63567f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                            intentExtras.getBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL));
6363de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    int dialogId = intentExtras.getInt(
6373de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            ImsExternalCallTracker.EXTRA_IMS_EXTERNAL_CALL_ID);
63891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    conn.setIsPulledCall(true);
6393de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    conn.setPulledDialogId(dialogId);
64067f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                }
64167f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn
642c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // Pack the OEM-specific call extras.
643c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                profile.mCallExtras.putBundle(ImsCallProfile.EXTRA_OEM_EXTRAS, intentExtras);
644c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
645c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // NOTE: Extras to be sent over the network are packed into the
646c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // intentExtras individually, with uniquely defined keys.
647c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // These key-value pairs are processed by IMS Service before
648c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // being sent to the lower layers/to the network.
649c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            }
650c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mImsManager.makeCall(mServiceId, profile,
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsCallListener);
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setImsCall(imsCall);
654ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
655c3ec7d484569eff5005ee31fe3c96dfc00b86096Jack Yu            mEventLog.writeOnImsCallStart(imsCall.getSession());
6565054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
657288268d5528e0df03f348e303954813cb188c55bRekha Kumar            setVideoCallProvider(conn, imsCall);
6588582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu            conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("dialInternal : " + e);
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
663ea8cb63201520592011a92849ad3661d22776c87Andrew Lee        } catch (RemoteException e) {
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
6672999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    /**
6682999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * Accepts a call with the specified video state.  The video state is the video state that the
6692999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * user has agreed upon in the InCall UI.
6702999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     *
6712999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @param videoState The video State
6722999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @throws CallStateException
6732999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     */
67475ba09a17a669f4906268088a769836aa87d8241fionaxu    public void acceptCall (int videoState) throws CallStateException {
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("acceptCall");
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState().isAlive()
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mBackgroundCall.getState().isAlive()) {
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot accept call");
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING)
683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mForegroundCall.getState().isAlive()) {
684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
68537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
68637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            boolean answeringWillDisconnect = false;
68737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall activeCall = mForegroundCall.getImsCall();
68837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall ringingCall = mRingingCall.getImsCall();
68937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (mForegroundCall.hasConnections() && mRingingCall.hasConnections()) {
69037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                answeringWillDisconnect =
69137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall);
69237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
69337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
694288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache video state for pending MT call.
695288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
69637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
69737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (answeringWillDisconnect) {
69837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                // We need to disconnect the foreground call before answering the background call.
69937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                mForegroundCall.hangup();
70037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                try {
70137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    ringingCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
70237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                } catch (ImsException e) {
70337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    throw new CallStateException("cannot accept call");
70437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                }
70537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            } else {
70637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                switchWaitingOrHoldingAndActive();
70737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mRingingCall.getState().isRinging()) {
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("acceptCall: incoming...");
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Always unmute when answering a new call
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) {
7152999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                    imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
7165054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallAccept(imsCall.getSession());
717a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("no valid ims call");
719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
721a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot accept call");
722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
723a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
72875ba09a17a669f4906268088a769836aa87d8241fionaxu    public void rejectCall () throws CallStateException {
729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("rejectCall");
730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState().isRinging()) {
732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            hangup(mRingingCall);
733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
738007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
739007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    private void switchAfterConferenceSuccess() {
740007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (DBG) log("switchAfterConferenceSuccess fg =" + mForegroundCall.getState() +
741007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                ", bg = " + mBackgroundCall.getState());
742007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
743007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
744007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            log("switchAfterConferenceSuccess");
745007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            mForegroundCall.switchWith(mBackgroundCall);
746007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        }
747007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    }
748007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
74975ba09a17a669f4906268088a769836aa87d8241fionaxu    public void switchWaitingOrHoldingAndActive() throws CallStateException {
750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("switchWaitingOrHoldingAndActive");
751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState() == ImsPhoneCall.State.INCOMING) {
753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot be in the incoming state");
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mForegroundCall.getImsCall();
758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == null) {
759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("no ims call");
760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
762276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Swap the ImsCalls pointed to by the foreground and background ImsPhoneCalls.
763276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If hold or resume later fails, we will swap them back.
764276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mSwitchingFgAndBgCalls = true;
765276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mCallExpectedToResume = mBackgroundCall.getImsCall();
766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.switchWith(mBackgroundCall);
767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
768276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Hold the foreground call; once the foreground call is held, the background call will
769276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // be resumed.
770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                imsCall.hold();
7725054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCallHold(imsCall.getSession());
773707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
774707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                // If there is no background call to resume, then don't expect there to be a switch.
775707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mCallExpectedToResume == null) {
776707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    mSwitchingFgAndBgCalls = false;
777707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
778a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mForegroundCall.switchWith(mBackgroundCall);
780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException(e.getMessage());
781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            resumeWaitingOrHolding();
784a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
785a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
786a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7877dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
788a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    conference() {
789a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("conference");
790a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
791a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall fgImsCall = mForegroundCall.getImsCall();
792a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (fgImsCall == null) {
793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no foreground ims call");
794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
796a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
797a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall bgImsCall = mBackgroundCall.getImsCall();
798a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (bgImsCall == null) {
799a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no background ims call");
800a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
801a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
802a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
803fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // Keep track of the connect time of the earliest call so that it can be set on the
804fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // {@code ImsConference} when it is created.
8057ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long foregroundConnectTime = mForegroundCall.getEarliestConnectTime();
8067ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long backgroundConnectTime = mBackgroundCall.getEarliestConnectTime();
8077ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long conferenceConnectTime;
8087ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        if (foregroundConnectTime > 0 && backgroundConnectTime > 0) {
8097ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = Math.min(mForegroundCall.getEarliestConnectTime(),
8107ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn                    mBackgroundCall.getEarliestConnectTime());
8117ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - using connect time = " + conferenceConnectTime);
8127ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else if (foregroundConnectTime > 0) {
8137ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - bg call connect time is 0; using fg = " + foregroundConnectTime);
8147ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = foregroundConnectTime;
8157ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else {
8167ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - fg call connect time is 0; using bg = " + backgroundConnectTime);
8177ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = backgroundConnectTime;
8187ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        }
8197ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn
820fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        ImsPhoneConnection foregroundConnection = mForegroundCall.getFirstConnection();
821fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        if (foregroundConnection != null) {
822fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            foregroundConnection.setConferenceConnectTime(conferenceConnectTime);
823fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        }
824fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
825a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
826a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            fgImsCall.merge(bgImsCall);
827a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
828a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference " + e.getMessage());
829a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
830a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
831a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
8327dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
833a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    explicitCallTransfer() {
834a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //TODO : implement
835a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
836a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
8377dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clearDisconnected() {
839a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("clearDisconnected");
840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
841a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        internalClearDisconnected();
842a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
843a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
844a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
845a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
846a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
8477dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
848a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canConference() {
849a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
850a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING
851a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mBackgroundCall.isFull()
852a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mForegroundCall.isFull();
853a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
854a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
8557dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
856a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canDial() {
857a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean ret;
858a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceState = mPhone.getServiceState().getState();
859a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        String disableCall = SystemProperties.get(
860a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
861a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
862a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
863a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mPendingMO == null
864a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mRingingCall.isRinging()
865a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !disableCall.equals("true")
866a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && (!mForegroundCall.getState().isAlive()
867a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    || !mBackgroundCall.getState().isAlive());
868a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
869a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ret;
870a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
871a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
8727dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
873a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canTransfer() {
874a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
875a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING;
876a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
877a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
878a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Private Instance Methods
879a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
880a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
881a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    internalClearDisconnected() {
882a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.clearDisconnected();
883a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.clearDisconnected();
884a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.clearDisconnected();
885a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.clearDisconnected();
886a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
887a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
888a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
889a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    updatePhoneState() {
890a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PhoneConstants.State oldState = mState;
891a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
892a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.isRinging()) {
893a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.RINGING;
894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPendingMO != null ||
895a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())) {
896a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.OFFHOOK;
897a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
898a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.IDLE;
899a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
900a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
901a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState == PhoneConstants.State.IDLE && oldState != mState) {
902a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallEndedRegistrants.notifyRegistrants(
903a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
904a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
905a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallStartedRegistrants.notifyRegistrants (
906a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
907a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
908a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
909a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("updatePhoneState oldState=" + oldState + ", newState=" + mState);
910a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
911a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState != oldState) {
912a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPhoneStateChanged();
9139746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writePhoneState(mState);
91491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            notifyPhoneStateChanged(oldState, mState);
915a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
916a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
917a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
918a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
919a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleRadioNotAvailable() {
920a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // handlePollCalls will clear out its
921a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // call list when it gets the CommandException
922a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // error result from this
923a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pollCallsWhenSafe();
924a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
925a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
926a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
927a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    dumpState() {
928a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        List l;
929a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
930a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Phone State:" + mState);
931a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
932a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Ringing call: " + mRingingCall.toString());
933a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
934a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mRingingCall.getConnections();
935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
938a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
939a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Foreground call: " + mForegroundCall.toString());
940a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
941a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mForegroundCall.getConnections();
942a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Background call: " + mBackgroundCall.toString());
947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mBackgroundCall.getConnections();
949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
952a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
953a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
954a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
955a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhone
956a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
95793c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setUiTTYMode(int uiTtyMode, Message onComplete) {
958cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        if (mImsManager == null) {
959cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            mPhone.sendErrorResponse(onComplete, getImsManagerIsNullException());
960cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            return;
961cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        }
962cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
963b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        try {
964f1099a9dfe0250a6b343de0646413db4034381deEtan Cohen            mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, uiTtyMode, onComplete);
965b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        } catch (ImsException e) {
966b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            loge("setTTYMode : " + e);
967b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            mPhone.sendErrorResponse(onComplete, e);
968b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        }
969b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh    }
970b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
97193c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setMute(boolean mute) {
972a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDesiredMute = mute;
973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.setMute(mute);
974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
975a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
97693c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public boolean getMute() {
977a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDesiredMute;
978a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
979a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
980f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void sendDtmf(char c, Message result) {
981a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendDtmf");
982a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imscall = mForegroundCall.getImsCall();
984a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imscall != null) {
985d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            imscall.sendDtmf(c, result);
986a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
987a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
988a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
9897dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
990c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    startDtmf(char c) {
991c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("startDtmf");
992c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
993c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
994c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
995c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.startDtmf(c);
996c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
997c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("startDtmf : no foreground call");
998c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
999c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
1000c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
10017dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1002c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    stopDtmf() {
1003c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("stopDtmf");
1004c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
1005c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
1006c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
1007c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.stopDtmf();
1008c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
1009c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("stopDtmf : no foreground call");
1010c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
1011c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
1012c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
1013a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneConnection
1014a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1015f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneConnection conn) throws CallStateException {
1016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup connection");
1017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getOwner() != this) {
1019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("ImsPhoneConnection " + conn
1020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "does not belong to ImsPhoneCallTracker " + this);
1021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        hangup(conn.getCall());
1024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1026a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneCall
1027a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1028f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneCall call) throws CallStateException {
1029a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup call");
1030a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1031a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call.getConnections().size() == 0) {
1032a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("no connections");
1033a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1034a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1035a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imsCall = call.getImsCall();
1036a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean rejectCall = false;
1037a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1038a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call == mRingingCall) {
1039a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
1040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            rejectCall = true;
1041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mForegroundCall) {
1042a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (call.isDialingOrAlerting()) {
1043a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
1044a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup dialing or alerting...");
1045a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1046a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
1047a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
1048a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup foreground");
1049a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1050a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //held call will be resumed by onCallTerminated
1051a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1052a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mBackgroundCall) {
1053a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) {
1054a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("(backgnd) hangup waiting or background");
1055a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1056a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1057ac82d4da0473991006a752e2337ccb93e85f0946Etan Cohen            throw new CallStateException ("ImsPhoneCall " + call +
1058a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    "does not belong to ImsPhoneCallTracker " + this);
1059a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1060a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1061a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        call.onHangupLocal();
1062a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1063a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall != null) {
10655054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (rejectCall) {
10665054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE);
10675054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallReject(imsCall.getSession());
10685054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                } else {
10695054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
10705054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallTerminate(imsCall.getSession());
10715054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mPendingMO != null && call == mForegroundCall) {
1073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // is holding a foreground call
1074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED);
1075a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.onDisconnect();
1076a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeConnection(mPendingMO);
1077a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
1078a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
1079a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeMessages(EVENT_DIAL_PENDINGMO);
1080a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1081a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1082a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1083a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1084a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1085a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
1086a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1087a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
108869e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    void callEndCleanupHandOverCallIfAny() {
108969e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        if (mHandoverCall.mConnections.size() > 0) {
109069e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            if (DBG) log("callEndCleanupHandOverCallIfAny, mHandoverCall.mConnections="
109169e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com                    + mHandoverCall.mConnections);
109269e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mHandoverCall.mConnections.clear();
1093d45e0852699f073cb67ef957eadffd4e8130aff5Shriram Ganesh            mConnections.clear();
109469e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mState = PhoneConstants.State.IDLE;
109569e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        }
109669e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    }
109769e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com
1098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1099a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void resumeWaitingOrHolding() throws CallStateException {
1100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("resumeWaitingOrHolding");
1101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getState().isAlive()) {
1104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //resume foreground call after holding background call
1105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //they were switched before holding
1106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mForegroundCall.getImsCall();
11075054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
11085054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
11095054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallResume(imsCall.getSession());
11105054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
1112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //accept waiting call after holding background call
1113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
1114288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (imsCall != null) {
1115288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    imsCall.accept(
1116288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        ImsCallProfile.getCallTypeFromVideoState(mPendingCallVideoState));
11175054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallAccept(imsCall.getSession());
1118288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
1119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
1120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //Just resume background call.
1121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //To distinguish resuming call with swapping calls
1122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we do not switch calls.here
1123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //ImsPhoneConnection.update will chnage the parent when completed
1124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mBackgroundCall.getImsCall();
11255054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
11265054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
11275054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallResume(imsCall.getSession());
11285054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11357dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void sendUSSD (String ussdString, Message response) {
1136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendUSSD");
1137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mUssdSession != null) {
1140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession.sendUssd(ussdString);
1141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                AsyncResult.forMessage(response, null, null);
1142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                response.sendToTarget();
1143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
1144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1146cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            if (mImsManager == null) {
1147cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                mPhone.sendErrorResponse(response, getImsManagerIsNullException());
1148cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                return;
1149cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            }
1150cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
1151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { ussdString };
1152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
1153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE);
1154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_DIALSTRING,
1155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.DIALSTRING_USSD);
1156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession = mImsManager.makeCall(mServiceId, profile,
1158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsUssdListener);
1159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("sendUSSD : " + e);
1161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.sendErrorResponse(response, e);
1162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1165cc8ea4abbe4f1f755dc5cf1b576d51ceb24fe79dAmit Mahajan    public void cancelUSSD() {
1166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUssdSession == null) return;
1167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
1170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1175288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private synchronized ImsPhoneConnection findConnection(final ImsCall imsCall) {
1176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (ImsPhoneConnection conn : mConnections) {
1177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getImsCall() == imsCall) {
1178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return conn;
1179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
1182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void removeConnection(ImsPhoneConnection conn) {
1185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.remove(conn);
11868bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        // If not emergency call is remaining, notify emergency call registrants
11878bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (mIsInEmergencyCall) {
11888bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            boolean isEmergencyCallInList = false;
11898bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            // if no emergency calls pending, set this to false
11908bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            for (ImsPhoneConnection imsPhoneConnection : mConnections) {
11918bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                if (imsPhoneConnection != null && imsPhoneConnection.isEmergency() == true) {
11928bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyCallInList = true;
11938bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    break;
11948bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                }
11958bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            }
11968bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1197a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            if (!isEmergencyCallInList) {
1198a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mIsInEmergencyCall = false;
1199a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mPhone.sendEmergencyCallStateChange(false);
1200a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            }
12018bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void addConnection(ImsPhoneConnection conn) {
1205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.add(conn);
12068bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (conn.isEmergency()) {
12078bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            mIsInEmergencyCall = true;
1208a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            mPhone.sendEmergencyCallStateChange(true);
12098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
12130db65ec818e58fb5b83a492e082db4536f3b83e0Tyler Gunn        if (DBG) log("processCallStateChange " + imsCall + " state=" + state + " cause=" + cause);
1214d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // This method is called on onCallUpdate() where there is not necessarily a call state
1215d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // change. In these situations, we'll ignore the state related updates and only process
1216d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // the change in media capabilities (as expected).  The default is to not ignore state
1217d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // changes so we do not change existing behavior.
1218d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        processCallStateChange(imsCall, state, cause, false /* do not ignore state update */);
1219d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    }
1220d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati
1221d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause,
1222d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            boolean ignoreState) {
1223d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (DBG) {
1224d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            log("processCallStateChange state=" + state + " cause=" + cause
1225d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                    + " ignoreState=" + ignoreState);
1226d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        }
1227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imsCall == null) return;
1229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
1231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneConnection conn = findConnection(imsCall);
1232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
1234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : what should be done?
1235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
1236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1238d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // processCallStateChange is triggered for onCallUpdated as well.
1239d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // onCallUpdated should not modify the state of the call
1240d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // It should modify only other capabilities of call through updateMediaCapabilities
1241d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // State updates will be triggered through individual callbacks
1242d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // i.e. onCallHeld, onCallResume, etc and conn.update will be responsible for the update
124357d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade        conn.updateMediaCapabilities(imsCall);
1244d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (ignoreState) {
124527e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati            conn.updateAddressDisplay(imsCall);
124621048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            conn.updateExtras(imsCall);
12473652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
12483652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            maybeSetVideoCallProvider(conn, imsCall);
1249d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            return;
1250d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        }
1251d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn
1252d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        changed = conn.update(imsCall, state);
1253d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        if (state == ImsPhoneCall.State.DISCONNECTED) {
1254d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            changed = conn.onDisconnect(cause) || changed;
1255d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            //detach the disconnected connections
1256d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            conn.getCall().detach(conn);
1257d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            removeConnection(conn);
1258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (changed) {
1261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getCall() == mHandoverCall) return;
1262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
1263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
1264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
12673652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    private void maybeSetVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall) {
12683652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        android.telecom.Connection.VideoProvider connVideoProvider = conn.getVideoProvider();
12693652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        if (connVideoProvider != null || imsCall.getCallSession().getVideoCallProvider() == null) {
12703652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            return;
12713652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
12723652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
12733652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        try {
12743652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            setVideoCallProvider(conn, imsCall);
12753652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        } catch (RemoteException e) {
12763652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            loge("maybeSetVideoCallProvider: exception " + e);
12773652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
12783652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    }
12793652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
128091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
128191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Returns the {@link ImsReasonInfo#getCode()}, potentially remapping to a new value based on
128291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * the {@link ImsReasonInfo#getCode()} and {@link ImsReasonInfo#getExtraMessage()}.
128391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
128491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * See {@link #mImsReasonCodeMap}.
128591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
128691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param reasonInfo The {@link ImsReasonInfo}.
128791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @return The remapped code.
128891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
128991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private int maybeRemapReasonCode(ImsReasonInfo reasonInfo) {
129091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        int code = reasonInfo.getCode();
129191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
129291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        Pair<Integer, String> toCheck = new Pair<>(code, reasonInfo.getExtraMessage());
129391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
129491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        if (mImsReasonCodeMap.containsKey(toCheck)) {
129591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            int toCode = mImsReasonCodeMap.get(toCheck);
129691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
129791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            log("maybeRemapReasonCode : fromCode = " + reasonInfo.getCode() + " ; message = "
129891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    + reasonInfo.getExtraMessage() + " ; toCode = " + toCode);
129991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            return toCode;
130091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
130191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        return code;
130291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
130391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
1304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int getDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
1305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int cause = DisconnectCause.ERROR_UNSPECIFIED;
1306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //int type = reasonInfo.getReasonType();
130891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        int code = maybeRemapReasonCode(reasonInfo);
1309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (code) {
1310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_ADDRESS:
1311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_REACHABLE:
1312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NUMBER_UNREACHABLE;
1313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BUSY:
1315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.BUSY;
1316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED:
1318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.LOCAL;
1319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
13203b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com            case ImsReasonInfo.CODE_LOCAL_CALL_DECLINE:
132191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_REMOTE_CALL_DECLINE:
132291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                // If the call has been declined locally (on this device), or on remotely (on
132391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                // another device using multiendpoint functionality), mark it as rejected.
13243b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                return DisconnectCause.INCOMING_REJECTED;
13253b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com
1326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE:
1327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NORMAL;
1328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
132991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_SIP_FORBIDDEN:
133091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                return DisconnectCause.SERVER_ERROR;
133191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
1332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REDIRECTED:
1333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_REQUEST:
1334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE:
1335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_USER_REJECTED:
1336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_GLOBAL_ERROR:
1337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_ERROR;
1338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE:
1340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_FOUND:
1341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVER_ERROR:
1342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_UNREACHABLE;
1343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING:
1345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED:
1346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN:
1347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE:
1348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED:
1349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE:
1350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE:
1351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING:
1352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.OUT_OF_SERVICE;
1353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT:
1355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING:
1356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER:
1357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE:
1358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.TIMED_OUT;
1359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_LOW_BATTERY:
1361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_POWER_OFF:
1362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.POWER_OFF;
1363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
136408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            case ImsReasonInfo.CODE_FDN_BLOCKED:
136508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                return DisconnectCause.FDN_BLOCKED;
13661c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn
13671c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_ANSWERED_ELSEWHERE:
13685deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn                return DisconnectCause.ANSWERED_ELSEWHERE;
13695deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn
13701c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_CALL_END_CAUSE_CALL_PULL:
13711c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn                return DisconnectCause.CALL_PULLED;
137291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
137391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED:
137491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                return DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED;
13752f9f55d539817926542b7db63a41d76badded853Tyler Gunn
13762f9f55d539817926542b7db63a41d76badded853Tyler Gunn            case ImsReasonInfo.CODE_DATA_DISABLED:
13772f9f55d539817926542b7db63a41d76badded853Tyler Gunn                return DisconnectCause.DATA_DISABLED;
13782f9f55d539817926542b7db63a41d76badded853Tyler Gunn
13792f9f55d539817926542b7db63a41d76badded853Tyler Gunn            case ImsReasonInfo.CODE_DATA_LIMIT_REACHED:
13802f9f55d539817926542b7db63a41d76badded853Tyler Gunn                return DisconnectCause.DATA_LIMIT_REACHED;
1381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            default:
1382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return cause;
1385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1388e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * @return true if the phone is in Emergency Callback mode, otherwise false
1389e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1390e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private boolean isPhoneInEcbMode() {
1391e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        return SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false);
1392e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1393e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1394e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1395e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * Before dialing pending MO request, check for the Emergency Callback mode.
1396e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * If device is in Emergency callback mode, then exit the mode before dialing pending MO.
1397e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1398e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private void dialPendingMO() {
1399e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
1400e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isEmergencyNumber = mPendingMO.isEmergency();
1401e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
1402e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_DIAL_PENDINGMO);
1403e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        } else {
1404e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_EXIT_ECBM_BEFORE_PENDINGMO);
1405e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        }
1406e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1407e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1408e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsCallListener = new ImsCall.Listener() {
1412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallProgressing(ImsCall imsCall) {
1414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallProgressing");
1415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ALERTING,
1418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
14195054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallProgressing(imsCall.getCallSession());
1420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStarted");
1425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1429508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
1430508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (mNotifyVtHandoverToWifiFail &&
1431508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    !imsCall.isWifiCall() && imsCall.isVideoCall() && isWifiConnected()) {
1432508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // Schedule check to see if handover succeeded.
1433508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                sendMessageDelayed(obtainMessage(EVENT_CHECK_FOR_WIFI_HANDOVER, imsCall),
1434508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        HANDOVER_TO_WIFI_TIMEOUT_MS);
1435508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
1436508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
14375054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallStarted(imsCall.getCallSession());
1438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1440288268d5528e0df03f348e303954813cb188c55bRekha Kumar        @Override
1441288268d5528e0df03f348e303954813cb188c55bRekha Kumar        public void onCallUpdated(ImsCall imsCall) {
1442288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (DBG) log("onCallUpdated");
1443288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (imsCall == null) {
1444288268d5528e0df03f348e303954813cb188c55bRekha Kumar                return;
1445288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1446288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsPhoneConnection conn = findConnection(imsCall);
1447288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (conn != null) {
1448288268d5528e0df03f348e303954813cb188c55bRekha Kumar                processCallStateChange(imsCall, conn.getCall().mState,
1449d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                        DisconnectCause.NOT_DISCONNECTED, true /*ignore state update*/);
14505054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeImsCallState(imsCall.getCallSession(), conn.getCall().mState);
1451288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1452288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
1453288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /**
1455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * onCallStartFailed will be invoked when:
1456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 1) Dialing fails
1457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 2) Ringing call is disconnected by local or remote user
1458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
1459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
1462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPendingMO != null) {
1464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // To initiate dialing circuit-switched call
1465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
1466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mBackgroundCall.getState() == ImsPhoneCall.State.IDLE
1467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mRingingCall.getState() == ImsPhoneCall.State.IDLE) {
1468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.detach(mPendingMO);
1469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.finalize();
1471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.initiateSilentRedial();
1473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return;
1474990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                } else {
14752770b0f5449670eadab1d68ea8d5fa4788f4704aSantos Cordon                    mPendingMO = null;
1476990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1477990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
1478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
14795054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCallStartFailed(imsCall.getCallSession(), reasonInfo);
1480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallTerminated reasonCode=" + reasonInfo.getCode());
1486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneCall.State oldState = mForegroundCall.getState();
1488bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1489bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            ImsPhoneConnection conn = findConnection(imsCall);
1490bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            if (DBG) log("cause = " + cause + " conn = " + conn);
1491bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com
1492db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (conn != null) {
1493db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                android.telecom.Connection.VideoProvider videoProvider = conn.getVideoProvider();
1494db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1495db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    ImsVideoCallProviderWrapper wrapper = (ImsVideoCallProviderWrapper)
1496db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            videoProvider;
1497db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1498db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    wrapper.removeImsVideoProviderCallback(conn);
1499db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                }
1500db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1501ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            if (mOnHoldToneId == System.identityHashCode(conn)) {
1502ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                if (conn != null && mOnHoldToneStarted) {
1503ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.stopOnHoldTone(conn);
1504ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                }
1505ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneStarted = false;
1506ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneId = -1;
1507ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            }
15083de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn            if (conn != null) {
15093de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                if (conn.isPulledCall() && (
15103de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_CALL_PULL_OUT_OF_SYNC ||
151148208a24933a644261184f47517a6a8ed7d6fd54Tyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_TEMPRARILY_UNAVAILABLE ||
151248208a24933a644261184f47517a6a8ed7d6fd54Tyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_FORBIDDEN) &&
15133de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        mPhone != null && mPhone.getExternalCallTracker() != null) {
15143de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn
15153de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    log("Call pull failed.");
15163de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Call was being pulled, but the call pull has failed -- inform the associated
15173de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // TelephonyConnection that the pull failed, and provide it with the original
15183de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // external connection which was pulled so that it can be swapped back.
15193de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    conn.onCallPullFailed(mPhone.getExternalCallTracker()
15203de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            .getConnectionById(conn.getPulledDialogId()));
15213de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Do not mark as disconnected; the call will just change from being a regular
15223de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // call to being an external call again.
15233de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    cause = DisconnectCause.NOT_DISCONNECTED;
15243de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn
15253de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                } else if (conn.isIncoming() && conn.getConnectTime() == 0
15263de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        && cause != DisconnectCause.ANSWERED_ELSEWHERE) {
15273de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Missed
15283de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    if (cause == DisconnectCause.NORMAL) {
15293de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        cause = DisconnectCause.INCOMING_MISSED;
15303de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    } else {
15313de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        cause = DisconnectCause.INCOMING_REJECTED;
15323de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    }
15333de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    if (DBG) log("Incoming connection of 0 connect time detected - translated " +
15343de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            "cause = " + cause);
153517e77849f88cf20dc5a28aeede66b839fbbdb831Uma Maheswari Ramalingam                }
1536bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            }
1537f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1538f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            if (cause == DisconnectCause.NORMAL && conn != null && conn.getImsCall().isMerged()) {
1539f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                // Call was terminated while it is merged instead of a remote disconnect.
1540f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                cause = DisconnectCause.IMS_MERGED_SUCCESSFULLY;
1541f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            }
1542f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
15439746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writeOnImsCallTerminated(imsCall.getCallSession(), reasonInfo);
15449746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
1545bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
154608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (mForegroundCall.getState() != ImsPhoneCall.State.ACTIVE) {
154708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                if (mRingingCall.getState().isRinging()) {
154808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Drop pending MO. We should address incoming call first
154908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    mPendingMO = null;
155008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else if (mPendingMO != null) {
155108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    sendEmptyMessage(EVENT_DIAL_PENDINGMO);
155208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                }
155308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            }
15541a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu
15551a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            if (mSwitchingFgAndBgCalls) {
15561a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (DBG) {
15571a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    log("onCallTerminated: Call terminated in the midst of Switching " +
15581a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                            "Fg and Bg calls.");
15591a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
15601a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // If we are the in midst of swapping FG and BG calls and the call that was
15611a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // terminated was the one that we expected to resume, we need to swap the FG and
15621a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // BG calls back.
15631a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (imsCall == mCallExpectedToResume) {
15641a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (DBG) {
15651a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        log("onCallTerminated: switching " + mForegroundCall + " with "
15661a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                                + mBackgroundCall);
15671a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
15681a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mForegroundCall.switchWith(mBackgroundCall);
15691a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
15701a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // This call terminated in the midst of a switch after the other call was held, so
15711a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // resume it back to ACTIVE state since the switch failed.
15721a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
15731a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    sendEmptyMessage(EVENT_RESUME_BACKGROUND);
15741a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mSwitchingFgAndBgCalls = false;
15751a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mCallExpectedToResume = null;
15761a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
15771a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            }
1578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHeld(ImsCall imsCall) {
1582707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (DBG) {
1583707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mForegroundCall.getImsCall() == imsCall) {
1584707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (fg) " + imsCall);
1585707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                } else if (mBackgroundCall.getImsCall() == imsCall) {
1586707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (bg) " + imsCall);
1587707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1588707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
1589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State oldState = mBackgroundCall.getState();
1592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
1593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        DisconnectCause.NOT_DISCONNECTED);
1594c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1595c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // Note: If we're performing a switchWaitingOrHoldingAndActive, the call to
1596c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // processCallStateChange above may have caused the mBackgroundCall and
1597c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // mForegroundCall references below to change meaning.  Watch out for this if you
1598c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // are reading through this code.
1599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (oldState == ImsPhoneCall.State.ACTIVE) {
1600276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // Note: This case comes up when we have just held a call in response to a
1601276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // switchWaitingOrHoldingAndActive.  We now need to resume the background call.
1602276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // The EVENT_RESUME_BACKGROUND causes resumeWaitingOrHolding to be called.
1603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
1604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
1605f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    } else {
1607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //when multiple connections belong to background call,
1608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //only the first callback reaches here
1609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //otherwise the oldState is already HOLDING
1610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mPendingMO != null) {
1611e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                            dialPendingMO();
1612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
1613c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1614c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // In this case there will be no call resumed, so we can assume that we
1615c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // are done switching fg and bg calls now.
1616c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // This may happen if there is no BG call and we are holding a call so that
1617c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // we can dial another one.
1618c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        mSwitchingFgAndBgCalls = false;
1619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
16201a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                } else if (oldState == ImsPhoneCall.State.IDLE && mSwitchingFgAndBgCalls) {
16211a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // The other call terminated in the midst of a switch before this call was held,
16221a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // so resume the foreground call back to ACTIVE state since the switch failed.
16231a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
16241a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        sendEmptyMessage(EVENT_RESUME_BACKGROUND);
16251a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mSwitchingFgAndBgCalls = false;
16261a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mCallExpectedToResume = null;
16271a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
1628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
16305054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHeld(imsCall.getCallSession());
1631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldFailed reasonCode=" + reasonInfo.getCode());
1636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State bgState = mBackgroundCall.getState();
1639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
1640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // disconnected while processing hold
1641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1642e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        dialPendingMO();
1643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else if (bgState == ImsPhoneCall.State.ACTIVE) {
1645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.switchWith(mBackgroundCall);
1646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
1649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
1650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
16525326ba5f8e9488416fd7160680dc6b6319c6b00eAnju Mathapati                mPhone.notifySuppServiceFailed(Phone.SuppService.HOLD);
1653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
16545054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHoldFailed(imsCall.getCallSession(), reasonInfo);
1655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumed(ImsCall imsCall) {
1659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumed");
1660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1661276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If we are the in midst of swapping FG and BG calls and the call we end up resuming
1662276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // is not the one we expected, we likely had a resume failure and we need to swap the
1663276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // FG and BG calls back.
16640ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn            if (mSwitchingFgAndBgCalls) {
16650ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                if (imsCall != mCallExpectedToResume) {
16660ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // If the call which resumed isn't as expected, we need to swap back to the
16670ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // previous configuration; the swap has failed.
16680ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
16690ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : switching " + mForegroundCall + " with "
16700ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                                + mBackgroundCall);
16710ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
16720ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    mForegroundCall.switchWith(mBackgroundCall);
16730ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                } else {
16740ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // The call which resumed is the one we expected to resume, so we can clear out
16750ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // the mSwitchingFgAndBgCalls flag.
16760ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
16770ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : expected call resumed.");
16780ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
1679707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1680276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1681276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1682276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
16855054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumed(imsCall.getCallSession());
1686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1690afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati            if (mSwitchingFgAndBgCalls) {
1691afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // If we are in the midst of swapping the FG and BG calls and
1692afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // we got a resume fail, we need to swap back the FG and BG calls.
1693afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // Since the FG call was held, will also try to resume the same.
1694afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                if (imsCall == mCallExpectedToResume) {
1695afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (DBG) {
1696afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                        log("onCallResumeFailed : switching " + mForegroundCall + " with "
1697afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                                + mBackgroundCall);
1698afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
1699afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    mForegroundCall.switchWith(mBackgroundCall);
1700afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
1701afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1702afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
1703707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1704afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati
1705afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                //Call swap is done, reset the relevant variables
1706276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1707276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1708276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1709276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mPhone.notifySuppServiceFailed(Phone.SuppService.RESUME);
17105054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumeFailed(imsCall.getCallSession(), reasonInfo);
1711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeReceived(ImsCall imsCall) {
1715a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumeReceived");
1716ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
1717ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            if (conn != null && mOnHoldToneStarted) {
1718ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mPhone.stopOnHoldTone(conn);
1719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mOnHoldToneStarted = false;
1720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
172108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
172208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
172308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
172408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
172508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
172608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_RETRIEVED;
172708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
17285054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumeReceived(imsCall.getCallSession());
1729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldReceived(ImsCall imsCall) {
1733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldReceived");
1734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneConnection conn = findConnection(imsCall);
1736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn != null && conn.getState() == ImsPhoneCall.State.ACTIVE) {
1737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (!mOnHoldToneStarted && ImsPhoneCall.isLocalTone(imsCall)) {
1738ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.startOnHoldTone(conn);
1739a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mOnHoldToneStarted = true;
1740ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mOnHoldToneId = System.identityHashCode(conn);
1741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1742a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
174308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
174408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
174508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
174608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
174708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
174808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_ON_HOLD;
174908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
17505054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHoldReceived(imsCall.getCallSession());
175108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        }
175208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
175308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        @Override
175408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
175508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                ImsSuppServiceNotification suppServiceInfo) {
175608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (DBG) log("onCallSuppServiceReceived: suppServiceInfo=" + suppServiceInfo);
175708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
175808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
17598762e33ba987774e43aa9f4e216ebdb084d3a03eTyler Gunn            supp.notificationType = suppServiceInfo.notificationType;
176008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = suppServiceInfo.code;
176108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.index = suppServiceInfo.index;
176208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.number = suppServiceInfo.number;
176308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.history = suppServiceInfo.history;
176408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
176508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
1766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1769007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        public void onCallMerged(final ImsCall call, final ImsCall peerCall, boolean swapCalls) {
1770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallMerged");
1771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1772707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall foregroundImsPhoneCall = findConnection(call).getCall();
1773007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            ImsPhoneConnection peerConnection = findConnection(peerCall);
1774707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall peerImsPhoneCall = peerConnection == null ? null
1775707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    : peerConnection.getCall();
1776007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1777fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            if (swapCalls) {
1778007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                switchAfterConferenceSuccess();
1779fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            }
1780707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            foregroundImsPhoneCall.merge(peerImsPhoneCall, ImsPhoneCall.State.ACTIVE);
1781007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1782ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            try {
1783ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                final ImsPhoneConnection conn = findConnection(call);
1784ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: ImsPhoneConnection=" + conn);
1785ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1786ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                setVideoCallProvider(conn, call);
1787ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1788ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            } catch (Exception e) {
1789ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                loge("onCallMerged: exception " + e);
1790ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            }
1791288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1792007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // After merge complete, update foreground as Active
1793007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // and background call as Held, if background call exists
1794007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            processCallStateChange(mForegroundCall.getImsCall(), ImsPhoneCall.State.ACTIVE,
1795007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1796007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (peerConnection != null) {
1797007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                processCallStateChange(mBackgroundCall.getImsCall(), ImsPhoneCall.State.HOLDING,
1798007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1799007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1800df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon
1801007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // Check if the merge was requested by an existing conference call. In that
1802007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // case, no further action is required.
1803007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (!call.isMergeRequestedByConf()) {
1804007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: calling onMultipartyStateChanged()");
1805007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                onMultipartyStateChanged(call, true);
1806007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            } else {
1807007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: Merge requested by existing conference.");
1808007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                // Reset the flag.
1809007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                call.resetIsMergeRequestedByConf(false);
1810007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1811707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            logState();
1812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1813a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1814a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1815a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
18164e47e27d1d2cbd8e533cdd2081c5bc8e51b79ad9Anthony Lee            if (DBG) log("onCallMergeFailed reasonInfo=" + reasonInfo);
181752c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
181852c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // TODO: the call to notifySuppServiceFailed throws up the "merge failed" dialog
181952c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // We should move this into the InCallService so that it is handled appropriately
182052c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // based on the user facing UI.
1821bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
182252c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
182352c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // Start plumbing this even through Telecom so other components can take
182452c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // appropriate action.
182552c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            ImsPhoneConnection conn = findConnection(call);
182652c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            if (conn != null) {
182752c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee                conn.onConferenceMergeFailed();
182852c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            }
1829a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1830fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1831fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        /**
1832f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
1833fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         *
1834fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         * @param call the call object that carries out the IMS call.
1835f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * @param participants the participant(s) and their new state information.
1836fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         */
1837fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        @Override
1838f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
1839f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                List<ConferenceParticipant> participants) {
1840f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn            if (DBG) log("onConferenceParticipantsStateChanged");
1841fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1842fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            ImsPhoneConnection conn = findConnection(call);
1843fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            if (conn != null) {
1844f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                conn.updateConferenceParticipants(participants);
1845fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            }
1846fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        }
18476d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak
18486d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        @Override
18496d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
18506d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak            mPhone.onTtyModeReceived(mode);
18516d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        }
18520ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
18530ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
18540ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
18550ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
18560ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
18570ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech=" +
18580ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    targetAccessTech + ", reasonInfo=" + reasonInfo);
18590ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
18600b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn
1861508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            boolean isHandoverToWifi = srcAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN &&
1862508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    targetAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
1863508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (isHandoverToWifi) {
1864508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // If we handed over to wifi successfully, don't check for failure in the future.
1865508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
1866508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
1867508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
18685054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHandover(imsCall.getCallSession(),
18695054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    srcAccessTech, targetAccessTech, reasonInfo);
18700ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
18710ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
18720ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
18730ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
18740ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
18750ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
18760ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandoverFailed :: srcAccessTech=" + srcAccessTech +
18770ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" + reasonInfo);
18780ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
18795054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHandoverFailed(imsCall.getCallSession(),
18805054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    srcAccessTech, targetAccessTech, reasonInfo);
18810b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn
18820b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            boolean isHandoverToWifi = srcAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN &&
18830b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn                    targetAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
18840b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
18850b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            if (conn != null && isHandoverToWifi) {
18860b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn                log("onCallHandoverFailed - handover to WIFI Failed");
1887508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
1888508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // If we know we failed to handover, don't check for failure in the future.
1889508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
1890508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
1891508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                if (mNotifyVtHandoverToWifiFail) {
1892508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    // Only notify others if carrier config indicates to do so.
1893508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    conn.onHandoverToWifiFailed();
1894508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                }
18950b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            }
18960ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
1897ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1898ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        /**
1899ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
1900ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * {@link ImsPhoneConnection} of the change.
1901ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *
1902ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param imsCall The IMS call.
1903ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
1904ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *      otherwise.
1905ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         */
1906ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        @Override
1907ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
1908ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (DBG) log("onMultipartyStateChanged to " + (isMultiParty ? "Y" : "N"));
1909ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1910ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
1911ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (conn != null) {
1912ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                conn.updateMultipartyState(isMultiParty);
1913ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            }
1914ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        }
1915a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1916a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1917a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1918a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1919a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1920a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsUssdListener = new ImsCall.Listener() {
1921a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1922a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1923a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStarted");
1924a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1925a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1926a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1927a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd);
1928a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1929a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1930a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1931a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1932a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1933a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1934a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStartFailed reasonCode=" + reasonInfo.getCode());
1937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1938a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
1939a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1940a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1941a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1942a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallTerminated reasonCode=" + reasonInfo.getCode());
1944508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
1945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession = null;
1948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    CommandException ex =
1950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            new CommandException(CommandException.Error.GENERIC_FAILURE);
1951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd, null, ex);
1952a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1953a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1954a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1955a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1956a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imsCall.close();
1957a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1958a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1959a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1960a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallUssdMessageReceived(ImsCall call,
1961a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                int mode, String ussdMessage) {
1962a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallUssdMessageReceived mode=" + mode);
1963a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1964a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int ussdMode = -1;
1965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1966a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch(mode) {
1967a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_REQUEST:
1968a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_REQUEST;
1969a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1970a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1971a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_NOTIFY:
1972a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_NOTIFY;
1973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1975a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1976a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.onIncomingUSSD(ussdMode, ussdMessage);
1977a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1978a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1979a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1980a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1981a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS service state change
1982a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     *
1983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1984a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsConnectionStateListener mImsConnectionStateListener =
1985a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        new ImsConnectionStateListener() {
1986a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1987a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsConnected() {
1988a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsConnected");
1989a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1990bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(true);
19915054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
19925054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_CONNECTED, null);
1993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
19960ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
19970ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);
1998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1999bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(false);
200053f2bb9ba3118ff4c22e20ab3ad46ec97a72ac24Pavel Zhamaitsiak            mPhone.processDisconnectReason(imsReasonInfo);
20015054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
20025054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_DISCONNECTED, imsReasonInfo);
2003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2004a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2005a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
20060ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsProgressing() {
20070ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsProgressing");
200808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
200908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setImsRegistered(false);
20105054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
20115054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_PROGRESSING, null);
20120ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
20130ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
20140ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
2015a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsResumed() {
2016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsResumed");
2017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
20185054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
20195054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_RESUMED, null);
2020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsSuspended() {
2024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsSuspended");
2025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
20265054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
20275054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_SUSPENDED, null);
2028a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2029cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2030cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        @Override
2031cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        public void onFeatureCapabilityChanged(int serviceClass,
2032cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                int[] enabledFeatures, int[] disabledFeatures) {
2033cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            if (serviceClass == ImsServiceClass.MMTEL) {
2034288268d5528e0df03f348e303954813cb188c55bRekha Kumar                boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
203504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
2036c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                StringBuilder sb;
2037c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
2038c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb = new StringBuilder(120);
2039c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb.append("onFeatureCapabilityChanged: ");
2040c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
204162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                for (int  i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
204208111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI &&
204308111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i < enabledFeatures.length; i++) {
204462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    if (enabledFeatures[i] == i) {
204504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // If the feature is set to its own integer value it is enabled.
2046c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
2047c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
2048c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":true ");
2049c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
2050c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
205162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = true;
205204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else if (enabledFeatures[i]
205304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                            == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
205404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled.
2055c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
2056c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
2057c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":false ");
2058c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
2059c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
206062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = false;
206104b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else {
206204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // Feature has unknown state; it is not its own value or -1.
206304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        if (DBG) {
2064c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            loge("onFeatureCapabilityChanged(" + i + ", " + mImsFeatureStrings[i]
2065c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                                    + "): unexpectedValue=" + enabledFeatures[i]);
206604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        }
206762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    }
2068cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                }
2069c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
2070c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    log(sb.toString());
2071c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
2072288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {
2073288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
2074288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
207504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee
207604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // TODO: Use the ImsCallSession or ImsCallProfile to tell the initial Wifi state and
207704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // {@link ImsCallSession.Listener#callSessionHandover} to listen for changes to
207804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // wifi capability caused by a handover.
2079164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                if (DBG) log("onFeatureCapabilityChanged: isVolteEnabled=" + isVolteEnabled()
2080164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVideoCallEnabled=" + isVideoCallEnabled()
2081164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVowifiEnabled=" + isVowifiEnabled()
2082164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isUtEnabled=" + isUtEnabled());
208304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                for (ImsPhoneConnection connection : mConnections) {
208404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    connection.updateWifiState();
208504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                }
2086e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak
2087e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak                mPhone.onFeatureCapabilityChanged();
20885054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
20895054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCapabilities(mImsFeatureEnabled);
2090cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            }
2091cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        }
209203545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade
209303545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        @Override
209403545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        public void onVoiceMessageCountChanged(int count) {
209503545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            if (DBG) log("onVoiceMessageCountChanged :: count=" + count);
209603545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            mPhone.mDefaultPhone.setVoiceMessageCount(count);
209703545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        }
2098d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan
2099d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        @Override
2100d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        public void registrationAssociatedUriChanged(Uri[] uris) {
2101d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan            if (DBG) log("registrationAssociatedUriChanged");
2102d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan            mPhone.setCurrentSubscriberUris(uris);
2103d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        }
2104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
2105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
21069746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    private ImsConfigListener.Stub mImsConfigListener = new ImsConfigListener.Stub() {
21079746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
21089746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetFeatureResponse(int feature, int network, int value, int status) {}
21099746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
21109746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
21119746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetFeatureResponse(int feature, int network, int value, int status) {
21129746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writeImsSetFeatureValue(feature, network, value, status);
21139746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        }
21149746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
21159746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
21169746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetVideoQuality(int status, int quality) {}
21179746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
21189746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
21199746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetVideoQuality(int status) {}
21209746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
21219746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    };
21229746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
212393c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public ImsUtInterface getUtInterface() throws ImsException {
2124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
2125cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
2126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration(mServiceId);
2129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ut;
2130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
21324be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    private void transferHandoverConnections(ImsPhoneCall call) {
21334be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.mConnections != null) {
21344be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : call.mConnections) {
21354be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                c.mPreHandoverState = call.mState;
21364be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                log ("Connection state before handover is " + c.getStateBeforeHandover());
21374be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
21384be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
21394be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections == null ) {
21404be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections = call.mConnections;
21414be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        } else { // Multi-call SRVCC
21424be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections.addAll(call.mConnections);
21434be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
21444be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections != null) {
21454be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            if (call.getImsCall() != null) {
21464be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                call.getImsCall().close();
21474be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
21484be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : mHandoverCall.mConnections) {
21494be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                ((ImsPhoneConnection)c).changeParent(mHandoverCall);
215052c193f0c615a9153a702ea2597217202613e413Libin.Tang@motorola.com                ((ImsPhoneConnection)c).releaseWakeLock();
21514be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
21524be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
21534be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.getState().isAlive()) {
21544be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            log ("Call is alive and state is " + call.mState);
21554be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mState = call.mState;
21564be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
21574be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mConnections.clear();
21584be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mState = ImsPhoneCall.State.IDLE;
21594be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    }
21604be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam
2161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
2162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void notifySrvccState(Call.SrvccState state) {
2163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("notifySrvccState state=" + state);
2164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mSrvccState = state;
2166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mSrvccState == Call.SrvccState.COMPLETED) {
21684be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mForegroundCall);
21694be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mBackgroundCall);
21704be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mRingingCall);
2171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //****** Overridden from Handler
2175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void
2178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleMessage (Message msg) {
2179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
2180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("handleMessage what=" + msg.what);
2181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (msg.what) {
2183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_HANGUP_PENDINGMO:
2184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingMO != null) {
2185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.onDisconnect();
2186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
2187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
2188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2189c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
2191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.notifyPreciseCallStateChanged();
2192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_RESUME_BACKGROUND:
2194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
2195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    resumeWaitingOrHolding();
2196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (CallStateException e) {
2197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (Phone.DEBUG_PHONE) {
2198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e);
2199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
2200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_DIAL_PENDINGMO:
2203c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, mClirMode, mPendingCallVideoState, mPendingIntentExtras);
2204c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
220604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
2207e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            case EVENT_EXIT_ECBM_BEFORE_PENDINGMO:
2208e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                if (mPendingMO != null) {
2209e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    //Send ECBM exit request
2210e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    try {
2211e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        getEcbmInterface().exitEmergencyCallbackMode();
2212e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
2213e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallClirMode = mClirMode;
2214e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallInEcm = true;
2215e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    } catch (ImsException e) {
2216e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        e.printStackTrace();
2217e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
2218e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
2219e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    }
2220e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                }
2221e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                break;
2222e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
222304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case EVENT_EXIT_ECM_RESPONSE_CDMA:
222404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // no matter the result, we still do the same here
222504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                if (pendingCallInEcm) {
2226288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    dialInternal(mPendingMO, pendingCallClirMode,
2227c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                            mPendingCallVideoState, mPendingIntentExtras);
2228c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                    mPendingIntentExtras = null;
222904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    pendingCallInEcm = false;
223004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
223104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.unsetOnEcbModeExitResponse(this);
223204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
223348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            case EVENT_VT_DATA_USAGE_UPDATE:
223448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ar = (AsyncResult) msg.obj;
223548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ImsCall call = (ImsCall) ar.userObj;
223648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long usage = (long) ar.result;
223748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                log("VT data usage update. usage = " + usage + ", imsCall = " + call);
223848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
223948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long oldUsage = 0L;
224048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                if (mVtDataUsageMap.containsKey(call.uniqueId)) {
224148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    oldUsage = mVtDataUsageMap.get(call.uniqueId);
224248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                }
224348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mTotalVtDataUsage += (usage - oldUsage);
224448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mVtDataUsageMap.put(call.uniqueId, usage);
224548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                break;
2246a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            case EVENT_DATA_ENABLED_CHANGED:
2247a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                ar = (AsyncResult) msg.obj;
2248a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                if (ar.result instanceof Pair) {
2249a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                    Pair<Boolean, Integer> p = (Pair<Boolean, Integer>) ar.result;
2250a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                    onDataEnabledChanged(p.first, p.second);
2251a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                }
2252a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                break;
2253c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            case EVENT_GET_IMS_SERVICE:
2254c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                try {
2255c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    getImsService();
2256c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                } catch (ImsException e) {
2257c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    loge("getImsService: " + e);
2258c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    //Leave mImsManager as null, then CallStateException will be thrown when dialing
2259c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    mImsManager = null;
2260c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    if (mImsServiceRetryCount < NUM_IMS_SERVICE_RETRIES) {
2261c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        loge("getImsService: Retrying getting ImsService...");
2262c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        sendEmptyMessageDelayed(EVENT_GET_IMS_SERVICE,
2263c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                                TIME_BETWEEN_IMS_SERVICE_RETRIES_MS);
2264c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        mImsServiceRetryCount++;
2265c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    } else {
2266c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        // We have been unable to connect for
2267c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        // NUM_IMS_SERVICE_RETRIES*TIME_BETWEEN_IMS_SERVICE_RETRIES_MS ms. We will
2268c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        // probably never be able to connect, so we should just give up.
2269c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                        loge("getImsService: ImsService retrieval timeout... ImsService is " +
2270c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                                "unavailable.");
2271c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    }
2272c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                }
2273c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                break;
2274508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            case EVENT_CHECK_FOR_WIFI_HANDOVER:
2275508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                if (msg.obj instanceof ImsCall) {
2276508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    ImsCall imsCall = (ImsCall) msg.obj;
2277508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    if (!imsCall.isWifiCall()) {
2278508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        // Call did not handover to wifi, notify of handover failure.
2279508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        ImsPhoneConnection conn = findConnection(imsCall);
2280508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        if (conn != null) {
2281508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                            conn.onHandoverToWifiFailed();
2282508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        }
2283508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    }
2284508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                }
2285508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                break;
2286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void log(String msg) {
2291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void loge(String msg) {
2295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.e(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2298707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /**
2299707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * Logs the current state of the ImsPhoneCallTracker.  Useful for debugging issues with
2300707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * call tracking.
2301707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     */
2302707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /* package */
2303707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    void logState() {
2304707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        if (!VERBOSE_STATE_LOGGING) {
2305707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            return;
2306707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        }
2307707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2308707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        StringBuilder sb = new StringBuilder();
2309707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("Current IMS PhoneCall State:\n");
2310707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Foreground: ");
2311707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mForegroundCall);
2312707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2313707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Background: ");
2314707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mBackgroundCall);
2315707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2316707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Ringing: ");
2317707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mRingingCall);
2318707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2319707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Handover: ");
2320707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mHandoverCall);
2321707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2322707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        Rlog.v(LOG_TAG, sb.toString());
2323707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    }
2324707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println("ImsPhoneCallTracker extends:");
2328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        super.dump(fd, pw, args);
2329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallEndedRegistrants=" + mVoiceCallEndedRegistrants);
2330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallStartedRegistrants=" + mVoiceCallStartedRegistrants);
2331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mRingingCall=" + mRingingCall);
2332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mForegroundCall=" + mForegroundCall);
2333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mBackgroundCall=" + mBackgroundCall);
2334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mHandoverCall=" + mHandoverCall);
2335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPendingMO=" + mPendingMO);
2336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //pw.println(" mHangupPendingMO=" + mHangupPendingMO);
2337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPhone=" + mPhone);
2338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mDesiredMute=" + mDesiredMute);
2339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mState=" + mState);
2340dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        for (int i = 0; i < mImsFeatureEnabled.length; i++) {
2341dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println(" " + mImsFeatureStrings[i] + ": "
2342dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                    + ((mImsFeatureEnabled[i]) ? "enabled" : "disabled"));
2343dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
234448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        pw.println(" mTotalVtDataUsage=" + mTotalVtDataUsage);
234548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        for (Map.Entry<Integer, Long> entry : mVtDataUsageMap.entrySet()) {
234648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            pw.println("    id=" + entry.getKey() + " ,usage=" + entry.getValue());
234748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
234848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
2349dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.flush();
2350dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.println("++++++++++++++++++++++++++++++++");
2351dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2352dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        try {
2353dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            if (mImsManager != null) {
2354dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                mImsManager.dump(fd, pw, args);
2355dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2356dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        } catch (Exception e) {
2357dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            e.printStackTrace();
2358dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2359dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2360dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        if (mConnections != null && mConnections.size() > 0) {
2361dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println("mConnections:");
2362dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            for (int i = 0; i < mConnections.size(); i++) {
2363dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                pw.println("  [" + i + "]: " + mConnections.get(i));
2364dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2365dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void handlePollCalls(AsyncResult ar) {
2370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
237104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
237204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    /* package */
237304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    ImsEcbm getEcbmInterface() throws ImsException {
237404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (mImsManager == null) {
2375cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
237604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
237704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
237804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        ImsEcbm ecbm = mImsManager.getEcbmInterface(mServiceId);
237904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return ecbm;
238004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
238104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
238293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /* package */
238393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
238493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        if (mImsManager == null) {
2385cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
238693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
238793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
2388b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        try {
2389b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            return mImsManager.getMultiEndpointInterface(mServiceId);
2390b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        } catch (ImsException e) {
2391b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            if (e.getCode() == ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED) {
2392b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                return null;
2393b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            } else {
2394b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                throw e;
2395b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            }
2396b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn
2397b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        }
239893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
239993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
240004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    public boolean isInEmergencyCall() {
240104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return mIsInEmergencyCall;
240204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
2403cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2404cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    public boolean isVolteEnabled() {
240562a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE];
240662a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    }
240762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com
240862a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    public boolean isVowifiEnabled() {
240962a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI];
2410cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2411cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2412288268d5528e0df03f348e303954813cb188c55bRekha Kumar    public boolean isVideoCallEnabled() {
241362a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE]
241462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI]);
2415cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2416288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2417b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    @Override
2418b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    public PhoneConstants.State getState() {
2419b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com        return mState;
2420b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    }
2421288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2422288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private void setVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall)
2423288268d5528e0df03f348e303954813cb188c55bRekha Kumar            throws RemoteException {
2424288268d5528e0df03f348e303954813cb188c55bRekha Kumar        IImsVideoCallProvider imsVideoCallProvider =
2425288268d5528e0df03f348e303954813cb188c55bRekha Kumar                imsCall.getCallSession().getVideoCallProvider();
2426288268d5528e0df03f348e303954813cb188c55bRekha Kumar        if (imsVideoCallProvider != null) {
2427288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsVideoCallProviderWrapper imsVideoCallProviderWrapper =
2428288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    new ImsVideoCallProviderWrapper(imsVideoCallProvider);
2429288268d5528e0df03f348e303954813cb188c55bRekha Kumar            conn.setVideoProvider(imsVideoCallProviderWrapper);
243048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            imsVideoCallProviderWrapper.registerForDataUsageUpdate
243148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    (this, EVENT_VT_DATA_USAGE_UPDATE, imsCall);
2432db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            imsVideoCallProviderWrapper.addImsVideoProviderCallback(conn);
2433288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
2434288268d5528e0df03f348e303954813cb188c55bRekha Kumar    }
2435164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati
2436164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    public boolean isUtEnabled() {
2437164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE]
2438164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI]);
2439164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    }
2440d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2441d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
2442d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * Given a call subject, removes any characters considered by the current carrier to be
24435c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * invalid, as well as escaping (using \) any characters which the carrier requires to be
24445c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * escaped.
2445d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
2446d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * @param callSubject The call subject.
24475c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The call subject with invalid characters removed and escaping applied as required.
2448d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
24495c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String cleanseInstantLetteringMessage(String callSubject) {
24504677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        if (TextUtils.isEmpty(callSubject)) {
24514677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn            return callSubject;
24524677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        }
24534677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn
24545c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Get the carrier config for the current sub.
24555c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        CarrierConfigManager configMgr = (CarrierConfigManager)
24565c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
24575c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if we can't find the carrier config service.
24585c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (configMgr == null) {
2459d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn            return callSubject;
2460d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
2461d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
24625c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        PersistableBundle carrierConfig = configMgr.getConfigForSubId(mPhone.getSubId());
24635c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if no carrier config found.
24645c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (carrierConfig == null) {
24655c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            return callSubject;
24665c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
24675c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
24685c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to replace invalid characters
24695c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String invalidCharacters = carrierConfig.getString(
24705c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING);
24715c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(invalidCharacters)) {
24725c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = callSubject.replaceAll(invalidCharacters, "");
24735c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
24745c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
24755c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to escape characters which need to be escaped.
24765c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String escapedCharacters = carrierConfig.getString(
24775c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING);
24785c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(escapedCharacters)) {
24795c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = escapeChars(escapedCharacters, callSubject);
24805c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
24815c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return callSubject;
2482d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
2483d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2484d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
24855c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * Given a source string, return a string where a set of characters are escaped using the
24865c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * backslash character.
2487d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
24885c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param toEscape The characters to escape with a backslash.
24895c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param source The source string.
24905c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The source string with characters escaped.
2491d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
24925c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String escapeChars(String toEscape, String source) {
24935c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        StringBuilder escaped = new StringBuilder();
24945c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        for (char c : source.toCharArray()) {
24955c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            if (toEscape.contains(Character.toString(c))) {
24965c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                escaped.append("\\");
24975c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            }
24985c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            escaped.append(c);
2499d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
25005c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
25015c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return escaped.toString();
2502d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
250393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
250493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /**
250593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull of an external call.
250693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
250793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull by making a dial request with the {@link ImsCallProfile#EXTRA_IS_CALL_PULL}
250893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * extra specified.  We call {@link ImsPhone#notifyUnknownConnection(Connection)} which notifies
250993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Telecom of the new dialed connection.  The
251093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@code PstnIncomingCallNotifier#maybeSwapWithUnknownConnection} logic ensures that the new
251193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsPhoneConnection} resulting from the dial gets swapped with the
251293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsExternalConnection}, which effectively makes the external call become a regular
251393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * call.  Magic!
251493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
251593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param number The phone number of the call to be pulled.
251693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param videoState The desired video state of the pulled call.
25173de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn     * @param dialogId The {@link ImsExternalConnection#getCallId()} dialog id associated with the
25183de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn     *                 call which is being pulled.
251993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     */
252093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    @Override
25213de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn    public void pullExternalCall(String number, int videoState, int dialogId) {
252293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        Bundle extras = new Bundle();
252393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        extras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL, true);
25243de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn        extras.putInt(ImsExternalCallTracker.EXTRA_IMS_EXTERNAL_CALL_ID, dialogId);
252593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        try {
252693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            Connection connection = dial(number, videoState, extras);
252793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            mPhone.notifyUnknownConnection(connection);
252893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        } catch (CallStateException e) {
252993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            loge("pullExternalCall failed - " + e);
253093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
253193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
2532cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
2533cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    private ImsException getImsManagerIsNullException() {
2534cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        return new ImsException("no ims manager", ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
2535cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    }
253637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
253737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
253837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Determines if answering an incoming call will cause the active call to be disconnected.
253937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * <p>
254037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * This will be the case if
254137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@link CarrierConfigManager#KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL} is
254237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@code true} for the carrier, the active call is a video call over WIFI, and the incoming
254337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * call is an audio call.
254437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *
254537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param activeCall The active call.
254637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param incomingCall The incoming call.
254737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @return {@code true} if answering the incoming call will cause the active call to be
254837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *      disconnected, {@code false} otherwise.
254937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
255037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean shouldDisconnectActiveCallOnAnswer(ImsCall activeCall,
255137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall incomingCall) {
255237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
255337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        if (!mDropVideoCallWhenAnsweringAudioCall) {
255437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return false;
255537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        }
255637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
255737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallVideo = activeCall.isVideoCall() ||
255837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                (mTreatDowngradedVideoCallsAsVideoCalls && activeCall.wasVideoCall());
255937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallOnWifi = activeCall.isWifiCall();
256079de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        boolean isVoWifiEnabled = mImsManager.isWfcEnabledByPlatform(mPhone.getContext()) &&
256179de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                mImsManager.isWfcEnabledByUser(mPhone.getContext());
256237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isIncomingCallAudio = !incomingCall.isVideoCall();
256379de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        log("shouldDisconnectActiveCallOnAnswer : isActiveCallVideo=" + isActiveCallVideo +
256479de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                " isActiveCallOnWifi=" + isActiveCallOnWifi + " isIncomingCallAudio=" +
256579de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                isIncomingCallAudio + " isVowifiEnabled=" + isVoWifiEnabled);
256679de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn
256779de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        return isActiveCallVideo && isActiveCallOnWifi && isIncomingCallAudio && !isVoWifiEnabled;
256837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    }
256948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
257048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    /** Get aggregated video call data usage since boot.
257148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     *
257248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     * @return data usage in bytes
257348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     */
257448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    public long getVtDataUsage() {
257548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
257648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // If there is an ongoing VT call, request the latest VT usage from the modem. The latest
257748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // usage will return asynchronously so it won't be counted in this round, but it will be
257848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // eventually counted when next getVtDataUsage is called.
257948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        if (mState != PhoneConstants.State.IDLE) {
258048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            for (ImsPhoneConnection conn : mConnections) {
2581f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                android.telecom.Connection.VideoProvider videoProvider = conn.getVideoProvider();
2582f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                if (videoProvider != null) {
2583f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                    videoProvider.onRequestConnectionDataUsage();
2584f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                }
258548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            }
258648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
258748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
258848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        return mTotalVtDataUsage;
258948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    }
259091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
259191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public void registerPhoneStateListener(PhoneStateListener listener) {
259291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        mPhoneStateListeners.add(listener);
259391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
259491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
259591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public void unregisterPhoneStateListener(PhoneStateListener listener) {
259691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        mPhoneStateListeners.remove(listener);
259791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
259891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
259991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
260091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Notifies local telephony listeners of changes to the IMS phone state.
260191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
260291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param oldState The old state.
260391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param newState The new state.
260491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
260591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private void notifyPhoneStateChanged(PhoneConstants.State oldState,
260691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            PhoneConstants.State newState) {
260791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
260891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        for (PhoneStateListener listener : mPhoneStateListeners) {
260991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            listener.onPhoneStateChanged(oldState, newState);
261091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
261191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
261291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
2613a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    /** Modify video call to a new video state.
2614a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     *
2615a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param imsCall IMS call to be modified
2616a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param newVideoState New video state. (Refer to VideoProfile)
2617a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     */
2618a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private void modifyVideoCall(ImsCall imsCall, int newVideoState) {
2619a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsPhoneConnection conn = findConnection(imsCall);
2620a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        if (conn != null) {
2621a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            int oldVideoState = conn.getVideoState();
2622a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            if (conn.getVideoProvider() != null) {
2623a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                conn.getVideoProvider().onSendSessionModifyRequest(
2624a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                        new VideoProfile(oldVideoState), new VideoProfile(newVideoState));
2625a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            }
2626a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        }
2627a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    }
2628a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
2629a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    /**
2630a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * Handler of data enabled changed event
2631a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param enabled True if data is enabled, otherwise disabled.
26322f9f55d539817926542b7db63a41d76badded853Tyler Gunn     * @param reason Reason for data enabled/disabled (see {@code REASON_*} in
26332f9f55d539817926542b7db63a41d76badded853Tyler Gunn     *      {@link DataEnabledSettings}.
2634a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     */
2635a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private void onDataEnabledChanged(boolean enabled, int reason) {
2636a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
2637a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        log("onDataEnabledChanged: enabled=" + enabled + ", reason=" + reason);
2638a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId()).setDataEnabled(enabled);
2639a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
26402f9f55d539817926542b7db63a41d76badded853Tyler Gunn        if (!enabled) {
26412f9f55d539817926542b7db63a41d76badded853Tyler Gunn            int reasonCode;
26422f9f55d539817926542b7db63a41d76badded853Tyler Gunn            if (reason == DataEnabledSettings.REASON_POLICY_DATA_ENABLED) {
26432f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_LIMIT_REACHED;
26442f9f55d539817926542b7db63a41d76badded853Tyler Gunn            } else if (reason == DataEnabledSettings.REASON_USER_DATA_ENABLED) {
26452f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
26462f9f55d539817926542b7db63a41d76badded853Tyler Gunn            } else {
26472f9f55d539817926542b7db63a41d76badded853Tyler Gunn                // Unexpected code, default to data disabled.
26482f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
26492f9f55d539817926542b7db63a41d76badded853Tyler Gunn            }
26502f9f55d539817926542b7db63a41d76badded853Tyler Gunn
26512f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // If data is disabled while there are ongoing VT calls which are not taking place over
26522f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // wifi, then they should be disconnected to prevent the user from incurring further
26532f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // data charges.
2654a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            for (ImsPhoneConnection conn : mConnections) {
2655a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                ImsCall imsCall = conn.getImsCall();
2656a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                if (imsCall != null && imsCall.isVideoCall() && !imsCall.isWifiCall()) {
26572e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                    if (conn.hasCapabilities(
26582e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
26592e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)) {
26602e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
26612e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // If the carrier supports downgrading to voice, then we can simply issue a
26622e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // downgrade to voice instead of terminating the call.
26632e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        if (reasonCode == ImsReasonInfo.CODE_DATA_DISABLED) {
26642e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            conn.onConnectionEvent(TelephonyManager.EVENT_DOWNGRADE_DATA_DISABLED,
26652e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    null);
26662e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        } else if (reasonCode == ImsReasonInfo.CODE_DATA_LIMIT_REACHED) {
26672e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            conn.onConnectionEvent(
26682e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    TelephonyManager.EVENT_DOWNGRADE_DATA_LIMIT_REACHED, null);
26692e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        }
26702e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
26712e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                    } else {
26722e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // If the carrier does not support downgrading to voice, the only choice we
26732e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // have is to terminate the call.
26742e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        try {
26752e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
26762e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        } catch (ImsException ie) {
26772e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            loge("Couldn't terminate call " + imsCall);
26782e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        }
26792f9f55d539817926542b7db63a41d76badded853Tyler Gunn                    }
2680a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                }
2681a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            }
2682a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        }
268391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
2684a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        // This will call into updateVideoCallFeatureValue and eventually all clients will be
2685a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        // asynchronously notified that the availability of VT over LTE has changed.
2686a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
2687a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    }
2688508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
2689508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    /**
2690508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * @return {@code true} if the device is connected to a WIFI network, {@code false} otherwise.
2691508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     */
2692508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private boolean isWifiConnected() {
2693508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        ConnectivityManager cm = (ConnectivityManager) mPhone.getContext()
2694508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                .getSystemService(Context.CONNECTIVITY_SERVICE);
2695508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        if (cm != null) {
2696508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            NetworkInfo ni = cm.getActiveNetworkInfo();
2697508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (ni != null && ni.isConnected()) {
2698508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                return ni.getType() == ConnectivityManager.TYPE_WIFI;
2699508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
2700508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        }
2701508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        return false;
2702508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    }
27032e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
27042e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    /**
27052e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * @return {@code true} if downgrading of a video call to audio is supported.
27062e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     */
27072e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    public boolean isCarrierDowngradeOfVtCallSupported() {
27082e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        return mSupportDowngradeVtToAudio;
27092e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    }
2710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
2711