ImsPhoneCallTracker.java revision 50a6eae6fb10462b1edb12cc30cb9701ca18a212
1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Copyright (C) 2013 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony.imsphone;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.app.PendingIntent;
20a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.BroadcastReceiver;
21a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
22a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Intent;
23a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.IntentFilter;
24a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.SharedPreferences;
25508daf6f8286407cf34e32750148fad120009c13Tyler Gunnimport android.net.ConnectivityManager;
26508daf6f8286407cf34e32750148fad120009c13Tyler Gunnimport android.net.NetworkInfo;
27d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajanimport android.net.Uri;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
29df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordonimport android.os.Bundle;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
32d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.os.PersistableBundle;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.RegistrantList;
35ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport android.os.RemoteException;
36a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemProperties;
37a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.preference.PreferenceManager;
38f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport android.provider.Settings;
39fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunnimport android.telecom.ConferenceParticipant;
40dc2b5d1c32cad5269106d00fd106bd64097238f4Tyler Gunnimport android.telecom.VideoProfile;
41f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport android.telephony.CarrierConfigManager;
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
43222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran Cimport android.telephony.PreciseDisconnectCause;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
4604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport android.telephony.ServiceState;
478560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunnimport android.telephony.SubscriptionManager;
48f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport android.telephony.TelephonyManager;
494a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebingerimport android.telephony.ims.ImsServiceProxy;
504a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebingerimport android.telephony.ims.feature.ImsFeature;
51f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport android.text.TextUtils;
52222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran Cimport android.util.SparseIntArray;
5391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunnimport android.util.ArrayMap;
549cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunnimport android.util.Log;
5591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunnimport android.util.Pair;
56a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCall;
5804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCallProfile;
59cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.comimport com.android.ims.ImsConfig;
609746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiakimport com.android.ims.ImsConfigListener;
6104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsConnectionStateListener;
6204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsEcbm;
6304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsException;
6404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsManager;
6593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnimport com.android.ims.ImsMultiEndpoint;
6604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsReasonInfo;
6704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsServiceClass;
6808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.ims.ImsSuppServiceNotification;
6904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsUtInterface;
70ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.IImsVideoCallProvider;
71ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.ImsVideoCallProviderWrapper;
724558536154e496ea917b343e496ed64c94250873Tyler Gunnimport com.android.internal.annotations.VisibleForTesting;
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Call;
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallTracker;
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandException;
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandsInterface;
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.TelephonyProperties;
82f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport com.android.internal.telephony.TelephonyProto.ImsConnectionState;
83f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport com.android.internal.telephony.TelephonyProto.TelephonyCallSession;
84f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport com.android.internal.telephony.TelephonyProto.TelephonyCallSession.Event.ImsCommand;
852f9f55d539817926542b7db63a41d76badded853Tyler Gunnimport com.android.internal.telephony.dataconnection.DataEnabledSettings;
8608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.internal.telephony.gsm.SuppServiceNotification;
87f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport com.android.internal.telephony.metrics.TelephonyMetrics;
88f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu
89f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.io.FileDescriptor;
90f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.io.PrintWriter;
91f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.util.ArrayList;
92f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.util.HashMap;
93f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.util.List;
94f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.util.Map;
95f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yuimport java.util.regex.Pattern;
96a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
97a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
98a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
10093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnpublic class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ImsPhoneCallTracker";
1029cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn    static final String VERBOSE_STATE_TAG = "IPCTState";
103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
10491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public interface PhoneStateListener {
10591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        void onPhoneStateChanged(PhoneConstants.State oldState, PhoneConstants.State newState);
10691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
10791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
110707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // When true, dumps the state of ImsPhoneCallTracker after changes to foreground and background
1119cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn    // calls.  This is helpful for debugging.  It is also possible to enable this at runtime by
1129cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn    // setting the IPCTState log tag to VERBOSE.
1139cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn    private static final boolean FORCE_VERBOSE_STATE_LOGGING = false; /* stopship if true */
1149cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn    private static final boolean VERBOSE_STATE_LOGGING = FORCE_VERBOSE_STATE_LOGGING ||
1159cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn            Rlog.isLoggable(VERBOSE_STATE_TAG, Log.VERBOSE);
116df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn
117915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold    //Indices map to ImsConfig.FeatureConstants
118164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private boolean[] mImsFeatureEnabled = {false, false, false, false, false, false};
119164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private final String[] mImsFeatureStrings = {"VoLTE", "ViLTE", "VoWiFi", "ViWiFi",
120164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            "UTLTE", "UTWiFi"};
121cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
122f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu    private TelephonyMetrics mMetrics;
1235054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onReceive(Context context, Intent intent) {
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (intent.getAction().equals(ImsManager.ACTION_IMS_INCOMING_CALL)) {
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (DBG) log("onReceive : incoming call intent");
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mImsManager == null) return;
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mServiceId < 0) return;
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Network initiated USSD will be treated by mImsUssdListener
136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    boolean isUssd = intent.getBooleanExtra(ImsManager.EXTRA_USSD, false);
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (isUssd) {
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (DBG) log("onReceive : USSD");
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mUssdSession = mImsManager.takeCall(mServiceId, intent, mImsUssdListener);
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mUssdSession != null) {
1412999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                            mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        return;
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
14608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    boolean isUnknown = intent.getBooleanExtra(ImsManager.EXTRA_IS_UNKNOWN_CALL,
14708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            false);
14808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (DBG) {
14908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        log("onReceive : isUnknown = " + isUnknown +
15008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " fg = " + mForegroundCall.getState() +
15108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " bg = " + mBackgroundCall.getState());
15208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
15308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
15408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Normal MT/Unknown call
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);
1566bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone, imsCall,
15708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            ImsPhoneCallTracker.this,
15808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            (isUnknown? mForegroundCall: mRingingCall), isUnknown);
15937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
16037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    // If there is an active call.
16137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    if (mForegroundCall.hasConnections()) {
16237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        ImsCall activeCall = mForegroundCall.getFirstConnection().getImsCall();
16337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        boolean answeringWillDisconnect =
16437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                                shouldDisconnectActiveCallOnAnswer(activeCall, imsCall);
16537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        conn.setActiveCallDisconnectedOnAnswer(answeringWillDisconnect);
16637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    }
1678582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                    conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    addConnection(conn);
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
170288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    setVideoCallProvider(conn, imsCall);
171ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
172f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    TelephonyMetrics.getInstance().writeOnImsCallReceive(mPhone.getPhoneId(),
173f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            imsCall.getSession());
1745054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
17508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (isUnknown) {
17608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyUnknownConnection(conn);
17708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    } else {
17808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) ||
17908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE)) {
18008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            conn.update(imsCall, ImsPhoneCall.State.WAITING);
18108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        }
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
18308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyNewRingingConnection(conn);
18408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyIncomingRing();
18508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    updatePhoneState();
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyPreciseCallStateChanged();
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (ImsException e) {
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    loge("onReceive : exception " + e);
191ea8cb63201520592011a92849ad3661d22776c87Andrew Lee                } catch (RemoteException e) {
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1938560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            } else if (intent.getAction().equals(
1948560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
1958560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
1968560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1978560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                if (subId == mPhone.getSubId()) {
19837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    cacheCarrierConfiguration(subId);
1998560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    log("onReceive : Updating mAllowEmergencyVideoCalls = " +
2008560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                            mAllowEmergencyVideoCalls);
2018560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                }
202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS = 7;
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5;
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_HANGUP_PENDINGMO = 18;
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_RESUME_BACKGROUND = 19;
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DIAL_PENDINGMO = 20;
214e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private static final int EVENT_EXIT_ECBM_BEFORE_PENDINGMO = 21;
21548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private static final int EVENT_VT_DATA_USAGE_UPDATE = 22;
216a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private static final int EVENT_DATA_ENABLED_CHANGED = 23;
217c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private static final int EVENT_GET_IMS_SERVICE = 24;
218508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private static final int EVENT_CHECK_FOR_WIFI_HANDOVER = 25;
2199f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger    private static final int EVENT_CLEAR_DISCONNECTING_CONN = 26;
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int TIMEOUT_HANGUP_PENDINGMO = 500;
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2239f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger    // The number of milliseconds the CallTracker will wait before manually disconnecting the
2249f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger    // connection due to the modem not responding.
2259f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger    private static final int TIMEOUT_CLEAR_DISCONNECTING_CONN = 5000;
2269f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger
2274a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    // Initial condition for ims connection retry.
2284a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    private static final int IMS_RETRY_STARTING_TIMEOUT_MS = 500; // ms
2294a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    // Ceiling bitshift amount for service query timeout, calculated as:
2304a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    // 2^mImsServiceRetryCount * IMS_RETRY_STARTING_TIMEOUT_MS, where
2314a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    // mImsServiceRetryCount ∊ [0, CEILING_SERVICE_RETRY_COUNT].
2324a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    private static final int CEILING_SERVICE_RETRY_COUNT = 6;
233c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger
234508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private static final int HANDOVER_TO_WIFI_TIMEOUT_MS = 60000; // ms
235508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ArrayList<ImsPhoneConnection> mConnections = new ArrayList<ImsPhoneConnection>();
238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallEndedRegistrants = new RegistrantList();
239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallStartedRegistrants = new RegistrantList();
240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
241ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mRingingCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_RINGING);
242ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mForegroundCall = new ImsPhoneCall(this,
24375ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_FOREGROUND);
244ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this,
24575ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_BACKGROUND);
246ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mHandoverCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_HANDOVER);
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
24848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // Hold aggregated video call data usage for each video call since boot.
24948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // The ImsCall's call id is the key of the map.
25048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>();
25148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private volatile long mTotalVtDataUsage = 0;
25248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneConnection mPendingMO;
254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mClirMode = CommandsInterface.CLIR_DEFAULT;
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Object mSyncHold = new Object();
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mUssdSession = null;
258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Message mPendingUssd = null;
259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhone mPhone;
261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDesiredMute = false;    // false = mute off
263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mOnHoldToneStarted = false;
264ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn    private int mOnHoldToneId = -1;
265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2669f5345c094210aa5d6606b7705a85a7bc17e831dAmit Mahajan    private PhoneConstants.State mState = PhoneConstants.State.IDLE;
267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
268c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private int mImsServiceRetryCount;
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsManager mImsManager;
270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mServiceId = -1;
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
27404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean mIsInEmergencyCall = false;
27504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
27604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private int pendingCallClirMode;
277288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private int mPendingCallVideoState;
278c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private Bundle mPendingIntentExtras;
27904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean pendingCallInEcm = false;
280276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private boolean mSwitchingFgAndBgCalls = false;
281276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private ImsCall mCallExpectedToResume = null;
2828560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    private boolean mAllowEmergencyVideoCalls = false;
283782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu    private boolean mIgnoreDataEnabledChangedForVideoCalls = false;
28404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
28537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
28691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Listeners to changes in the phone state.  Intended for use by other interested IMS components
28791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * without the need to register a full blown {@link android.telephony.PhoneStateListener}.
28891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
28991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private List<PhoneStateListener> mPhoneStateListeners = new ArrayList<>();
29091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
29191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
29237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if video calls which have been downgraded to an
29337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * audio call should be treated as if they are still video calls.
29437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
29537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mTreatDowngradedVideoCallsAsVideoCalls = false;
29637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
29737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
29837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if an ongoing video call over wifi should be
29937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * dropped when an audio call is answered.
30037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
30137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mDropVideoCallWhenAnsweringAudioCall = false;
30237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
3038582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    /**
3048582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * Carrier configuration option which determines whether adding a call during a video call
3058582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * should be allowed.
3068582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     */
3078582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    private boolean mAllowAddCallDuringVideoCall = true;
3088582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu
30991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
310508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * Carrier configuration option which determines whether to notify the connection if a handover
311508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * to wifi fails.
312508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     */
313508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private boolean mNotifyVtHandoverToWifiFail = false;
314508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
315508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    /**
3162e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * Carrier configuration option which determines whether the carrier supports downgrading a
3172e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * TX/RX/TX-RX video call directly to an audio-only call.
3182e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     */
3192e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    private boolean mSupportDowngradeVtToAudio = false;
3202e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
3212e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    /**
322222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C     * Stores the mapping of {@code ImsReasonInfo#CODE_*} to {@code PreciseDisconnectCause#*}
323222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C     */
324222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    private static final SparseIntArray PRECISE_CAUSE_MAP = new SparseIntArray();
325222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    static {
326222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT,
327222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_ILLEGAL_ARGUMENT);
328222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE,
329222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_ILLEGAL_STATE);
330222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR,
331222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_INTERNAL_ERROR);
332222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN,
333222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_IMS_SERVICE_DOWN);
334222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NO_PENDING_CALL,
335222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NO_PENDING_CALL);
336222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_POWER_OFF,
337222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_POWER_OFF);
338222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_LOW_BATTERY,
339222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_LOW_BATTERY);
340222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE,
341222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NETWORK_NO_SERVICE);
342222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE,
343222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NETWORK_NO_LTE_COVERAGE);
344222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING,
345222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NETWORK_ROAMING);
346222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED,
347222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NETWORK_IP_CHANGED);
348222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE,
349222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_SERVICE_UNAVAILABLE);
350222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
351222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_NOT_REGISTERED);
352222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_EXCEEDED,
353222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_MAX_CALL_EXCEEDED);
354222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_DECLINE,
355222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_DECLINE);
356222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING,
357222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_VCC_ON_PROGRESSING);
358222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED,
359222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_RESOURCE_RESERVATION_FAILED);
360222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED,
361222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_CS_RETRY_REQUIRED);
362222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED,
363222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_VOLTE_RETRY_REQUIRED);
364222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED,
365222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_CALL_TERMINATED);
366222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
367222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOCAL_HO_NOT_FEASIBLE);
368222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING,
369222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.TIMEOUT_1XX_WAITING);
370222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER,
371222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.TIMEOUT_NO_ANSWER);
372222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE,
373222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.TIMEOUT_NO_ANSWER_CALL_UPDATE);
374222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_FDN_BLOCKED,
375222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.FDN_BLOCKED);
376222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REDIRECTED,
377222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_REDIRECTED);
378222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BAD_REQUEST,
379222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_BAD_REQUEST);
380222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_FORBIDDEN,
381222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_FORBIDDEN);
382222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_FOUND,
383222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_NOT_FOUND);
384222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_SUPPORTED,
385222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_NOT_SUPPORTED);
386222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT,
387222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_REQUEST_TIMEOUT);
388222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_TEMPRARILY_UNAVAILABLE,
389222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_TEMPRARILY_UNAVAILABLE);
390222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BAD_ADDRESS,
391222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_BAD_ADDRESS);
392222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_BUSY,
393222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_BUSY);
394222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_REQUEST_CANCELLED,
395222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_REQUEST_CANCELLED);
396222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE,
397222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_NOT_ACCEPTABLE);
398222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_NOT_REACHABLE,
399222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_NOT_REACHABLE);
400222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_CLIENT_ERROR,
401222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_CLIENT_ERROR);
402222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_INTERNAL_ERROR,
403222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_SERVER_INTERNAL_ERROR);
404222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE,
405222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_SERVICE_UNAVAILABLE);
406222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_TIMEOUT,
407222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_SERVER_TIMEOUT);
408222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_SERVER_ERROR,
409222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_SERVER_ERROR);
410222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_USER_REJECTED,
411222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_USER_REJECTED);
412222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SIP_GLOBAL_ERROR,
413222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SIP_GLOBAL_ERROR);
414222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE,
415222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE);
416222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE,
417222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.EMERGENCY_PERM_FAILURE);
418222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_INIT_FAILED,
419222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MEDIA_INIT_FAILED);
420222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_NO_DATA,
421222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MEDIA_NO_DATA);
422222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_NOT_ACCEPTABLE,
423222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MEDIA_NOT_ACCEPTABLE);
424222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MEDIA_UNSPECIFIED,
425222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MEDIA_UNSPECIFIED);
426222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_TERMINATED,
427222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.USER_TERMINATED);
428222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_NOANSWER,
429222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.USER_NOANSWER);
430222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_IGNORE,
431222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.USER_IGNORE);
432222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_DECLINE,
433222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.USER_DECLINE);
434222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_LOW_BATTERY,
435222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.LOW_BATTERY);
436222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_BLACKLISTED_CALL_ID,
437222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.BLACKLISTED_CALL_ID);
438222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE,
439222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.USER_TERMINATED_BY_REMOTE);
440222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_NOT_SUPPORTED,
441222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.UT_NOT_SUPPORTED);
442222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE,
443222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.UT_SERVICE_UNAVAILABLE);
444222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_OPERATION_NOT_ALLOWED,
445222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.UT_OPERATION_NOT_ALLOWED);
446222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_NETWORK_ERROR,
447222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.UT_NETWORK_ERROR);
448222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_UT_CB_PASSWORD_MISMATCH,
449222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.UT_CB_PASSWORD_MISMATCH);
450222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ECBM_NOT_SUPPORTED,
451222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.ECBM_NOT_SUPPORTED);
452222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED,
453222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MULTIENDPOINT_NOT_SUPPORTED);
454222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE,
455222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE);
456222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ANSWERED_ELSEWHERE,
457222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.ANSWERED_ELSEWHERE);
458222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_PULL_OUT_OF_SYNC,
459222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.CALL_PULL_OUT_OF_SYNC);
460222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_CALL_END_CAUSE_CALL_PULL,
461222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.CALL_PULLED);
462222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_FAILED,
463222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SUPP_SVC_FAILED);
464222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_CANCELLED,
465222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SUPP_SVC_CANCELLED);
466222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_SUPP_SVC_REINVITE_COLLISION,
467222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.SUPP_SVC_REINVITE_COLLISION);
468222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_IWLAN_DPD_FAILURE,
469222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.IWLAN_DPD_FAILURE);
470222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_ESTABLISH_FAILURE,
471222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.EPDG_TUNNEL_ESTABLISH_FAILURE);
472222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_REKEY_FAILURE,
473222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.EPDG_TUNNEL_REKEY_FAILURE);
474222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_EPDG_TUNNEL_LOST_CONNECTION,
475222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.EPDG_TUNNEL_LOST_CONNECTION);
476222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED,
477222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED);
478222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE,
479222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.REMOTE_CALL_DECLINE);
480222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_DATA_LIMIT_REACHED,
481222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.DATA_LIMIT_REACHED);
482222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_DATA_DISABLED,
483222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.DATA_DISABLED);
484222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_WIFI_LOST,
485222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.WIFI_LOST);
486222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_OFF,
487222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_OFF);
488222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NO_VALID_SIM,
489222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.NO_VALID_SIM);
490222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_INTERNAL_ERROR,
491222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_INTERNAL_ERROR);
492222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_RESP_TIMEOUT,
493222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.NETWORK_RESP_TIMEOUT);
494222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_REJECT,
495222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.NETWORK_REJECT);
496222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_ACCESS_FAILURE,
497222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_ACCESS_FAILURE);
498222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_LINK_FAILURE,
499222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_LINK_FAILURE);
500222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_LINK_LOST,
501222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_LINK_LOST);
502222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_UPLINK_FAILURE,
503222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_UPLINK_FAILURE);
504222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_SETUP_FAILURE,
505222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_SETUP_FAILURE);
506222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_RELEASE_NORMAL,
507222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_RELEASE_NORMAL);
508222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_RADIO_RELEASE_ABNORMAL,
509222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.RADIO_RELEASE_ABNORMAL);
510222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_ACCESS_CLASS_BLOCKED,
511222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.ACCESS_CLASS_BLOCKED);
512222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_NETWORK_DETACH,
513222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.NETWORK_DETACH);
514222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_1,
515222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_1);
516222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_2,
517222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_2);
518222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_3,
519222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_3);
520222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_4,
521222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_4);
522222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_5,
523222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_5);
524222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_6,
525222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_6);
526222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_7,
527222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_7);
528222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_8,
529222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_8);
530222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_9,
531222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_9);
532222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_10,
533222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_10);
534222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_11,
535222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_11);
536222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_12,
537222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_12);
538222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_13,
539222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_13);
540222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_14,
541222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_14);
542222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        PRECISE_CAUSE_MAP.append(ImsReasonInfo.CODE_OEM_CAUSE_15,
543222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.OEM_CAUSE_15);
544222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
545222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
546222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    /**
547df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn     * Carrier configuration option which determines whether the carrier wants to inform the user
548df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn     * when a video call is handed over from WIFI to LTE.
549df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn     * See {@link CarrierConfigManager#KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL} for more
550df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn     * information.
551df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn     */
552df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn    private boolean mNotifyHandoverVideoFromWifiToLTE = false;
553df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn
554df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn    /**
55591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Carrier configuration option which defines a mapping from pairs of
55691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * {@link ImsReasonInfo#getCode()} and {@link ImsReasonInfo#getExtraMessage()} values to a new
55791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * {@code ImsReasonInfo#CODE_*} value.
55891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
55991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * See {@link CarrierConfigManager#KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY}.
56091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
56191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private Map<Pair<Integer, String>, Integer> mImsReasonCodeMap = new ArrayMap<>();
56291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
5634a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    private ImsServiceProxy.INotifyStatusChanged mNotifyFeatureRemovedCallback = () -> {
5644a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        try {
5654a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            if (mImsManager.getImsServiceStatus() != ImsFeature.STATE_READY) {
5664a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger                retryGetImsService();
5674a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            }
5684a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        } catch (ImsException e) {
5694a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            // Could not get the ImsService, retry!
5704a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            retryGetImsService();
5714a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        }
5724a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    };
5734a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Events
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
57975ba09a17a669f4906268088a769836aa87d8241fionaxu    public ImsPhoneCallTracker(ImsPhone phone) {
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        this.mPhone = phone;
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
582f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu        mMetrics = TelephonyMetrics.getInstance();
5835054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        IntentFilter intentfilter = new IntentFilter();
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
5868560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().registerReceiver(mReceiver, intentfilter);
58837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        cacheCarrierConfiguration(mPhone.getSubId());
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
590a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        mPhone.getDefaultPhone().registerForDataEnabledChanged(
591a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                this, EVENT_DATA_ENABLED_CHANGED, null);
592a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
593c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mImsServiceRetryCount = 0;
594c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // Send a message to connect to the Ims Service and open a connection through
595c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // getImsService().
596c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        sendEmptyMessage(EVENT_GET_IMS_SERVICE);
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PendingIntent createIncomingCallPendingIntent() {
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
601a89314bcc94c43512299131609feea0c2c8167cfLibin.Tang@motorola.com        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                PendingIntent.FLAG_UPDATE_CURRENT);
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
606c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger    private void getImsService() throws ImsException {
607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("getImsService");
60853dde7e076954c250e55d156cc1df1202c3a8a9eEtan Cohen        mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId());
6094a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        // Adding to set, will be safe adding multiple times.
6104a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        mImsManager.addNotifyStatusChangedCallback(mNotifyFeatureRemovedCallback);
6114a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        if (mImsManager.getImsServiceStatus() != ImsFeature.STATE_READY) {
6124a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            // We can not call "open" until the ims service is ready
6134a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            throw new ImsException("getImsServiceStatus()",
6144a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
6154a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        }
6164a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        mImsServiceRetryCount = 0;
617c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mServiceId = mImsManager.open(ImsServiceClass.MMTEL,
618c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                createIncomingCallPendingIntent(),
619c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                mImsConnectionStateListener);
62004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
621c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        mImsManager.setImsConfigListener(mImsConfigListener);
6229746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
623c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        // Get the ECBM interface and set IMSPhone's listener object for notifications
624c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        getEcbmInterface().setEcbmStateListener(mPhone.getImsEcbmStateListener());
625c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        if (mPhone.isInEcm()) {
626c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            // Call exit ECBM which will invoke onECBMExited
627c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            mPhone.exitEmergencyCallbackMode();
628c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        }
629c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        int mPreferredTtyMode = Settings.Secure.getInt(
630c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            mPhone.getContext().getContentResolver(),
631c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            Settings.Secure.PREFERRED_TTY_MODE,
632c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            Phone.TTY_MODE_OFF);
633d8c6d59607f963be65bb78f92c44194a78b66108Brad Ebinger        mImsManager.setUiTTYMode(mPhone.getContext(), mPreferredTtyMode, null);
634c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger
635c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        ImsMultiEndpoint multiEndpoint = getMultiEndpointInterface();
636c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        if (multiEndpoint != null) {
637c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            multiEndpoint.setExternalCallStateListener(
638c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    mPhone.getExternalCallTracker().getExternalCallStateListener());
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dispose");
644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.dispose();
645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.dispose();
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.dispose();
647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.dispose();
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().unregisterReceiver(mReceiver);
651d2c46a7e08af8f56c0f2112a78969d3d647cfa03Jiazeng Tian        mPhone.getDefaultPhone().unregisterForDataEnabledChanged(this);
652c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger        removeMessages(EVENT_GET_IMS_SERVICE);
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void finalize() {
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("ImsPhoneCallTracker finalized");
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Methods
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Public Methods
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.add(r);
667a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.remove(h);
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.add(r);
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.remove(h);
683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
68575ba09a17a669f4906268088a769836aa87d8241fionaxu    public Connection dial(String dialString, int videoState, Bundle intentExtras) throws
68675ba09a17a669f4906268088a769836aa87d8241fionaxu            CallStateException {
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
6881a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        int oirMode = sp.getInt(Phone.CLIR_KEY, CommandsInterface.CLIR_DEFAULT);
689df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon        return dial(dialString, oirMode, videoState, intentExtras);
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * oirMode is one of the CLIR_ constants
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    synchronized Connection
696df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon    dial(String dialString, int clirMode, int videoState, Bundle intentExtras)
697df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon            throws CallStateException {
698e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
69904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(dialString);
70004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dial clirMode=" + clirMode);
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // note that this triggers call state changed notif
704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
707a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("service not available");
708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!canDial()) {
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot dial in current state");
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
71404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (isPhoneInEcmMode && isEmergencyNumber) {
71504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            handleEcmTimer(ImsPhone.CANCEL_ECM_TIMER);
71604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
71704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
7188560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // If the call is to an emergency number and the carrier does not support video emergency
7198560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // calls, dial as an audio-only call.
720025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        if (isEmergencyNumber && VideoProfile.isVideo(videoState) &&
7218560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                !mAllowEmergencyVideoCalls) {
7228560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            loge("dial: carrier does not support video emergency calls; downgrade to audio-only");
7238560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            videoState = VideoProfile.STATE_AUDIO_ONLY;
7248560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
7258560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean holdBeforeDial = false;
727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
728a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // The new call must be assigned to the foreground call.
729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // That call must be idle, so place anything that's
730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // there on hold
731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we should have failed in !canDial() above before we get here
734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot dial in current state");
735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // foreground call is empty for the newly dialed connection
737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            holdBeforeDial = true;
738288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache the video state for pending MO call.
739288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
740c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            mPendingIntentExtras = intentExtras;
741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
742a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
743a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
744a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
745a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
746a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
747a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mClirMode = clirMode;
748a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
749a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mSyncHold) {
750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (holdBeforeDial) {
751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                fgState = mForegroundCall.getState();
752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                bgState = mBackgroundCall.getState();
753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call failed
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (fgState == ImsPhoneCall.State.ACTIVE) {
756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("cannot dial in current state");
757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call succeeded
760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (bgState == ImsPhoneCall.State.HOLDING) {
761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    holdBeforeDial = false;
762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7656bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mPendingMO = new ImsPhoneConnection(mPhone,
7668bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    checkForTestEmergencyNumber(dialString), this, mForegroundCall,
7678bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyNumber);
76857d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade            mPendingMO.setVideoState(videoState);
769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        addConnection(mPendingMO);
771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
772a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!holdBeforeDial) {
77304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
774c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, clirMode, videoState, intentExtras);
77504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            } else {
77604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                try {
77704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    getEcbmInterface().exitEmergencyCallbackMode();
77804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                } catch (ImsException e) {
77904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    e.printStackTrace();
78004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    throw new CallStateException("service not available");
78104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
78204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
78304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallClirMode = clirMode;
784288268d5528e0df03f348e303954813cb188c55bRekha Kumar                mPendingCallVideoState = videoState;
78504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallInEcm = true;
78604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
787a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
788a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
789a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
790a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
791a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
792a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mPendingMO;
793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7958560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    /**
79637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Caches frequently used carrier configuration items locally.
7978560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     *
7988560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     * @param subId The sub id.
7998560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     */
80037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private void cacheCarrierConfiguration(int subId) {
8018560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
8028560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
8038560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfigManager == null) {
80437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: No carrier config service found.");
80537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
8068560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
8078560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
808025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
8098560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfig == null) {
81037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: Empty carrier config.");
81137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
8128560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
8138560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
81437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mAllowEmergencyVideoCalls =
81537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
81637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mTreatDowngradedVideoCallsAsVideoCalls =
81737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
81837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL);
81937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mDropVideoCallWhenAnsweringAudioCall =
82037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
82137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL);
8228582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu        mAllowAddCallDuringVideoCall =
8238582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                carrierConfig.getBoolean(
8248582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                        CarrierConfigManager.KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL);
825508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        mNotifyVtHandoverToWifiFail = carrierConfig.getBoolean(
826508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                CarrierConfigManager.KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL);
8272e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        mSupportDowngradeVtToAudio = carrierConfig.getBoolean(
8282e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                CarrierConfigManager.KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL);
829df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn        mNotifyHandoverVideoFromWifiToLTE = carrierConfig.getBoolean(
830df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn                CarrierConfigManager.KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL);
831782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu        mIgnoreDataEnabledChangedForVideoCalls = carrierConfig.getBoolean(
832782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
83391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
83491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        String[] mappings = carrierConfig
83591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                .getStringArray(CarrierConfigManager.KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY);
83691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        if (mappings != null && mappings.length > 0) {
83791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            for (String mapping : mappings) {
83891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                String[] values = mapping.split(Pattern.quote("|"));
83991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                if (values.length != 3) {
84091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    continue;
84191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                }
84291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
84391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                try {
8444558536154e496ea917b343e496ed64c94250873Tyler Gunn                    Integer fromCode;
8454558536154e496ea917b343e496ed64c94250873Tyler Gunn                    if (values[0].equals("*")) {
8464558536154e496ea917b343e496ed64c94250873Tyler Gunn                        fromCode = null;
8474558536154e496ea917b343e496ed64c94250873Tyler Gunn                    } else {
8484558536154e496ea917b343e496ed64c94250873Tyler Gunn                        fromCode = Integer.parseInt(values[0]);
8494558536154e496ea917b343e496ed64c94250873Tyler Gunn                    }
85091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    String message = values[1];
85191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    int toCode = Integer.parseInt(values[2]);
85291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
8534558536154e496ea917b343e496ed64c94250873Tyler Gunn                    addReasonCodeRemapping(fromCode, message, toCode);
8544558536154e496ea917b343e496ed64c94250873Tyler Gunn                    log("Loaded ImsReasonInfo mapping : fromCode = " +
8554558536154e496ea917b343e496ed64c94250873Tyler Gunn                            fromCode == null ? "any" : fromCode + " ; message = " +
85691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                            message + " ; toCode = " + toCode);
85791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                } catch (NumberFormatException nfe) {
85891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    loge("Invalid ImsReasonInfo mapping found: " + mapping);
85991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                }
86091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            }
86191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        } else {
86291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            log("No carrier ImsReasonInfo mappings defined.");
86391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
8648560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    }
8658560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
86604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private void handleEcmTimer(int action) {
86704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        mPhone.handleTimerInEmergencyCallbackMode(action);
86804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        switch (action) {
86904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.CANCEL_ECM_TIMER:
87004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
87104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.RESTART_ECM_TIMER:
87204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
87304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            default:
87404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                log("handleEcmTimer, unsupported action " + action);
87504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
87604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
87704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
878c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private void dialInternal(ImsPhoneConnection conn, int clirMode, int videoState,
879c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            Bundle intentExtras) {
880c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
881a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
882a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
883a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
884a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
885a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getAddress()== null || conn.getAddress().length() == 0
886a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
887a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Phone number is invalid
888a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
889a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
890a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
891a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
892a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
893a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Always unmute when initiating a new call
894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setMute(false);
895a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
8966bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
89764e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
89864e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
89964e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        conn.setVideoState(videoState);
900a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
901a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
902a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { conn.getAddress() };
903a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
9046bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                    serviceType, callType);
905a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
906a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
907c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // Translate call subject intent-extra from Telecom-specific extra key to the
908c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // ImsCallProfile key.
909c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            if (intentExtras != null) {
910c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                if (intentExtras.containsKey(android.telecom.TelecomManager.EXTRA_CALL_SUBJECT)) {
911c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                    intentExtras.putString(ImsCallProfile.EXTRA_DISPLAY_TEXT,
9125c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                            cleanseInstantLetteringMessage(intentExtras.getString(
913d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                                    android.telecom.TelecomManager.EXTRA_CALL_SUBJECT))
914d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                    );
915c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                }
916c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
91767f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                if (intentExtras.containsKey(ImsCallProfile.EXTRA_IS_CALL_PULL)) {
91867f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                    profile.mCallExtras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL,
91967f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                            intentExtras.getBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL));
9203de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    int dialogId = intentExtras.getInt(
9213de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            ImsExternalCallTracker.EXTRA_IMS_EXTERNAL_CALL_ID);
92291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    conn.setIsPulledCall(true);
9233de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    conn.setPulledDialogId(dialogId);
92467f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                }
92567f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn
926c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // Pack the OEM-specific call extras.
927c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                profile.mCallExtras.putBundle(ImsCallProfile.EXTRA_OEM_EXTRAS, intentExtras);
928c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
929c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // NOTE: Extras to be sent over the network are packed into the
930c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // intentExtras individually, with uniquely defined keys.
931c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // These key-value pairs are processed by IMS Service before
932c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // being sent to the lower layers/to the network.
933c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            }
934c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mImsManager.makeCall(mServiceId, profile,
936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsCallListener);
937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setImsCall(imsCall);
938ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
939f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallStart(mPhone.getPhoneId(),
940f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    imsCall.getSession());
9415054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
942288268d5528e0df03f348e303954813cb188c55bRekha Kumar            setVideoCallProvider(conn, imsCall);
9438582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu            conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("dialInternal : " + e);
946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
948ea8cb63201520592011a92849ad3661d22776c87Andrew Lee        } catch (RemoteException e) {
949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
9522999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    /**
9532999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * Accepts a call with the specified video state.  The video state is the video state that the
9542999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * user has agreed upon in the InCall UI.
9552999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     *
9562999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @param videoState The video State
9572999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @throws CallStateException
9582999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     */
95975ba09a17a669f4906268088a769836aa87d8241fionaxu    public void acceptCall (int videoState) throws CallStateException {
960a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("acceptCall");
961a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
962a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState().isAlive()
963a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mBackgroundCall.getState().isAlive()) {
964a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot accept call");
965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
966a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
967a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING)
968a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mForegroundCall.getState().isAlive()) {
969a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
97037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
97137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            boolean answeringWillDisconnect = false;
97237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall activeCall = mForegroundCall.getImsCall();
97337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall ringingCall = mRingingCall.getImsCall();
97437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (mForegroundCall.hasConnections() && mRingingCall.hasConnections()) {
97537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                answeringWillDisconnect =
97637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall);
97737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
97837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
979288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache video state for pending MT call.
980288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
98137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
98237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (answeringWillDisconnect) {
98337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                // We need to disconnect the foreground call before answering the background call.
98437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                mForegroundCall.hangup();
98537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                try {
98637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    ringingCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
98737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                } catch (ImsException e) {
98837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    throw new CallStateException("cannot accept call");
98937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                }
99037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            } else {
99137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                switchWaitingOrHoldingAndActive();
99237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mRingingCall.getState().isRinging()) {
994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("acceptCall: incoming...");
995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Always unmute when answering a new call
996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
997a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
999a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) {
10002999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                    imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
1001f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1002f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_ACCEPT);
1003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
1004a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("no valid ims call");
1005a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1006a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
1007a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot accept call");
1008a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1009a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1010a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
1011a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1012a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1013a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
101475ba09a17a669f4906268088a769836aa87d8241fionaxu    public void rejectCall () throws CallStateException {
1015a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("rejectCall");
1016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState().isRinging()) {
1018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            hangup(mRingingCall);
1019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
1021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1024007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1025007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    private void switchAfterConferenceSuccess() {
1026007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (DBG) log("switchAfterConferenceSuccess fg =" + mForegroundCall.getState() +
1027007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                ", bg = " + mBackgroundCall.getState());
1028007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1029007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
1030007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            log("switchAfterConferenceSuccess");
1031007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            mForegroundCall.switchWith(mBackgroundCall);
1032007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        }
1033007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    }
1034007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
103575ba09a17a669f4906268088a769836aa87d8241fionaxu    public void switchWaitingOrHoldingAndActive() throws CallStateException {
1036a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("switchWaitingOrHoldingAndActive");
1037a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1038a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState() == ImsPhoneCall.State.INCOMING) {
1039a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot be in the incoming state");
1040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1042a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
1043a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mForegroundCall.getImsCall();
1044a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == null) {
1045a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("no ims call");
1046a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1047a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1048276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Swap the ImsCalls pointed to by the foreground and background ImsPhoneCalls.
1049276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If hold or resume later fails, we will swap them back.
10503379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            boolean switchingWithWaitingCall = mBackgroundCall.getImsCall() == null &&
10513379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mRingingCall != null &&
10523379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mRingingCall.getState() == ImsPhoneCall.State.WAITING;
10533379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu
1054276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mSwitchingFgAndBgCalls = true;
10553379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            if (switchingWithWaitingCall) {
10563379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                mCallExpectedToResume = mRingingCall.getImsCall();
10573379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            } else {
10583379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                mCallExpectedToResume = mBackgroundCall.getImsCall();
10593379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            }
1060a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.switchWith(mBackgroundCall);
1061a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1062276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Hold the foreground call; once the foreground call is held, the background call will
1063276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // be resumed.
1064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
1065a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                imsCall.hold();
1066f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1067f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                        ImsCommand.IMS_CMD_HOLD);
1068707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
1069707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                // If there is no background call to resume, then don't expect there to be a switch.
1070707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mCallExpectedToResume == null) {
10713379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    log("mCallExpectedToResume is null");
1072707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    mSwitchingFgAndBgCalls = false;
1073707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
1075a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mForegroundCall.switchWith(mBackgroundCall);
1076a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException(e.getMessage());
1077a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1078a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
1079a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            resumeWaitingOrHolding();
1080a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1081a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1082a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
10837dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1084a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    conference() {
1085a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("conference");
1086a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1087a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall fgImsCall = mForegroundCall.getImsCall();
1088a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (fgImsCall == null) {
1089a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no foreground ims call");
1090a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
1091a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1092a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1093a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall bgImsCall = mBackgroundCall.getImsCall();
1094a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (bgImsCall == null) {
1095a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no background ims call");
1096a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
1097a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1099fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // Keep track of the connect time of the earliest call so that it can be set on the
1100fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // {@code ImsConference} when it is created.
11017ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long foregroundConnectTime = mForegroundCall.getEarliestConnectTime();
11027ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long backgroundConnectTime = mBackgroundCall.getEarliestConnectTime();
11037ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long conferenceConnectTime;
11047ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        if (foregroundConnectTime > 0 && backgroundConnectTime > 0) {
11057ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = Math.min(mForegroundCall.getEarliestConnectTime(),
11067ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn                    mBackgroundCall.getEarliestConnectTime());
11077ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - using connect time = " + conferenceConnectTime);
11087ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else if (foregroundConnectTime > 0) {
11097ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - bg call connect time is 0; using fg = " + foregroundConnectTime);
11107ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = foregroundConnectTime;
11117ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else {
11127ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - fg call connect time is 0; using bg = " + backgroundConnectTime);
11137ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = backgroundConnectTime;
11147ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        }
11157ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn
1116fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        ImsPhoneConnection foregroundConnection = mForegroundCall.getFirstConnection();
1117fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        if (foregroundConnection != null) {
1118fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            foregroundConnection.setConferenceConnectTime(conferenceConnectTime);
1119fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        }
1120fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
1121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            fgImsCall.merge(bgImsCall);
1123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference " + e.getMessage());
1125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11287dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    explicitCallTransfer() {
1130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //TODO : implement
1131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11337dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clearDisconnected() {
1135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("clearDisconnected");
1136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        internalClearDisconnected();
1138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
1140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
1141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11437dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
1144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canConference() {
1145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
1146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING
1147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mBackgroundCall.isFull()
1148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mForegroundCall.isFull();
1149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11517dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
1152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canDial() {
1153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean ret;
1154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceState = mPhone.getServiceState().getState();
1155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        String disableCall = SystemProperties.get(
1156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
1157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
1159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mPendingMO == null
1160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mRingingCall.isRinging()
1161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !disableCall.equals("true")
1162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && (!mForegroundCall.getState().isAlive()
1163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    || !mBackgroundCall.getState().isAlive());
1164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ret;
1166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11687dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
1169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canTransfer() {
1170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
1171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING;
1172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Private Instance Methods
1175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
1177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    internalClearDisconnected() {
1178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.clearDisconnected();
1179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.clearDisconnected();
1180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.clearDisconnected();
1181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.clearDisconnected();
1182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
1185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    updatePhoneState() {
1186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PhoneConstants.State oldState = mState;
1187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11889cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn        boolean isPendingMOIdle = mPendingMO == null || !mPendingMO.getState().isAlive();
11899cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn
1190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.isRinging()) {
1191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.RINGING;
11929cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn        } else if (!isPendingMOIdle || !mForegroundCall.isIdle() || !mBackgroundCall.isIdle()) {
11939cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn            // There is a non-idle call, so we're off the hook.
1194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.OFFHOOK;
1195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.IDLE;
1197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState == PhoneConstants.State.IDLE && oldState != mState) {
1200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallEndedRegistrants.notifyRegistrants(
1201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
1202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
1203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallStartedRegistrants.notifyRegistrants (
1204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
1205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
12079cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn        if (DBG) {
12089cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn            log("updatePhoneState pendingMo = " + (mPendingMO == null ? "null"
12099cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn                    : mPendingMO.getState()) + ", fg= " + mForegroundCall.getState() + "("
12109cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn                    + mForegroundCall.getConnections().size() + "), bg= " + mBackgroundCall
12119cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn                    .getState() + "(" + mBackgroundCall.getConnections().size() + ")");
12129cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn            log("updatePhoneState oldState=" + oldState + ", newState=" + mState);
12139cf07ae65ed86b9e79aaa74b66441f0811d9cc15Tyler Gunn        }
1214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState != oldState) {
1216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPhoneStateChanged();
1217f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writePhoneState(mPhone.getPhoneId(), mState);
121891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            notifyPhoneStateChanged(oldState, mState);
1219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
1223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleRadioNotAvailable() {
1224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // handlePollCalls will clear out its
1225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // call list when it gets the CommandException
1226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // error result from this
1227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pollCallsWhenSafe();
1228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
1231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    dumpState() {
1232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        List l;
1233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Phone State:" + mState);
1235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Ringing call: " + mRingingCall.toString());
1237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mRingingCall.getConnections();
1239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
1240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
1241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Foreground call: " + mForegroundCall.toString());
1244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mForegroundCall.getConnections();
1246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
1247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
1248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Background call: " + mBackgroundCall.toString());
1251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mBackgroundCall.getConnections();
1253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
1254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
1255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhone
1260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
126193c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setUiTTYMode(int uiTtyMode, Message onComplete) {
1262cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        if (mImsManager == null) {
1263cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            mPhone.sendErrorResponse(onComplete, getImsManagerIsNullException());
1264cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            return;
1265cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        }
1266cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
1267b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        try {
1268d8c6d59607f963be65bb78f92c44194a78b66108Brad Ebinger            mImsManager.setUiTTYMode(mPhone.getContext(), uiTtyMode, onComplete);
1269b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        } catch (ImsException e) {
1270b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            loge("setTTYMode : " + e);
1271b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            mPhone.sendErrorResponse(onComplete, e);
1272b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        }
1273b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh    }
1274b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
127593c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setMute(boolean mute) {
1276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDesiredMute = mute;
1277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.setMute(mute);
1278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
128093c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public boolean getMute() {
1281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDesiredMute;
1282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1284f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void sendDtmf(char c, Message result) {
1285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendDtmf");
1286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imscall = mForegroundCall.getImsCall();
1288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imscall != null) {
1289d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            imscall.sendDtmf(c, result);
1290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
12937dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1294c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    startDtmf(char c) {
1295c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("startDtmf");
1296c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
1297c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
1298c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
1299c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.startDtmf(c);
1300c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
1301c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("startDtmf : no foreground call");
1302c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
1303c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
1304c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
13057dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
1306c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    stopDtmf() {
1307c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("stopDtmf");
1308c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
1309c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
1310c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
1311c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.stopDtmf();
1312c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
1313c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("stopDtmf : no foreground call");
1314c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
1315c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
1316c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
1317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneConnection
1318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1319f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneConnection conn) throws CallStateException {
1320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup connection");
1321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getOwner() != this) {
1323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("ImsPhoneConnection " + conn
1324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "does not belong to ImsPhoneCallTracker " + this);
1325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        hangup(conn.getCall());
1328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneCall
1331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1332f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneCall call) throws CallStateException {
1333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup call");
1334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call.getConnections().size() == 0) {
1336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("no connections");
1337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imsCall = call.getImsCall();
13409f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        // Get first connection that is associated with imsCall.
13419f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        ImsPhoneConnection imsPhoneConnection = call.getFirstConnection();
1342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean rejectCall = false;
1343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call == mRingingCall) {
1345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
1346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            rejectCall = true;
1347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mForegroundCall) {
1348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (call.isDialingOrAlerting()) {
1349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
1350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup dialing or alerting...");
1351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
1353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
1354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup foreground");
1355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //held call will be resumed by onCallTerminated
1357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mBackgroundCall) {
1359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) {
1360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("(backgnd) hangup waiting or background");
1361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
1363ac82d4da0473991006a752e2337ccb93e85f0946Etan Cohen            throw new CallStateException ("ImsPhoneCall " + call +
1364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    "does not belong to ImsPhoneCallTracker " + this);
1365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        call.onHangupLocal();
13689f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        // Schedule a cleaning event for the ImsPhoneCall. If the modem has not responded in
13699f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        // TIMEOUT_CLEAR_DISCONNECTING_CONN milliseconds, manually disconnect the connection.
13709f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        if (!hasMessages(EVENT_CLEAR_DISCONNECTING_CONN, imsPhoneConnection)) {
13719f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger            sendMessageDelayed(obtainMessage(EVENT_CLEAR_DISCONNECTING_CONN, imsPhoneConnection),
13729f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    TIMEOUT_CLEAR_DISCONNECTING_CONN);
13739f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger        }
1374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall != null) {
13775054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (rejectCall) {
13785054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE);
1379f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1380f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_REJECT);
13815054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                } else {
13825054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
1383f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1384f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_TERMINATE);
13855054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mPendingMO != null && call == mForegroundCall) {
1387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // is holding a foreground call
1388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED);
1389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.onDisconnect();
1390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeConnection(mPendingMO);
1391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
1392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
1393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeMessages(EVENT_DIAL_PENDINGMO);
1394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
1400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
140269e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    void callEndCleanupHandOverCallIfAny() {
140369e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        if (mHandoverCall.mConnections.size() > 0) {
140469e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            if (DBG) log("callEndCleanupHandOverCallIfAny, mHandoverCall.mConnections="
140569e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com                    + mHandoverCall.mConnections);
140669e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mHandoverCall.mConnections.clear();
1407d45e0852699f073cb67ef957eadffd4e8130aff5Shriram Ganesh            mConnections.clear();
140869e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mState = PhoneConstants.State.IDLE;
140969e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        }
141069e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    }
141169e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com
1412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void resumeWaitingOrHolding() throws CallStateException {
1414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("resumeWaitingOrHolding");
1415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getState().isAlive()) {
1418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //resume foreground call after holding background call
1419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //they were switched before holding
1420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mForegroundCall.getImsCall();
14215054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
14225054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
1423f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1424f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_RESUME);
14255054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
1427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //accept waiting call after holding background call
1428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
1429288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (imsCall != null) {
1430288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    imsCall.accept(
1431288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        ImsCallProfile.getCallTypeFromVideoState(mPendingCallVideoState));
1432f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1433f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_ACCEPT);
1434288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
1435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
1436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //Just resume background call.
1437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //To distinguish resuming call with swapping calls
1438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we do not switch calls.here
1439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //ImsPhoneConnection.update will chnage the parent when completed
1440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mBackgroundCall.getImsCall();
14415054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
14425054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
1443f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mMetrics.writeOnImsCommand(mPhone.getPhoneId(), imsCall.getSession(),
1444f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                            ImsCommand.IMS_CMD_RESUME);
14455054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
14527dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void sendUSSD (String ussdString, Message response) {
1453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendUSSD");
1454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mUssdSession != null) {
1457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession.sendUssd(ussdString);
1458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                AsyncResult.forMessage(response, null, null);
1459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                response.sendToTarget();
1460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
1461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1463cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            if (mImsManager == null) {
1464cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                mPhone.sendErrorResponse(response, getImsManagerIsNullException());
1465cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                return;
1466cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            }
1467cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
1468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { ussdString };
1469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
1470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE);
1471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_DIALSTRING,
1472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.DIALSTRING_USSD);
1473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession = mImsManager.makeCall(mServiceId, profile,
1475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsUssdListener);
1476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("sendUSSD : " + e);
1478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.sendErrorResponse(response, e);
1479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1482cc8ea4abbe4f1f755dc5cf1b576d51ceb24fe79dAmit Mahajan    public void cancelUSSD() {
1483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUssdSession == null) return;
1484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
1487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1492288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private synchronized ImsPhoneConnection findConnection(final ImsCall imsCall) {
1493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (ImsPhoneConnection conn : mConnections) {
1494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getImsCall() == imsCall) {
1495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return conn;
1496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
1499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void removeConnection(ImsPhoneConnection conn) {
1502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.remove(conn);
15038bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        // If not emergency call is remaining, notify emergency call registrants
15048bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (mIsInEmergencyCall) {
15058bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            boolean isEmergencyCallInList = false;
15068bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            // if no emergency calls pending, set this to false
15078bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            for (ImsPhoneConnection imsPhoneConnection : mConnections) {
15088bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                if (imsPhoneConnection != null && imsPhoneConnection.isEmergency() == true) {
15098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyCallInList = true;
15108bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    break;
15118bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                }
15128bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            }
15138bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1514a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            if (!isEmergencyCallInList) {
1515a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mIsInEmergencyCall = false;
1516a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mPhone.sendEmergencyCallStateChange(false);
1517a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            }
15188bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void addConnection(ImsPhoneConnection conn) {
1522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.add(conn);
15238bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (conn.isEmergency()) {
15248bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            mIsInEmergencyCall = true;
1525a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            mPhone.sendEmergencyCallStateChange(true);
15268bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
15300db65ec818e58fb5b83a492e082db4536f3b83e0Tyler Gunn        if (DBG) log("processCallStateChange " + imsCall + " state=" + state + " cause=" + cause);
1531d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // This method is called on onCallUpdate() where there is not necessarily a call state
1532d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // change. In these situations, we'll ignore the state related updates and only process
1533d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // the change in media capabilities (as expected).  The default is to not ignore state
1534d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // changes so we do not change existing behavior.
1535d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        processCallStateChange(imsCall, state, cause, false /* do not ignore state update */);
1536d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    }
1537d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati
1538d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause,
1539d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            boolean ignoreState) {
1540d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (DBG) {
1541d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            log("processCallStateChange state=" + state + " cause=" + cause
1542d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                    + " ignoreState=" + ignoreState);
1543d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        }
1544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imsCall == null) return;
1546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
1548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneConnection conn = findConnection(imsCall);
1549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
1551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : what should be done?
1552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
1553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1555d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // processCallStateChange is triggered for onCallUpdated as well.
1556d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // onCallUpdated should not modify the state of the call
1557d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // It should modify only other capabilities of call through updateMediaCapabilities
1558d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // State updates will be triggered through individual callbacks
1559d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // i.e. onCallHeld, onCallResume, etc and conn.update will be responsible for the update
156057d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade        conn.updateMediaCapabilities(imsCall);
1561d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (ignoreState) {
156227e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati            conn.updateAddressDisplay(imsCall);
156321048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            conn.updateExtras(imsCall);
15643652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
15653652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            maybeSetVideoCallProvider(conn, imsCall);
1566d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            return;
1567d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        }
1568d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn
1569d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        changed = conn.update(imsCall, state);
1570d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        if (state == ImsPhoneCall.State.DISCONNECTED) {
1571d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            changed = conn.onDisconnect(cause) || changed;
1572d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            //detach the disconnected connections
1573d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            conn.getCall().detach(conn);
1574d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            removeConnection(conn);
1575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (changed) {
1578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getCall() == mHandoverCall) return;
1579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
1580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
1581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
15843652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    private void maybeSetVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall) {
15853652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        android.telecom.Connection.VideoProvider connVideoProvider = conn.getVideoProvider();
15863652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        if (connVideoProvider != null || imsCall.getCallSession().getVideoCallProvider() == null) {
15873652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            return;
15883652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
15893652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
15903652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        try {
15913652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            setVideoCallProvider(conn, imsCall);
15923652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        } catch (RemoteException e) {
15933652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            loge("maybeSetVideoCallProvider: exception " + e);
15943652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
15953652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    }
15963652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
159791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
15984558536154e496ea917b343e496ed64c94250873Tyler Gunn     * Adds a reason code remapping, for test purposes.
15994558536154e496ea917b343e496ed64c94250873Tyler Gunn     *
16004558536154e496ea917b343e496ed64c94250873Tyler Gunn     * @param fromCode The from code, or {@code null} if all.
16014558536154e496ea917b343e496ed64c94250873Tyler Gunn     * @param message The message to map.
16024558536154e496ea917b343e496ed64c94250873Tyler Gunn     * @param toCode The code to remap to.
16034558536154e496ea917b343e496ed64c94250873Tyler Gunn     */
16044558536154e496ea917b343e496ed64c94250873Tyler Gunn    @VisibleForTesting
16054558536154e496ea917b343e496ed64c94250873Tyler Gunn    public void addReasonCodeRemapping(Integer fromCode, String message, Integer toCode) {
16064558536154e496ea917b343e496ed64c94250873Tyler Gunn        mImsReasonCodeMap.put(new Pair<>(fromCode, message), toCode);
16074558536154e496ea917b343e496ed64c94250873Tyler Gunn    }
16084558536154e496ea917b343e496ed64c94250873Tyler Gunn
16094558536154e496ea917b343e496ed64c94250873Tyler Gunn    /**
161091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Returns the {@link ImsReasonInfo#getCode()}, potentially remapping to a new value based on
161191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * the {@link ImsReasonInfo#getCode()} and {@link ImsReasonInfo#getExtraMessage()}.
161291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
161391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * See {@link #mImsReasonCodeMap}.
161491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
161591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param reasonInfo The {@link ImsReasonInfo}.
161691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @return The remapped code.
161791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
16184558536154e496ea917b343e496ed64c94250873Tyler Gunn    @VisibleForTesting
16194558536154e496ea917b343e496ed64c94250873Tyler Gunn    public int maybeRemapReasonCode(ImsReasonInfo reasonInfo) {
162091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        int code = reasonInfo.getCode();
162191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
162291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        Pair<Integer, String> toCheck = new Pair<>(code, reasonInfo.getExtraMessage());
16234558536154e496ea917b343e496ed64c94250873Tyler Gunn        Pair<Integer, String> wildcardToCheck = new Pair<>(null, reasonInfo.getExtraMessage());
162491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        if (mImsReasonCodeMap.containsKey(toCheck)) {
162591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            int toCode = mImsReasonCodeMap.get(toCheck);
162691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
162791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            log("maybeRemapReasonCode : fromCode = " + reasonInfo.getCode() + " ; message = "
162891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                    + reasonInfo.getExtraMessage() + " ; toCode = " + toCode);
162991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            return toCode;
16304558536154e496ea917b343e496ed64c94250873Tyler Gunn        } else if (mImsReasonCodeMap.containsKey(wildcardToCheck)) {
16314558536154e496ea917b343e496ed64c94250873Tyler Gunn            // Handle the case where a wildcard is specified for the fromCode; in this case we will
16324558536154e496ea917b343e496ed64c94250873Tyler Gunn            // match without caring about the fromCode.
16334558536154e496ea917b343e496ed64c94250873Tyler Gunn            int toCode = mImsReasonCodeMap.get(wildcardToCheck);
16344558536154e496ea917b343e496ed64c94250873Tyler Gunn
16354558536154e496ea917b343e496ed64c94250873Tyler Gunn            log("maybeRemapReasonCode : fromCode(wildcard) = " + reasonInfo.getCode() +
16364558536154e496ea917b343e496ed64c94250873Tyler Gunn                    " ; message = " + reasonInfo.getExtraMessage() + " ; toCode = " + toCode);
16374558536154e496ea917b343e496ed64c94250873Tyler Gunn            return toCode;
163891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
163991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        return code;
164091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
164191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
1642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int getDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
1643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int cause = DisconnectCause.ERROR_UNSPECIFIED;
1644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //int type = reasonInfo.getReasonType();
164691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        int code = maybeRemapReasonCode(reasonInfo);
1647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (code) {
1648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_ADDRESS:
1649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_REACHABLE:
1650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NUMBER_UNREACHABLE;
1651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BUSY:
1653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.BUSY;
1654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED:
1656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.LOCAL;
1657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
16583b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com            case ImsReasonInfo.CODE_LOCAL_CALL_DECLINE:
165991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_REMOTE_CALL_DECLINE:
166091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                // If the call has been declined locally (on this device), or on remotely (on
166191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                // another device using multiendpoint functionality), mark it as rejected.
16623b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                return DisconnectCause.INCOMING_REJECTED;
16633b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com
1664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE:
1665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NORMAL;
1666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
166791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_SIP_FORBIDDEN:
166891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                return DisconnectCause.SERVER_ERROR;
166991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
1670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REDIRECTED:
1671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_REQUEST:
1672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE:
1673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_USER_REJECTED:
1674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_GLOBAL_ERROR:
1675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_ERROR;
1676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE:
1678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_FOUND:
1679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVER_ERROR:
1680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_UNREACHABLE;
1681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING:
1683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED:
1684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN:
1685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE:
1686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED:
1687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE:
1688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE:
1689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING:
1690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.OUT_OF_SERVICE;
1691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT:
1693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING:
1694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER:
1695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE:
1696a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.TIMED_OUT;
1697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_LOW_BATTERY:
1699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_POWER_OFF:
1700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.POWER_OFF;
1701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
170208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            case ImsReasonInfo.CODE_FDN_BLOCKED:
170308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                return DisconnectCause.FDN_BLOCKED;
17041c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn
17051c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_ANSWERED_ELSEWHERE:
17065deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn                return DisconnectCause.ANSWERED_ELSEWHERE;
17075deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn
17081c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_CALL_END_CAUSE_CALL_PULL:
17091c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn                return DisconnectCause.CALL_PULLED;
171091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
171191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            case ImsReasonInfo.CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED:
171291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn                return DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED;
17132f9f55d539817926542b7db63a41d76badded853Tyler Gunn
17142f9f55d539817926542b7db63a41d76badded853Tyler Gunn            case ImsReasonInfo.CODE_DATA_DISABLED:
17152f9f55d539817926542b7db63a41d76badded853Tyler Gunn                return DisconnectCause.DATA_DISABLED;
17162f9f55d539817926542b7db63a41d76badded853Tyler Gunn
17172f9f55d539817926542b7db63a41d76badded853Tyler Gunn            case ImsReasonInfo.CODE_DATA_LIMIT_REACHED:
17182f9f55d539817926542b7db63a41d76badded853Tyler Gunn                return DisconnectCause.DATA_LIMIT_REACHED;
17194558536154e496ea917b343e496ed64c94250873Tyler Gunn
17204558536154e496ea917b343e496ed64c94250873Tyler Gunn            case ImsReasonInfo.CODE_WIFI_LOST:
17214558536154e496ea917b343e496ed64c94250873Tyler Gunn                return DisconnectCause.WIFI_LOST;
1722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            default:
1723a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return cause;
1726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1728222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    private int getPreciseDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
1729222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C        return PRECISE_CAUSE_MAP.get(maybeRemapReasonCode(reasonInfo),
1730222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                PreciseDisconnectCause.ERROR_UNSPECIFIED);
1731222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C    }
1732222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
1733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1734e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * @return true if the phone is in Emergency Callback mode, otherwise false
1735e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1736e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private boolean isPhoneInEcbMode() {
1737e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        return SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false);
1738e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1739e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1740e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1741e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * Before dialing pending MO request, check for the Emergency Callback mode.
1742e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * If device is in Emergency callback mode, then exit the mode before dialing pending MO.
1743e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1744e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private void dialPendingMO() {
1745e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
1746e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isEmergencyNumber = mPendingMO.isEmergency();
1747e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
1748e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_DIAL_PENDINGMO);
1749e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        } else {
1750e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_EXIT_ECBM_BEFORE_PENDINGMO);
1751e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        }
1752e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1753e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1754e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsCallListener = new ImsCall.Listener() {
1758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallProgressing(ImsCall imsCall) {
1760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallProgressing");
1761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ALERTING,
1764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1765f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallProgressing(mPhone.getPhoneId(), imsCall.getCallSession());
1766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStarted");
1771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17723379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            if (mSwitchingFgAndBgCalls) {
17733379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                // If we put a call on hold to answer an incoming call, we should reset the
17743379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                // variables that keep track of the switch here.
17753379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                if (mCallExpectedToResume != null && mCallExpectedToResume == imsCall) {
17763379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    if (DBG) log("onCallStarted: starting a call as a result of a switch.");
17773379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mSwitchingFgAndBgCalls = false;
17783379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mCallExpectedToResume = null;
17793379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                }
17803379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            }
17813379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu
1782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1784a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1785508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
1786508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (mNotifyVtHandoverToWifiFail &&
1787508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    !imsCall.isWifiCall() && imsCall.isVideoCall() && isWifiConnected()) {
1788508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // Schedule check to see if handover succeeded.
1789508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                sendMessageDelayed(obtainMessage(EVENT_CHECK_FOR_WIFI_HANDOVER, imsCall),
1790508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        HANDOVER_TO_WIFI_TIMEOUT_MS);
1791508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
1792508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
1793f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallStarted(mPhone.getPhoneId(), imsCall.getCallSession());
1794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1796288268d5528e0df03f348e303954813cb188c55bRekha Kumar        @Override
1797288268d5528e0df03f348e303954813cb188c55bRekha Kumar        public void onCallUpdated(ImsCall imsCall) {
1798288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (DBG) log("onCallUpdated");
1799288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (imsCall == null) {
1800288268d5528e0df03f348e303954813cb188c55bRekha Kumar                return;
1801288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1802288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsPhoneConnection conn = findConnection(imsCall);
1803288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (conn != null) {
1804288268d5528e0df03f348e303954813cb188c55bRekha Kumar                processCallStateChange(imsCall, conn.getCall().mState,
1805d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                        DisconnectCause.NOT_DISCONNECTED, true /*ignore state update*/);
1806f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                mMetrics.writeImsCallState(mPhone.getPhoneId(),
1807f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                        imsCall.getCallSession(), conn.getCall().mState);
1808288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1809288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
1810288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1811a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /**
1812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * onCallStartFailed will be invoked when:
1813a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 1) Dialing fails
1814a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 2) Ringing call is disconnected by local or remote user
1815a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
1816a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1818a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
1819a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
18203379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            if (mSwitchingFgAndBgCalls) {
18213379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                // If we put a call on hold to answer an incoming call, we should reset the
18223379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                // variables that keep track of the switch here.
18233379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                if (mCallExpectedToResume != null && mCallExpectedToResume == imsCall) {
18243379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    if (DBG) log("onCallStarted: starting a call as a result of a switch.");
18253379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mSwitchingFgAndBgCalls = false;
18263379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                    mCallExpectedToResume = null;
18273379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                }
18283379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu            }
18293379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu
1830a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPendingMO != null) {
1831a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // To initiate dialing circuit-switched call
1832a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
1833a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mBackgroundCall.getState() == ImsPhoneCall.State.IDLE
1834a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mRingingCall.getState() == ImsPhoneCall.State.IDLE) {
1835a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.detach(mPendingMO);
1836a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1837a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.finalize();
1838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1839a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.initiateSilentRedial();
1840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return;
1841990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                } else {
18422770b0f5449670eadab1d68ea8d5fa4788f4704aSantos Cordon                    mPendingMO = null;
1843990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1844222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                    ImsPhoneConnection conn = findConnection(imsCall);
1845222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
1846222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                    if(conn != null) {
1847222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                        conn.setPreciseDisconnectCause(
1848222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                                getPreciseDisconnectCauseFromReasonInfo(reasonInfo));
1849222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                    }
1850222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
1851990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
1852a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1853f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                mMetrics.writeOnImsCallStartFailed(mPhone.getPhoneId(), imsCall.getCallSession(),
1854f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                        reasonInfo);
1855a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1856a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1857a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1858a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1859a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1860a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallTerminated reasonCode=" + reasonInfo.getCode());
1861a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1862bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1863bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            ImsPhoneConnection conn = findConnection(imsCall);
1864bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            if (DBG) log("cause = " + cause + " conn = " + conn);
1865bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com
1866db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            if (conn != null) {
1867db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                android.telecom.Connection.VideoProvider videoProvider = conn.getVideoProvider();
1868db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                if (videoProvider instanceof ImsVideoCallProviderWrapper) {
1869db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    ImsVideoCallProviderWrapper wrapper = (ImsVideoCallProviderWrapper)
1870db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                            videoProvider;
1871db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn
1872db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                    wrapper.removeImsVideoProviderCallback(conn);
1873db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn                }
1874db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            }
1875ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            if (mOnHoldToneId == System.identityHashCode(conn)) {
1876ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                if (conn != null && mOnHoldToneStarted) {
1877ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.stopOnHoldTone(conn);
1878ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                }
1879ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneStarted = false;
1880ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneId = -1;
1881ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            }
18823de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn            if (conn != null) {
18833de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                if (conn.isPulledCall() && (
18843de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_CALL_PULL_OUT_OF_SYNC ||
188548208a24933a644261184f47517a6a8ed7d6fd54Tyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_TEMPRARILY_UNAVAILABLE ||
188648208a24933a644261184f47517a6a8ed7d6fd54Tyler Gunn                        reasonInfo.getCode() == ImsReasonInfo.CODE_SIP_FORBIDDEN) &&
18873de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        mPhone != null && mPhone.getExternalCallTracker() != null) {
18883de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn
18893de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    log("Call pull failed.");
18903de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Call was being pulled, but the call pull has failed -- inform the associated
18913de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // TelephonyConnection that the pull failed, and provide it with the original
18923de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // external connection which was pulled so that it can be swapped back.
18933de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    conn.onCallPullFailed(mPhone.getExternalCallTracker()
18943de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            .getConnectionById(conn.getPulledDialogId()));
18953de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Do not mark as disconnected; the call will just change from being a regular
18963de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // call to being an external call again.
18973de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    cause = DisconnectCause.NOT_DISCONNECTED;
18983de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn
18993de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                } else if (conn.isIncoming() && conn.getConnectTime() == 0
19003de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        && cause != DisconnectCause.ANSWERED_ELSEWHERE) {
19013de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    // Missed
19023de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    if (cause == DisconnectCause.NORMAL) {
19033de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        cause = DisconnectCause.INCOMING_MISSED;
19043de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    } else {
19053de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                        cause = DisconnectCause.INCOMING_REJECTED;
19063de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    }
19073de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                    if (DBG) log("Incoming connection of 0 connect time detected - translated " +
19083de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn                            "cause = " + cause);
190917e77849f88cf20dc5a28aeede66b839fbbdb831Uma Maheswari Ramalingam                }
1910bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            }
1911f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1912f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            if (cause == DisconnectCause.NORMAL && conn != null && conn.getImsCall().isMerged()) {
1913f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                // Call was terminated while it is merged instead of a remote disconnect.
1914f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                cause = DisconnectCause.IMS_MERGED_SUCCESSFULLY;
1915f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            }
1916f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1917f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallTerminated(mPhone.getPhoneId(), imsCall.getCallSession(),
1918f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    reasonInfo);
19199746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
1920222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C            if(conn != null) {
1921222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C                conn.setPreciseDisconnectCause(getPreciseDisconnectCauseFromReasonInfo(reasonInfo));
1922222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C            }
1923222bd9d64068a23f5470561655ca4dbd2359eeceJayachandran C
1924bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
192508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (mForegroundCall.getState() != ImsPhoneCall.State.ACTIVE) {
192608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                if (mRingingCall.getState().isRinging()) {
192708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Drop pending MO. We should address incoming call first
192808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    mPendingMO = null;
192908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else if (mPendingMO != null) {
193008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    sendEmptyMessage(EVENT_DIAL_PENDINGMO);
193108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                }
193208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            }
19331a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu
19341a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            if (mSwitchingFgAndBgCalls) {
19351a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (DBG) {
19361a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    log("onCallTerminated: Call terminated in the midst of Switching " +
19371a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                            "Fg and Bg calls.");
19381a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
19391a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // If we are the in midst of swapping FG and BG calls and the call that was
19401a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // terminated was the one that we expected to resume, we need to swap the FG and
19411a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // BG calls back.
19421a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (imsCall == mCallExpectedToResume) {
19431a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (DBG) {
19441a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        log("onCallTerminated: switching " + mForegroundCall + " with "
19451a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                                + mBackgroundCall);
19461a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
19471a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mForegroundCall.switchWith(mBackgroundCall);
19481a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
19491a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // This call terminated in the midst of a switch after the other call was held, so
19501a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // resume it back to ACTIVE state since the switch failed.
19513379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                log("onCallTerminated: foreground call in state " + mForegroundCall.getState() +
19523379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                        " and ringing call in state " + (mRingingCall == null ? "null" :
19533379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                        mRingingCall.getState().toString()));
19543379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu
19553379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING ||
19563379e399780e6e6531eb84f14d1eca92ae48af2aHall Liu                        mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
19571a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    sendEmptyMessage(EVENT_RESUME_BACKGROUND);
19581a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mSwitchingFgAndBgCalls = false;
19591a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mCallExpectedToResume = null;
19601a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
19611a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            }
1962a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1963a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1964a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHeld(ImsCall imsCall) {
1966707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (DBG) {
1967707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mForegroundCall.getImsCall() == imsCall) {
1968707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (fg) " + imsCall);
1969707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                } else if (mBackgroundCall.getImsCall() == imsCall) {
1970707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (bg) " + imsCall);
1971707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1972707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
1973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1975a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State oldState = mBackgroundCall.getState();
1976a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
1977a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        DisconnectCause.NOT_DISCONNECTED);
1978c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1979c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // Note: If we're performing a switchWaitingOrHoldingAndActive, the call to
1980c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // processCallStateChange above may have caused the mBackgroundCall and
1981c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // mForegroundCall references below to change meaning.  Watch out for this if you
1982c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // are reading through this code.
1983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (oldState == ImsPhoneCall.State.ACTIVE) {
1984276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // Note: This case comes up when we have just held a call in response to a
1985276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // switchWaitingOrHoldingAndActive.  We now need to resume the background call.
1986276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // The EVENT_RESUME_BACKGROUND causes resumeWaitingOrHolding to be called.
1987a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
1988a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
1989f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1990a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    } else {
1991a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //when multiple connections belong to background call,
1992a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //only the first callback reaches here
1993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //otherwise the oldState is already HOLDING
1994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mPendingMO != null) {
1995e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                            dialPendingMO();
1996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
1997c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1998c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // In this case there will be no call resumed, so we can assume that we
1999c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // are done switching fg and bg calls now.
2000c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // This may happen if there is no BG call and we are holding a call so that
2001c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // we can dial another one.
2002c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        mSwitchingFgAndBgCalls = false;
2003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
20041a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                } else if (oldState == ImsPhoneCall.State.IDLE && mSwitchingFgAndBgCalls) {
20051a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // The other call terminated in the midst of a switch before this call was held,
20061a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // so resume the foreground call back to ACTIVE state since the switch failed.
20071a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
20081a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        sendEmptyMessage(EVENT_RESUME_BACKGROUND);
20091a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mSwitchingFgAndBgCalls = false;
20101a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mCallExpectedToResume = null;
20111a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
2012a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2013a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
2014f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallHeld(mPhone.getPhoneId(), imsCall.getCallSession());
2015a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
2019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldFailed reasonCode=" + reasonInfo.getCode());
2020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
2022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State bgState = mBackgroundCall.getState();
2023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
2024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // disconnected while processing hold
2025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
2026e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        dialPendingMO();
2027a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
2028a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else if (bgState == ImsPhoneCall.State.ACTIVE) {
2029a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.switchWith(mBackgroundCall);
2030a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2031a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
2032a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
2033a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
2034a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
2035a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
20365326ba5f8e9488416fd7160680dc6b6319c6b00eAnju Mathapati                mPhone.notifySuppServiceFailed(Phone.SuppService.HOLD);
2037a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
2038f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallHoldFailed(mPhone.getPhoneId(), imsCall.getCallSession(),
2039f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    reasonInfo);
2040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2042a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2043a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumed(ImsCall imsCall) {
2044a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumed");
2045a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2046276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If we are the in midst of swapping FG and BG calls and the call we end up resuming
2047276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // is not the one we expected, we likely had a resume failure and we need to swap the
2048276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // FG and BG calls back.
20490ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn            if (mSwitchingFgAndBgCalls) {
20500ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                if (imsCall != mCallExpectedToResume) {
20510ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // If the call which resumed isn't as expected, we need to swap back to the
20520ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // previous configuration; the swap has failed.
20530ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
20540ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : switching " + mForegroundCall + " with "
20550ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                                + mBackgroundCall);
20560ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
20570ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    mForegroundCall.switchWith(mBackgroundCall);
20580ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                } else {
20590ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // The call which resumed is the one we expected to resume, so we can clear out
20600ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // the mSwitchingFgAndBgCalls flag.
20610ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
20620ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : expected call resumed.");
20630ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
2064707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
2065276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
2066276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
2067276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
2068a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
2069a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
2070f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallResumed(mPhone.getPhoneId(), imsCall.getCallSession());
2071a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
2075afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati            if (mSwitchingFgAndBgCalls) {
2076afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // If we are in the midst of swapping the FG and BG calls and
2077afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // we got a resume fail, we need to swap back the FG and BG calls.
2078afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // Since the FG call was held, will also try to resume the same.
2079afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                if (imsCall == mCallExpectedToResume) {
2080afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (DBG) {
2081afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                        log("onCallResumeFailed : switching " + mForegroundCall + " with "
2082afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                                + mBackgroundCall);
2083afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
2084afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    mForegroundCall.switchWith(mBackgroundCall);
2085afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
2086afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
2087afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
2088707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
2089afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati
2090afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                //Call swap is done, reset the relevant variables
2091276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
2092276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
2093276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
2094276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mPhone.notifySuppServiceFailed(Phone.SuppService.RESUME);
2095f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallResumeFailed(mPhone.getPhoneId(), imsCall.getCallSession(),
2096f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    reasonInfo);
2097a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2099a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeReceived(ImsCall imsCall) {
2101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumeReceived");
2102ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
210333290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn            if (conn != null) {
210433290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                if (mOnHoldToneStarted) {
210533290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                    mPhone.stopOnHoldTone(conn);
210633290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                    mOnHoldToneStarted = false;
210733290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                }
210833290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn
210933290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                conn.onConnectionEvent(android.telecom.Connection.EVENT_CALL_REMOTELY_UNHELD, null);
2110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
211108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
211208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
211308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
211408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
211508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
211608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_RETRIEVED;
211708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
2118f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallResumeReceived(mPhone.getPhoneId(), imsCall.getCallSession());
2119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldReceived(ImsCall imsCall) {
2123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldReceived");
2124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneConnection conn = findConnection(imsCall);
212633290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn            if (conn != null) {
212733290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                if (!mOnHoldToneStarted && ImsPhoneCall.isLocalTone(imsCall) &&
212833290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                        conn.getState() == ImsPhoneCall.State.ACTIVE) {
2129ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.startOnHoldTone(conn);
2130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mOnHoldToneStarted = true;
2131ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mOnHoldToneId = System.identityHashCode(conn);
2132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
213333290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn
213433290100c702ea8a1d4fcede360fc81e81bfccb2Tyler Gunn                conn.onConnectionEvent(android.telecom.Connection.EVENT_CALL_REMOTELY_HELD, null);
2135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
213608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
213708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
213808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
213908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
214008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
214108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_ON_HOLD;
214208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
2143f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallHoldReceived(mPhone.getPhoneId(), imsCall.getCallSession());
214408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        }
214508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
214608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        @Override
214708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
214808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                ImsSuppServiceNotification suppServiceInfo) {
214908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (DBG) log("onCallSuppServiceReceived: suppServiceInfo=" + suppServiceInfo);
215008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
215108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
21528762e33ba987774e43aa9f4e216ebdb084d3a03eTyler Gunn            supp.notificationType = suppServiceInfo.notificationType;
215308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = suppServiceInfo.code;
215408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.index = suppServiceInfo.index;
215508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.number = suppServiceInfo.number;
215608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.history = suppServiceInfo.history;
215708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
215808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
2159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2162007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        public void onCallMerged(final ImsCall call, final ImsCall peerCall, boolean swapCalls) {
2163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallMerged");
2164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2165707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall foregroundImsPhoneCall = findConnection(call).getCall();
2166007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            ImsPhoneConnection peerConnection = findConnection(peerCall);
2167707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall peerImsPhoneCall = peerConnection == null ? null
2168707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    : peerConnection.getCall();
2169007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
2170fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            if (swapCalls) {
2171007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                switchAfterConferenceSuccess();
2172fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            }
2173707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            foregroundImsPhoneCall.merge(peerImsPhoneCall, ImsPhoneCall.State.ACTIVE);
2174007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
2175ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            try {
2176ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                final ImsPhoneConnection conn = findConnection(call);
2177ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: ImsPhoneConnection=" + conn);
2178ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
2179ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                setVideoCallProvider(conn, call);
2180ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
2181ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            } catch (Exception e) {
2182ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                loge("onCallMerged: exception " + e);
2183ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            }
2184288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2185007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // After merge complete, update foreground as Active
2186007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // and background call as Held, if background call exists
2187007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            processCallStateChange(mForegroundCall.getImsCall(), ImsPhoneCall.State.ACTIVE,
2188007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
2189007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (peerConnection != null) {
2190007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                processCallStateChange(mBackgroundCall.getImsCall(), ImsPhoneCall.State.HOLDING,
2191007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
2192007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
2193df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon
2194007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // Check if the merge was requested by an existing conference call. In that
2195007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // case, no further action is required.
2196007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (!call.isMergeRequestedByConf()) {
2197007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: calling onMultipartyStateChanged()");
2198007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                onMultipartyStateChanged(call, true);
2199007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            } else {
2200007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: Merge requested by existing conference.");
2201007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                // Reset the flag.
2202007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                call.resetIsMergeRequestedByConf(false);
2203007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
2204707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            logState();
2205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
22094e47e27d1d2cbd8e533cdd2081c5bc8e51b79ad9Anthony Lee            if (DBG) log("onCallMergeFailed reasonInfo=" + reasonInfo);
221052c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
221152c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // TODO: the call to notifySuppServiceFailed throws up the "merge failed" dialog
221252c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // We should move this into the InCallService so that it is handled appropriately
221352c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // based on the user facing UI.
2214bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
221552c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
221652c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // Start plumbing this even through Telecom so other components can take
221752c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // appropriate action.
221852c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            ImsPhoneConnection conn = findConnection(call);
221952c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            if (conn != null) {
222052c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee                conn.onConferenceMergeFailed();
222152c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            }
2222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2223fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
2224fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        /**
2225f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
2226fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         *
2227fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         * @param call the call object that carries out the IMS call.
2228f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * @param participants the participant(s) and their new state information.
2229fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         */
2230fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        @Override
2231f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
2232f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                List<ConferenceParticipant> participants) {
2233f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn            if (DBG) log("onConferenceParticipantsStateChanged");
2234fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
2235fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            ImsPhoneConnection conn = findConnection(call);
2236fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            if (conn != null) {
2237f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                conn.updateConferenceParticipants(participants);
2238fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            }
2239fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        }
22406d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak
22416d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        @Override
22426d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
22436d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak            mPhone.onTtyModeReceived(mode);
22446d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        }
22450ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
22460ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
22470ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
22480ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
22490ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
22500ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech=" +
22510ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    targetAccessTech + ", reasonInfo=" + reasonInfo);
22520ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
22530b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn
2254508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            boolean isHandoverToWifi = srcAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN &&
2255508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    targetAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
2256508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (isHandoverToWifi) {
2257508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // If we handed over to wifi successfully, don't check for failure in the future.
2258508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
2259508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
2260508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
2261df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn            boolean isHandoverFromWifi =
2262df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn                    srcAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN &&
2263df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn                            targetAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
2264df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn            if (mNotifyHandoverVideoFromWifiToLTE && isHandoverFromWifi && imsCall.isVideoCall()) {
22652d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                log("onCallHandover :: notifying of WIFI to LTE handover.");
22662d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                ImsPhoneConnection conn = findConnection(imsCall);
22672d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                if (conn != null) {
22682d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                    conn.onConnectionEvent(
22692d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                            TelephonyManager.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE, null);
2270df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn                } else {
22712d996aa6061c038ba69dbe3b9430c5164283db22Tyler Gunn                    loge("onCallHandover :: failed to notify of handover; connection is null.");
2272df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn                }
2273df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn            }
2274df0a189fcdf375cb6f0f1f533e20efec575d6c4eTyler Gunn
2275f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallHandoverEvent(mPhone.getPhoneId(),
2276f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    TelephonyCallSession.Event.Type.IMS_CALL_HANDOVER, imsCall.getCallSession(),
22775054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    srcAccessTech, targetAccessTech, reasonInfo);
22780ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
22790ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
22800ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
22810ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
22820ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
22830ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
22840ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandoverFailed :: srcAccessTech=" + srcAccessTech +
22850ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" + reasonInfo);
22860ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
2287f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsCallHandoverEvent(mPhone.getPhoneId(),
2288f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    TelephonyCallSession.Event.Type.IMS_CALL_HANDOVER_FAILED,
2289f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    imsCall.getCallSession(), srcAccessTech, targetAccessTech, reasonInfo);
22900b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn
22910b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            boolean isHandoverToWifi = srcAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN &&
22920b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn                    targetAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
22930b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
22940b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            if (conn != null && isHandoverToWifi) {
22950b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn                log("onCallHandoverFailed - handover to WIFI Failed");
2296508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
2297508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                // If we know we failed to handover, don't check for failure in the future.
2298508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
2299508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
2300508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                if (mNotifyVtHandoverToWifiFail) {
2301508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    // Only notify others if carrier config indicates to do so.
2302508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    conn.onHandoverToWifiFailed();
2303508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                }
23040b93f32c1bed6554f058b9f614a0435f7dbfe942Tyler Gunn            }
23050ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
2306ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
2307ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        /**
2308ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
2309ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * {@link ImsPhoneConnection} of the change.
2310ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *
2311ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param imsCall The IMS call.
2312ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
2313ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *      otherwise.
2314ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         */
2315ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        @Override
2316ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
2317ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (DBG) log("onMultipartyStateChanged to " + (isMultiParty ? "Y" : "N"));
2318ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
2319ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
2320ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (conn != null) {
2321ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                conn.updateMultipartyState(isMultiParty);
2322ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            }
2323ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        }
2324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
2325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
2327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
2328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
2329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsUssdListener = new ImsCall.Listener() {
2330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
2332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStarted");
2333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
2335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
2336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd);
2337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
2338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
2339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
2341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
2345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStartFailed reasonCode=" + reasonInfo.getCode());
2346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
2348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
2352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallTerminated reasonCode=" + reasonInfo.getCode());
2353508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
2354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
2356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession = null;
2357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
2358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    CommandException ex =
2359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            new CommandException(CommandException.Error.GENERIC_FAILURE);
2360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd, null, ex);
2361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
2362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
2363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
2365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imsCall.close();
2366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallUssdMessageReceived(ImsCall call,
2370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                int mode, String ussdMessage) {
2371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallUssdMessageReceived mode=" + mode);
2372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int ussdMode = -1;
2374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch(mode) {
2376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_REQUEST:
2377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_REQUEST;
2378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
2379a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_NOTIFY:
2381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_NOTIFY;
2382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
2383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
2384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.onIncomingUSSD(ussdMode, ussdMessage);
2386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
2388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
2390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS service state change
2391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     *
2392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
2393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsConnectionStateListener mImsConnectionStateListener =
2394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        new ImsConnectionStateListener() {
2395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsConnected() {
2397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsConnected");
2398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
2399bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(true);
2400f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
2401f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    ImsConnectionState.State.CONNECTED, null);
2402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
24050ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
24060ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);
2407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
2408bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(false);
240953f2bb9ba3118ff4c22e20ab3ad46ec97a72ac24Pavel Zhamaitsiak            mPhone.processDisconnectReason(imsReasonInfo);
2410f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
2411f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    ImsConnectionState.State.DISCONNECTED, imsReasonInfo);
2412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
24150ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsProgressing() {
24160ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsProgressing");
241708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
241808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setImsRegistered(false);
2419f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
2420f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    ImsConnectionState.State.PROGRESSING, null);
24210ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
24220ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
24230ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
2424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsResumed() {
2425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsResumed");
2426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
2427f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
2428f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    ImsConnectionState.State.RESUMED, null);
2429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
2432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsSuspended() {
2433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsSuspended");
2434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
2435f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeOnImsConnectionState(mPhone.getPhoneId(),
2436f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    ImsConnectionState.State.SUSPENDED, null);
2437f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu
2438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2439cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2440cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        @Override
2441cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        public void onFeatureCapabilityChanged(int serviceClass,
2442cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                int[] enabledFeatures, int[] disabledFeatures) {
2443cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            if (serviceClass == ImsServiceClass.MMTEL) {
2444288268d5528e0df03f348e303954813cb188c55bRekha Kumar                boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
244504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
2446c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                StringBuilder sb;
2447c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
2448c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb = new StringBuilder(120);
2449c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb.append("onFeatureCapabilityChanged: ");
2450c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
245162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                for (int  i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
245208111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI &&
245308111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i < enabledFeatures.length; i++) {
245462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    if (enabledFeatures[i] == i) {
245504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // If the feature is set to its own integer value it is enabled.
2456c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
2457c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
2458c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":true ");
2459c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
2460c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
246162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = true;
246204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else if (enabledFeatures[i]
246304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                            == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
246404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled.
2465c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
2466c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
2467c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":false ");
2468c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
2469c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
247062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = false;
247104b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else {
247204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // Feature has unknown state; it is not its own value or -1.
247304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        if (DBG) {
2474c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            loge("onFeatureCapabilityChanged(" + i + ", " + mImsFeatureStrings[i]
2475c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                                    + "): unexpectedValue=" + enabledFeatures[i]);
247604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        }
247762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    }
2478cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                }
2479c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
2480c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    log(sb.toString());
2481c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
2482288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {
2483288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
2484288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
248504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee
248604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // TODO: Use the ImsCallSession or ImsCallProfile to tell the initial Wifi state and
248704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // {@link ImsCallSession.Listener#callSessionHandover} to listen for changes to
248804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // wifi capability caused by a handover.
2489164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                if (DBG) log("onFeatureCapabilityChanged: isVolteEnabled=" + isVolteEnabled()
2490164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVideoCallEnabled=" + isVideoCallEnabled()
2491164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVowifiEnabled=" + isVowifiEnabled()
2492164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isUtEnabled=" + isUtEnabled());
249304b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                for (ImsPhoneConnection connection : mConnections) {
249404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    connection.updateWifiState();
249504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                }
2496e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak
2497e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak                mPhone.onFeatureCapabilityChanged();
24985054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
2499f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                mMetrics.writeOnImsCapabilities(
2500f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                        mPhone.getPhoneId(), mImsFeatureEnabled);
2501cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            }
2502cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        }
250303545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade
250403545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        @Override
250503545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        public void onVoiceMessageCountChanged(int count) {
250603545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            if (DBG) log("onVoiceMessageCountChanged :: count=" + count);
250703545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            mPhone.mDefaultPhone.setVoiceMessageCount(count);
250803545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        }
2509d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan
2510d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        @Override
2511d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        public void registrationAssociatedUriChanged(Uri[] uris) {
2512d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan            if (DBG) log("registrationAssociatedUriChanged");
2513d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan            mPhone.setCurrentSubscriberUris(uris);
2514d2b1b9dbc1f6a4fa960c9b5762f82e503cc37c27Amit Mahajan        }
2515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
2516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
25179746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    private ImsConfigListener.Stub mImsConfigListener = new ImsConfigListener.Stub() {
25189746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
25199746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetFeatureResponse(int feature, int network, int value, int status) {}
25209746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
25219746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
25229746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetFeatureResponse(int feature, int network, int value, int status) {
2523f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu            mMetrics.writeImsSetFeatureValue(
2524f2d0fa64860a12423fb8709766d6af90fba5e6cfJack Yu                    mPhone.getPhoneId(), feature, network, value, status);
25259746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        }
25269746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
25279746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
25289746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetVideoQuality(int status, int quality) {}
25299746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
25309746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
25319746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetVideoQuality(int status) {}
25329746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
25339746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    };
25349746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
253593c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public ImsUtInterface getUtInterface() throws ImsException {
2536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
2537cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
2538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2540d8c6d59607f963be65bb78f92c44194a78b66108Brad Ebinger        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration();
2541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ut;
2542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
25444be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    private void transferHandoverConnections(ImsPhoneCall call) {
25454be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.mConnections != null) {
25464be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : call.mConnections) {
25474be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                c.mPreHandoverState = call.mState;
25484be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                log ("Connection state before handover is " + c.getStateBeforeHandover());
25494be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
25504be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
25514be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections == null ) {
25524be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections = call.mConnections;
25534be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        } else { // Multi-call SRVCC
25544be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections.addAll(call.mConnections);
25554be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
25564be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections != null) {
25574be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            if (call.getImsCall() != null) {
25584be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                call.getImsCall().close();
25594be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
25604be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : mHandoverCall.mConnections) {
25614be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                ((ImsPhoneConnection)c).changeParent(mHandoverCall);
256252c193f0c615a9153a702ea2597217202613e413Libin.Tang@motorola.com                ((ImsPhoneConnection)c).releaseWakeLock();
25634be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
25644be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
25654be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.getState().isAlive()) {
25664be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            log ("Call is alive and state is " + call.mState);
25674be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mState = call.mState;
25684be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
25694be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mConnections.clear();
25704be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mState = ImsPhoneCall.State.IDLE;
25714be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    }
25724be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam
2573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
2574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void notifySrvccState(Call.SrvccState state) {
2575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("notifySrvccState state=" + state);
2576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mSrvccState = state;
2578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mSrvccState == Call.SrvccState.COMPLETED) {
25804be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mForegroundCall);
25814be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mBackgroundCall);
25824be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mRingingCall);
2583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //****** Overridden from Handler
2587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void
2590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleMessage (Message msg) {
2591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
2592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("handleMessage what=" + msg.what);
2593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (msg.what) {
2595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_HANGUP_PENDINGMO:
2596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingMO != null) {
2597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.onDisconnect();
2598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
2599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
2600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2601c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
2603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.notifyPreciseCallStateChanged();
2604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_RESUME_BACKGROUND:
2606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
2607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    resumeWaitingOrHolding();
2608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (CallStateException e) {
2609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (Phone.DEBUG_PHONE) {
2610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e);
2611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
2612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_DIAL_PENDINGMO:
2615c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, mClirMode, mPendingCallVideoState, mPendingIntentExtras);
2616c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
261804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
2619e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            case EVENT_EXIT_ECBM_BEFORE_PENDINGMO:
2620e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                if (mPendingMO != null) {
2621e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    //Send ECBM exit request
2622e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    try {
2623e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        getEcbmInterface().exitEmergencyCallbackMode();
2624e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
2625e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallClirMode = mClirMode;
2626e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallInEcm = true;
2627e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    } catch (ImsException e) {
2628e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        e.printStackTrace();
2629e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
2630e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
2631e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    }
2632e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                }
2633e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                break;
2634e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
263504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case EVENT_EXIT_ECM_RESPONSE_CDMA:
263604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // no matter the result, we still do the same here
263704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                if (pendingCallInEcm) {
2638288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    dialInternal(mPendingMO, pendingCallClirMode,
2639c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                            mPendingCallVideoState, mPendingIntentExtras);
2640c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                    mPendingIntentExtras = null;
264104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    pendingCallInEcm = false;
264204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
264304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.unsetOnEcbModeExitResponse(this);
264404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
264548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            case EVENT_VT_DATA_USAGE_UPDATE:
264648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ar = (AsyncResult) msg.obj;
264748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ImsCall call = (ImsCall) ar.userObj;
264848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long usage = (long) ar.result;
264948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                log("VT data usage update. usage = " + usage + ", imsCall = " + call);
265048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
265148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long oldUsage = 0L;
265248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                if (mVtDataUsageMap.containsKey(call.uniqueId)) {
265348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    oldUsage = mVtDataUsageMap.get(call.uniqueId);
265448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                }
265548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mTotalVtDataUsage += (usage - oldUsage);
265648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mVtDataUsageMap.put(call.uniqueId, usage);
265748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                break;
2658a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            case EVENT_DATA_ENABLED_CHANGED:
2659a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                ar = (AsyncResult) msg.obj;
2660a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                if (ar.result instanceof Pair) {
2661a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                    Pair<Boolean, Integer> p = (Pair<Boolean, Integer>) ar.result;
2662a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                    onDataEnabledChanged(p.first, p.second);
2663a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                }
2664a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                break;
2665c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger            case EVENT_GET_IMS_SERVICE:
2666c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                try {
2667c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    getImsService();
2668c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                } catch (ImsException e) {
2669c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                    loge("getImsService: " + e);
26704a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger                    retryGetImsService();
2671c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                }
2672c10b7afb2e174246d7110db5cf2948129af4603dBrad Ebinger                break;
2673508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            case EVENT_CHECK_FOR_WIFI_HANDOVER:
2674508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                if (msg.obj instanceof ImsCall) {
2675508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    ImsCall imsCall = (ImsCall) msg.obj;
2676508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    if (!imsCall.isWifiCall()) {
2677508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        // Call did not handover to wifi, notify of handover failure.
2678508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        ImsPhoneConnection conn = findConnection(imsCall);
2679508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        if (conn != null) {
2680508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                            conn.onHandoverToWifiFailed();
2681508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                        }
2682508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                    }
2683508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                }
2684508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                break;
26859f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger            case EVENT_CLEAR_DISCONNECTING_CONN:
26869f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                if (msg.obj instanceof ImsPhoneConnection) {
26879f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    ImsPhoneConnection imsPhoneConnection = (ImsPhoneConnection) msg.obj;
26889f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    removeMessages(EVENT_CLEAR_DISCONNECTING_CONN, imsPhoneConnection);
26899f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger
26909f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    // We have timed out waiting for the modem while disconnecting this connection.
26919f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    // Manually disconnect to avoid tracking an invalid call.
26929f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    if (imsPhoneConnection != null && imsPhoneConnection.isDisconnecting()) {
26939f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                        Rlog.e(LOG_TAG, "No response from modem. Manually disconnecting: " +
26949f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                                imsPhoneConnection);
26959f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                        imsPhoneConnection.onDisconnect();
26969f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                    }
26979f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                }
26989f13848d600c0782a5bcb3b1d2d7dca5dca35005Brad Ebinger                break;
2699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void log(String msg) {
2704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2707a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void loge(String msg) {
2708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.e(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2711707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /**
2712707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * Logs the current state of the ImsPhoneCallTracker.  Useful for debugging issues with
2713707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * call tracking.
2714707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     */
2715707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /* package */
2716707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    void logState() {
2717707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        if (!VERBOSE_STATE_LOGGING) {
2718707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            return;
2719707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        }
2720707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2721707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        StringBuilder sb = new StringBuilder();
2722707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("Current IMS PhoneCall State:\n");
2723707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Foreground: ");
2724707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mForegroundCall);
2725707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2726707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Background: ");
2727707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mBackgroundCall);
2728707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2729707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Ringing: ");
2730707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mRingingCall);
2731707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2732707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Handover: ");
2733707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mHandoverCall);
2734707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2735707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        Rlog.v(LOG_TAG, sb.toString());
2736707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    }
2737707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2738a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2739a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2740a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println("ImsPhoneCallTracker extends:");
2741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        super.dump(fd, pw, args);
2742a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallEndedRegistrants=" + mVoiceCallEndedRegistrants);
2743a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallStartedRegistrants=" + mVoiceCallStartedRegistrants);
2744a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mRingingCall=" + mRingingCall);
2745a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mForegroundCall=" + mForegroundCall);
2746a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mBackgroundCall=" + mBackgroundCall);
2747a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mHandoverCall=" + mHandoverCall);
2748a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPendingMO=" + mPendingMO);
2749a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //pw.println(" mHangupPendingMO=" + mHangupPendingMO);
2750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPhone=" + mPhone);
2751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mDesiredMute=" + mDesiredMute);
2752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mState=" + mState);
2753dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        for (int i = 0; i < mImsFeatureEnabled.length; i++) {
2754dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println(" " + mImsFeatureStrings[i] + ": "
2755dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                    + ((mImsFeatureEnabled[i]) ? "enabled" : "disabled"));
2756dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
275748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        pw.println(" mTotalVtDataUsage=" + mTotalVtDataUsage);
275848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        for (Map.Entry<Integer, Long> entry : mVtDataUsageMap.entrySet()) {
275948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            pw.println("    id=" + entry.getKey() + " ,usage=" + entry.getValue());
276048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
276148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
2762dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.flush();
2763dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.println("++++++++++++++++++++++++++++++++");
2764dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2765dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        try {
2766dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            if (mImsManager != null) {
2767dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                mImsManager.dump(fd, pw, args);
2768dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2769dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        } catch (Exception e) {
2770dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            e.printStackTrace();
2771dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2772dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2773dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        if (mConnections != null && mConnections.size() > 0) {
2774dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println("mConnections:");
2775dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            for (int i = 0; i < mConnections.size(); i++) {
2776dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                pw.println("  [" + i + "]: " + mConnections.get(i));
2777dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2778dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void handlePollCalls(AsyncResult ar) {
2783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
278404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
278504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    /* package */
278604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    ImsEcbm getEcbmInterface() throws ImsException {
278704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (mImsManager == null) {
2788cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
278904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
279004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
279104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        ImsEcbm ecbm = mImsManager.getEcbmInterface(mServiceId);
279204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return ecbm;
279304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
279404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
279593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /* package */
279693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
279793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        if (mImsManager == null) {
2798cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
279993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
280093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
2801b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        try {
2802b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            return mImsManager.getMultiEndpointInterface(mServiceId);
2803b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        } catch (ImsException e) {
2804b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            if (e.getCode() == ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED) {
2805b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                return null;
2806b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            } else {
2807b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                throw e;
2808b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            }
2809b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn
2810b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        }
281193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
281293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
281304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    public boolean isInEmergencyCall() {
281404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return mIsInEmergencyCall;
281504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
2816cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2817cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    public boolean isVolteEnabled() {
281862a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE];
281962a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    }
282062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com
282162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    public boolean isVowifiEnabled() {
282262a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI];
2823cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2824cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2825288268d5528e0df03f348e303954813cb188c55bRekha Kumar    public boolean isVideoCallEnabled() {
282662a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE]
282762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI]);
2828cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2829288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2830b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    @Override
2831b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    public PhoneConstants.State getState() {
2832b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com        return mState;
2833b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    }
2834288268d5528e0df03f348e303954813cb188c55bRekha Kumar
28354a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    private void retryGetImsService() {
28364a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        //Leave mImsManager as null, then CallStateException will be thrown when dialing
28374a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        mImsManager = null;
28384a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        // Exponential backoff during retry, limited to 32 seconds.
28394a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        loge("getImsService: Retrying getting ImsService...");
28404a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        removeMessages(EVENT_GET_IMS_SERVICE);
28414a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        sendEmptyMessageDelayed(EVENT_GET_IMS_SERVICE,
28424a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger                (1 << mImsServiceRetryCount) * IMS_RETRY_STARTING_TIMEOUT_MS);
28434a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        if (mImsServiceRetryCount <= CEILING_SERVICE_RETRY_COUNT) {
28444a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger            mImsServiceRetryCount++;
28454a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger        }
28464a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger    }
28474a424775eab77d5f9a805ef56eca2e526038f0a1Brad Ebinger
2848288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private void setVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall)
2849288268d5528e0df03f348e303954813cb188c55bRekha Kumar            throws RemoteException {
2850288268d5528e0df03f348e303954813cb188c55bRekha Kumar        IImsVideoCallProvider imsVideoCallProvider =
2851288268d5528e0df03f348e303954813cb188c55bRekha Kumar                imsCall.getCallSession().getVideoCallProvider();
2852288268d5528e0df03f348e303954813cb188c55bRekha Kumar        if (imsVideoCallProvider != null) {
2853288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsVideoCallProviderWrapper imsVideoCallProviderWrapper =
2854288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    new ImsVideoCallProviderWrapper(imsVideoCallProvider);
2855288268d5528e0df03f348e303954813cb188c55bRekha Kumar            conn.setVideoProvider(imsVideoCallProviderWrapper);
285648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            imsVideoCallProviderWrapper.registerForDataUsageUpdate
285748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    (this, EVENT_VT_DATA_USAGE_UPDATE, imsCall);
2858db5b6a50186bc3fc8d42c50f4d23c91b05412ec6Tyler Gunn            imsVideoCallProviderWrapper.addImsVideoProviderCallback(conn);
2859288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
2860288268d5528e0df03f348e303954813cb188c55bRekha Kumar    }
2861164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati
2862164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    public boolean isUtEnabled() {
2863164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE]
2864164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI]);
2865164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    }
2866d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2867d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
2868d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * Given a call subject, removes any characters considered by the current carrier to be
28695c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * invalid, as well as escaping (using \) any characters which the carrier requires to be
28705c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * escaped.
2871d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
2872d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * @param callSubject The call subject.
28735c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The call subject with invalid characters removed and escaping applied as required.
2874d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
28755c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String cleanseInstantLetteringMessage(String callSubject) {
28764677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        if (TextUtils.isEmpty(callSubject)) {
28774677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn            return callSubject;
28784677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        }
28794677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn
28805c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Get the carrier config for the current sub.
28815c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        CarrierConfigManager configMgr = (CarrierConfigManager)
28825c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
28835c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if we can't find the carrier config service.
28845c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (configMgr == null) {
2885d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn            return callSubject;
2886d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
2887d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
28885c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        PersistableBundle carrierConfig = configMgr.getConfigForSubId(mPhone.getSubId());
28895c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if no carrier config found.
28905c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (carrierConfig == null) {
28915c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            return callSubject;
28925c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
28935c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
28945c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to replace invalid characters
28955c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String invalidCharacters = carrierConfig.getString(
28965c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING);
28975c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(invalidCharacters)) {
28985c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = callSubject.replaceAll(invalidCharacters, "");
28995c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
29005c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
29015c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to escape characters which need to be escaped.
29025c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String escapedCharacters = carrierConfig.getString(
29035c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING);
29045c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(escapedCharacters)) {
29055c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = escapeChars(escapedCharacters, callSubject);
29065c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
29075c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return callSubject;
2908d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
2909d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2910d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
29115c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * Given a source string, return a string where a set of characters are escaped using the
29125c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * backslash character.
2913d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
29145c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param toEscape The characters to escape with a backslash.
29155c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param source The source string.
29165c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The source string with characters escaped.
2917d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
29185c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String escapeChars(String toEscape, String source) {
29195c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        StringBuilder escaped = new StringBuilder();
29205c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        for (char c : source.toCharArray()) {
29215c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            if (toEscape.contains(Character.toString(c))) {
29225c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                escaped.append("\\");
29235c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            }
29245c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            escaped.append(c);
2925d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
29265c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
29275c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return escaped.toString();
2928d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
292993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
293093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /**
293193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull of an external call.
293293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
293393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull by making a dial request with the {@link ImsCallProfile#EXTRA_IS_CALL_PULL}
293493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * extra specified.  We call {@link ImsPhone#notifyUnknownConnection(Connection)} which notifies
293593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Telecom of the new dialed connection.  The
293693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@code PstnIncomingCallNotifier#maybeSwapWithUnknownConnection} logic ensures that the new
293793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsPhoneConnection} resulting from the dial gets swapped with the
293893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsExternalConnection}, which effectively makes the external call become a regular
293993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * call.  Magic!
294093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
294193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param number The phone number of the call to be pulled.
294293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param videoState The desired video state of the pulled call.
29433de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn     * @param dialogId The {@link ImsExternalConnection#getCallId()} dialog id associated with the
29443de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn     *                 call which is being pulled.
294593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     */
294693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    @Override
29473de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn    public void pullExternalCall(String number, int videoState, int dialogId) {
294893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        Bundle extras = new Bundle();
294993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        extras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL, true);
29503de018282cd7dae66d4dfff41303e81419d2004dTyler Gunn        extras.putInt(ImsExternalCallTracker.EXTRA_IMS_EXTERNAL_CALL_ID, dialogId);
295193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        try {
295293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            Connection connection = dial(number, videoState, extras);
295393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            mPhone.notifyUnknownConnection(connection);
295493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        } catch (CallStateException e) {
295593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            loge("pullExternalCall failed - " + e);
295693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
295793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
2958cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
2959cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    private ImsException getImsManagerIsNullException() {
2960cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        return new ImsException("no ims manager", ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
2961cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    }
296237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
296337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
296437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Determines if answering an incoming call will cause the active call to be disconnected.
296537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * <p>
296637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * This will be the case if
296737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@link CarrierConfigManager#KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL} is
296837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@code true} for the carrier, the active call is a video call over WIFI, and the incoming
296937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * call is an audio call.
297037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *
297137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param activeCall The active call.
297237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param incomingCall The incoming call.
297337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @return {@code true} if answering the incoming call will cause the active call to be
297437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *      disconnected, {@code false} otherwise.
297537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
297637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean shouldDisconnectActiveCallOnAnswer(ImsCall activeCall,
297737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall incomingCall) {
297837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
297950a6eae6fb10462b1edb12cc30cb9701ca18a212Brad Ebinger        if (activeCall == null || incomingCall == null) {
298050a6eae6fb10462b1edb12cc30cb9701ca18a212Brad Ebinger            return false;
298150a6eae6fb10462b1edb12cc30cb9701ca18a212Brad Ebinger        }
298250a6eae6fb10462b1edb12cc30cb9701ca18a212Brad Ebinger
298337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        if (!mDropVideoCallWhenAnsweringAudioCall) {
298437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return false;
298537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        }
298637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
298737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallVideo = activeCall.isVideoCall() ||
298837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                (mTreatDowngradedVideoCallsAsVideoCalls && activeCall.wasVideoCall());
298937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallOnWifi = activeCall.isWifiCall();
299079de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        boolean isVoWifiEnabled = mImsManager.isWfcEnabledByPlatform(mPhone.getContext()) &&
299179de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                mImsManager.isWfcEnabledByUser(mPhone.getContext());
299237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isIncomingCallAudio = !incomingCall.isVideoCall();
299379de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        log("shouldDisconnectActiveCallOnAnswer : isActiveCallVideo=" + isActiveCallVideo +
299479de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                " isActiveCallOnWifi=" + isActiveCallOnWifi + " isIncomingCallAudio=" +
299579de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn                isIncomingCallAudio + " isVowifiEnabled=" + isVoWifiEnabled);
299679de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn
299779de4402e6be40cbe9cef27d8378645957e4ec88Tyler Gunn        return isActiveCallVideo && isActiveCallOnWifi && isIncomingCallAudio && !isVoWifiEnabled;
299837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    }
299948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
300048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    /** Get aggregated video call data usage since boot.
300148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     *
300248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     * @return data usage in bytes
300348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     */
300448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    public long getVtDataUsage() {
300548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
300648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // If there is an ongoing VT call, request the latest VT usage from the modem. The latest
300748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // usage will return asynchronously so it won't be counted in this round, but it will be
300848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // eventually counted when next getVtDataUsage is called.
300948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        if (mState != PhoneConstants.State.IDLE) {
301048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            for (ImsPhoneConnection conn : mConnections) {
3011f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                android.telecom.Connection.VideoProvider videoProvider = conn.getVideoProvider();
3012f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                if (videoProvider != null) {
3013f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                    videoProvider.onRequestConnectionDataUsage();
3014f8a97a03e91c81eee19420bcdf66a2305f0b4578Brad Ebinger                }
301548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            }
301648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
301748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
301848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        return mTotalVtDataUsage;
301948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    }
302091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
302191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public void registerPhoneStateListener(PhoneStateListener listener) {
302291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        mPhoneStateListeners.add(listener);
302391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
302491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
302591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    public void unregisterPhoneStateListener(PhoneStateListener listener) {
302691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        mPhoneStateListeners.remove(listener);
302791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
302891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
302991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    /**
303091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * Notifies local telephony listeners of changes to the IMS phone state.
303191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     *
303291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param oldState The old state.
303391c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     * @param newState The new state.
303491c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn     */
303591c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    private void notifyPhoneStateChanged(PhoneConstants.State oldState,
303691c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            PhoneConstants.State newState) {
303791c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
303891c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        for (PhoneStateListener listener : mPhoneStateListeners) {
303991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn            listener.onPhoneStateChanged(oldState, newState);
304091c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn        }
304191c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn    }
304291c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
3043a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    /** Modify video call to a new video state.
3044a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     *
3045a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param imsCall IMS call to be modified
3046a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param newVideoState New video state. (Refer to VideoProfile)
3047a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     */
3048a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private void modifyVideoCall(ImsCall imsCall, int newVideoState) {
3049a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsPhoneConnection conn = findConnection(imsCall);
3050a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        if (conn != null) {
3051a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            int oldVideoState = conn.getVideoState();
3052a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            if (conn.getVideoProvider() != null) {
3053a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                conn.getVideoProvider().onSendSessionModifyRequest(
3054a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                        new VideoProfile(oldVideoState), new VideoProfile(newVideoState));
3055a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            }
3056a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        }
3057a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    }
3058a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
3059a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    /**
3060a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * Handler of data enabled changed event
3061a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     * @param enabled True if data is enabled, otherwise disabled.
30622f9f55d539817926542b7db63a41d76badded853Tyler Gunn     * @param reason Reason for data enabled/disabled (see {@code REASON_*} in
30632f9f55d539817926542b7db63a41d76badded853Tyler Gunn     *      {@link DataEnabledSettings}.
3064a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu     */
3065a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    private void onDataEnabledChanged(boolean enabled, int reason) {
3066a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
3067a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        log("onDataEnabledChanged: enabled=" + enabled + ", reason=" + reason);
3068782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu
3069a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId()).setDataEnabled(enabled);
3070a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu
3071782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu        if (mIgnoreDataEnabledChangedForVideoCalls) {
3072782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu            log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " due to carrier policy.");
3073782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu            return;
3074782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu        }
3075782c44d28a8944478b6906aa5c86a14ffd0e63dbJack Yu
30762f9f55d539817926542b7db63a41d76badded853Tyler Gunn        if (!enabled) {
30772f9f55d539817926542b7db63a41d76badded853Tyler Gunn            int reasonCode;
30782f9f55d539817926542b7db63a41d76badded853Tyler Gunn            if (reason == DataEnabledSettings.REASON_POLICY_DATA_ENABLED) {
30792f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_LIMIT_REACHED;
30802f9f55d539817926542b7db63a41d76badded853Tyler Gunn            } else if (reason == DataEnabledSettings.REASON_USER_DATA_ENABLED) {
30812f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
30822f9f55d539817926542b7db63a41d76badded853Tyler Gunn            } else {
30832f9f55d539817926542b7db63a41d76badded853Tyler Gunn                // Unexpected code, default to data disabled.
30842f9f55d539817926542b7db63a41d76badded853Tyler Gunn                reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
30852f9f55d539817926542b7db63a41d76badded853Tyler Gunn            }
30862f9f55d539817926542b7db63a41d76badded853Tyler Gunn
30872f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // If data is disabled while there are ongoing VT calls which are not taking place over
30882f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // wifi, then they should be disconnected to prevent the user from incurring further
30892f9f55d539817926542b7db63a41d76badded853Tyler Gunn            // data charges.
3090a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            for (ImsPhoneConnection conn : mConnections) {
3091a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                ImsCall imsCall = conn.getImsCall();
3092a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                if (imsCall != null && imsCall.isVideoCall() && !imsCall.isWifiCall()) {
30932e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                    if (conn.hasCapabilities(
30942e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
30952e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)) {
30962e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
30972e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // If the carrier supports downgrading to voice, then we can simply issue a
30982e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // downgrade to voice instead of terminating the call.
30992e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        if (reasonCode == ImsReasonInfo.CODE_DATA_DISABLED) {
31002e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            conn.onConnectionEvent(TelephonyManager.EVENT_DOWNGRADE_DATA_DISABLED,
31012e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    null);
31022e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        } else if (reasonCode == ImsReasonInfo.CODE_DATA_LIMIT_REACHED) {
31032e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            conn.onConnectionEvent(
31042e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                                    TelephonyManager.EVENT_DOWNGRADE_DATA_LIMIT_REACHED, null);
31052e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        }
31062e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
31072e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                    } else {
31082e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // If the carrier does not support downgrading to voice, the only choice we
31092e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        // have is to terminate the call.
31102e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        try {
31112e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
31122e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        } catch (ImsException ie) {
31132e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                            loge("Couldn't terminate call " + imsCall);
31142e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn                        }
31152f9f55d539817926542b7db63a41d76badded853Tyler Gunn                    }
3116a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu                }
3117a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu            }
3118a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        }
311991c714c06cc426b4f1af05a758c4d560b16f6d24Tyler Gunn
3120a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        // This will call into updateVideoCallFeatureValue and eventually all clients will be
3121a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        // asynchronously notified that the availability of VT over LTE has changed.
3122a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu        ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
3123a8f5a859f8e4a15902d729af5d2edc9a9433ba41Jack Yu    }
3124508daf6f8286407cf34e32750148fad120009c13Tyler Gunn
3125508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    /**
3126508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     * @return {@code true} if the device is connected to a WIFI network, {@code false} otherwise.
3127508daf6f8286407cf34e32750148fad120009c13Tyler Gunn     */
3128508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    private boolean isWifiConnected() {
3129508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        ConnectivityManager cm = (ConnectivityManager) mPhone.getContext()
3130508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                .getSystemService(Context.CONNECTIVITY_SERVICE);
3131508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        if (cm != null) {
3132508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            NetworkInfo ni = cm.getActiveNetworkInfo();
3133508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            if (ni != null && ni.isConnected()) {
3134508daf6f8286407cf34e32750148fad120009c13Tyler Gunn                return ni.getType() == ConnectivityManager.TYPE_WIFI;
3135508daf6f8286407cf34e32750148fad120009c13Tyler Gunn            }
3136508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        }
3137508daf6f8286407cf34e32750148fad120009c13Tyler Gunn        return false;
3138508daf6f8286407cf34e32750148fad120009c13Tyler Gunn    }
31392e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn
31402e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    /**
31412e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     * @return {@code true} if downgrading of a video call to audio is supported.
31422e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn     */
31432e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    public boolean isCarrierDowngradeOfVtCallSupported() {
31442e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn        return mSupportDowngradeVtToAudio;
31452e7e09e79c04f34034bebea8f5d86606bb584577Tyler Gunn    }
3146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
3147