ImsPhoneCallTracker.java revision d45e0852699f073cb67ef957eadffd4e8130aff5
1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Copyright (C) 2013 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony.imsphone;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.io.FileDescriptor;
2004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.io.PrintWriter;
2104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.util.ArrayList;
2248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yuimport java.util.HashMap;
2304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.util.List;
2448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yuimport java.util.Map;
2504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
26a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.app.PendingIntent;
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.BroadcastReceiver;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Intent;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.IntentFilter;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.SharedPreferences;
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
33df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordonimport android.os.Bundle;
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
36d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.os.PersistableBundle;
37a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
38a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.RegistrantList;
39ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport android.os.RemoteException;
40a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemProperties;
41b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganeshimport android.provider.Settings;
42d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.telephony.CarrierConfigManager;
43d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.text.TextUtils;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.preference.PreferenceManager;
45fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunnimport android.telecom.ConferenceParticipant;
46dc2b5d1c32cad5269106d00fd106bd64097238f4Tyler Gunnimport android.telecom.VideoProfile;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
5004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport android.telephony.ServiceState;
518560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunnimport android.telephony.SubscriptionManager;
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCall;
5404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCallProfile;
55cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.comimport com.android.ims.ImsConfig;
569746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiakimport com.android.ims.ImsConfigListener;
5704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsConnectionStateListener;
5804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsEcbm;
5904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsException;
6004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsManager;
6193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnimport com.android.ims.ImsMultiEndpoint;
6204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsReasonInfo;
6304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsServiceClass;
6408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.ims.ImsSuppServiceNotification;
6504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsUtInterface;
66ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.IImsVideoCallProvider;
67ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.ImsVideoCallProviderWrapper;
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Call;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallTracker;
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandException;
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandsInterface;
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
765054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiakimport com.android.internal.telephony.TelephonyEventLog;
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.TelephonyProperties;
7808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.internal.telephony.gsm.SuppServiceNotification;
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
8393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunnpublic class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ImsPhoneCallTracker";
85a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
86a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
87a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
88707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // When true, dumps the state of ImsPhoneCallTracker after changes to foreground and background
89707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // calls.  This is helpful for debugging.
90707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    private static final boolean VERBOSE_STATE_LOGGING = false; /* stopship if true */
91707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
92915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold    //Indices map to ImsConfig.FeatureConstants
93164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private boolean[] mImsFeatureEnabled = {false, false, false, false, false, false};
94164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private final String[] mImsFeatureStrings = {"VoLTE", "ViLTE", "VoWiFi", "ViWiFi",
95164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            "UTLTE", "UTWiFi"};
96cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
975054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak    private TelephonyEventLog mEventLog;
985054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onReceive(Context context, Intent intent) {
102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (intent.getAction().equals(ImsManager.ACTION_IMS_INCOMING_CALL)) {
103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (DBG) log("onReceive : incoming call intent");
104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mImsManager == null) return;
106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mServiceId < 0) return;
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Network initiated USSD will be treated by mImsUssdListener
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    boolean isUssd = intent.getBooleanExtra(ImsManager.EXTRA_USSD, false);
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (isUssd) {
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (DBG) log("onReceive : USSD");
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mUssdSession = mImsManager.takeCall(mServiceId, intent, mImsUssdListener);
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mUssdSession != null) {
1162999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                            mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        return;
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
12108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    boolean isUnknown = intent.getBooleanExtra(ImsManager.EXTRA_IS_UNKNOWN_CALL,
12208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            false);
12308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (DBG) {
12408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        log("onReceive : isUnknown = " + isUnknown +
12508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " fg = " + mForegroundCall.getState() +
12608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " bg = " + mBackgroundCall.getState());
12708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
12808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
12908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Normal MT/Unknown call
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);
1316bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone, imsCall,
13208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            ImsPhoneCallTracker.this,
13308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            (isUnknown? mForegroundCall: mRingingCall), isUnknown);
13437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
13537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    // If there is an active call.
13637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    if (mForegroundCall.hasConnections()) {
13737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        ImsCall activeCall = mForegroundCall.getFirstConnection().getImsCall();
13837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        boolean answeringWillDisconnect =
13937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                                shouldDisconnectActiveCallOnAnswer(activeCall, imsCall);
14037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        conn.setActiveCallDisconnectedOnAnswer(answeringWillDisconnect);
14137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    }
1428582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                    conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    addConnection(conn);
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
145288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    setVideoCallProvider(conn, imsCall);
146ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
1475054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallReceive(imsCall.getSession());
1485054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
14908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (isUnknown) {
15008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyUnknownConnection(conn);
15108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    } else {
15208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) ||
15308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE)) {
15408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            conn.update(imsCall, ImsPhoneCall.State.WAITING);
15508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        }
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
15708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyNewRingingConnection(conn);
15808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyIncomingRing();
15908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    updatePhoneState();
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyPreciseCallStateChanged();
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (ImsException e) {
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    loge("onReceive : exception " + e);
165ea8cb63201520592011a92849ad3661d22776c87Andrew Lee                } catch (RemoteException e) {
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1678560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            } else if (intent.getAction().equals(
1688560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
1698560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
1708560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                        SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1718560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                if (subId == mPhone.getSubId()) {
17237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    cacheCarrierConfiguration(subId);
1738560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                    log("onReceive : Updating mAllowEmergencyVideoCalls = " +
1748560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                            mAllowEmergencyVideoCalls);
1758560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                }
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS = 7;
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5;
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_HANGUP_PENDINGMO = 18;
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_RESUME_BACKGROUND = 19;
187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DIAL_PENDINGMO = 20;
188e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private static final int EVENT_EXIT_ECBM_BEFORE_PENDINGMO = 21;
18948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private static final int EVENT_VT_DATA_USAGE_UPDATE = 22;
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int TIMEOUT_HANGUP_PENDINGMO = 500;
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ArrayList<ImsPhoneConnection> mConnections = new ArrayList<ImsPhoneConnection>();
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallEndedRegistrants = new RegistrantList();
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallStartedRegistrants = new RegistrantList();
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
198ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mRingingCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_RINGING);
199ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mForegroundCall = new ImsPhoneCall(this,
20075ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_FOREGROUND);
201ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this,
20275ba09a17a669f4906268088a769836aa87d8241fionaxu            ImsPhoneCall.CONTEXT_BACKGROUND);
203ecac744a4e585e3c7af95ffa06fa3e711131200cAmit Mahajan    public ImsPhoneCall mHandoverCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_HANDOVER);
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
20548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // Hold aggregated video call data usage for each video call since boot.
20648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    // The ImsCall's call id is the key of the map.
20748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private final HashMap<Integer, Long> mVtDataUsageMap = new HashMap<>();
20848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    private volatile long mTotalVtDataUsage = 0;
20948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneConnection mPendingMO;
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mClirMode = CommandsInterface.CLIR_DEFAULT;
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Object mSyncHold = new Object();
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mUssdSession = null;
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Message mPendingUssd = null;
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhone mPhone;
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDesiredMute = false;    // false = mute off
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mOnHoldToneStarted = false;
221ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn    private int mOnHoldToneId = -1;
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2239f5345c094210aa5d6606b7705a85a7bc17e831dAmit Mahajan    private PhoneConstants.State mState = PhoneConstants.State.IDLE;
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsManager mImsManager;
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mServiceId = -1;
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
23004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean mIsInEmergencyCall = false;
23104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
23204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private int pendingCallClirMode;
233288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private int mPendingCallVideoState;
234c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private Bundle mPendingIntentExtras;
23504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean pendingCallInEcm = false;
236276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private boolean mSwitchingFgAndBgCalls = false;
237276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private ImsCall mCallExpectedToResume = null;
2388560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    private boolean mAllowEmergencyVideoCalls = false;
23904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
24037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
24137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if video calls which have been downgraded to an
24237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * audio call should be treated as if they are still video calls.
24337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
24437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mTreatDowngradedVideoCallsAsVideoCalls = false;
24537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
24637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
24737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Carrier configuration option which determines if an ongoing video call over wifi should be
24837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * dropped when an audio call is answered.
24937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
25037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean mDropVideoCallWhenAnsweringAudioCall = false;
25137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
2528582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    /**
2538582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * Carrier configuration option which determines whether adding a call during a video call
2548582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     * should be allowed.
2558582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu     */
2568582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu    private boolean mAllowAddCallDuringVideoCall = true;
2578582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu
258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Events
259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
26375ba09a17a669f4906268088a769836aa87d8241fionaxu    public ImsPhoneCallTracker(ImsPhone phone) {
264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        this.mPhone = phone;
265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2667a1c1b02c8603c2bf2f3b401facb389528180eedPavel Zhamaitsiak        mEventLog = new TelephonyEventLog(mPhone.getPhoneId());
2675054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        IntentFilter intentfilter = new IntentFilter();
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
2708560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().registerReceiver(mReceiver, intentfilter);
27237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        cacheCarrierConfiguration(mPhone.getSubId());
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Thread t = new Thread() {
275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            public void run() {
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                getImsService();
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        };
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        t.start();
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PendingIntent createIncomingCallPendingIntent() {
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
284a89314bcc94c43512299131609feea0c2c8167cfLibin.Tang@motorola.com        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                PendingIntent.FLAG_UPDATE_CURRENT);
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void getImsService() {
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("getImsService");
29153dde7e076954c250e55d156cc1df1202c3a8a9eEtan Cohen        mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId());
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mServiceId = mImsManager.open(ImsServiceClass.MMTEL,
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    createIncomingCallPendingIntent(),
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mImsConnectionStateListener);
29604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
2979746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mImsManager.setImsConfigListener(mImsConfigListener);
2989746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
29904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            // Get the ECBM interface and set IMSPhone's listener object for notifications
300ffb90b77322fa64adbe79b976f1c16f3c9441753Amit Mahajan            getEcbmInterface().setEcbmStateListener(mPhone.getImsEcbmStateListener());
30104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if (mPhone.isInEcm()) {
30204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // Call exit ECBM which will invoke onECBMExited
30304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.exitEmergencyCallbackMode();
30404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
305b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            int mPreferredTtyMode = Settings.Secure.getInt(
306b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                mPhone.getContext().getContentResolver(),
307b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                Settings.Secure.PREFERRED_TTY_MODE,
308b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                Phone.TTY_MODE_OFF);
309b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, mPreferredTtyMode, null);
310b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
311b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            ImsMultiEndpoint multiEndpoint = getMultiEndpointInterface();
312b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            if (multiEndpoint != null) {
313b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                multiEndpoint.setExternalCallStateListener(
314b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                        mPhone.getExternalCallTracker().getExternalCallStateListener());
315b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            }
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("getImsService: " + e);
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Leave mImsManager as null, then CallStateException will be thrown when dialing
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mImsManager = null;
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dispose");
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.dispose();
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.dispose();
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.dispose();
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.dispose();
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().unregisterReceiver(mReceiver);
332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void finalize() {
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("ImsPhoneCallTracker finalized");
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Methods
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Public Methods
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.add(r);
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.remove(h);
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.add(r);
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.remove(h);
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
36475ba09a17a669f4906268088a769836aa87d8241fionaxu    public Connection dial(String dialString, int videoState, Bundle intentExtras) throws
36575ba09a17a669f4906268088a769836aa87d8241fionaxu            CallStateException {
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
3671a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu        int oirMode = sp.getInt(Phone.CLIR_KEY, CommandsInterface.CLIR_DEFAULT);
368df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon        return dial(dialString, oirMode, videoState, intentExtras);
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * oirMode is one of the CLIR_ constants
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    synchronized Connection
375df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon    dial(String dialString, int clirMode, int videoState, Bundle intentExtras)
376df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon            throws CallStateException {
377e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
37804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(dialString);
37904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dial clirMode=" + clirMode);
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // note that this triggers call state changed notif
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("service not available");
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!canDial()) {
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot dial in current state");
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
39304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (isPhoneInEcmMode && isEmergencyNumber) {
39404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            handleEcmTimer(ImsPhone.CANCEL_ECM_TIMER);
39504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
39604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
3978560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // If the call is to an emergency number and the carrier does not support video emergency
3988560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        // calls, dial as an audio-only call.
399025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        if (isEmergencyNumber && VideoProfile.isVideo(videoState) &&
4008560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                !mAllowEmergencyVideoCalls) {
4018560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            loge("dial: carrier does not support video emergency calls; downgrade to audio-only");
4028560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn            videoState = VideoProfile.STATE_AUDIO_ONLY;
4038560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
4048560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean holdBeforeDial = false;
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // The new call must be assigned to the foreground call.
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // That call must be idle, so place anything that's
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // there on hold
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we should have failed in !canDial() above before we get here
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot dial in current state");
414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // foreground call is empty for the newly dialed connection
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            holdBeforeDial = true;
417288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache the video state for pending MO call.
418288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
419c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            mPendingIntentExtras = intentExtras;
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mClirMode = clirMode;
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mSyncHold) {
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (holdBeforeDial) {
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                fgState = mForegroundCall.getState();
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                bgState = mBackgroundCall.getState();
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call failed
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (fgState == ImsPhoneCall.State.ACTIVE) {
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("cannot dial in current state");
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call succeeded
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (bgState == ImsPhoneCall.State.HOLDING) {
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    holdBeforeDial = false;
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4446bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mPendingMO = new ImsPhoneConnection(mPhone,
4458bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    checkForTestEmergencyNumber(dialString), this, mForegroundCall,
4468bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyNumber);
44757d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade            mPendingMO.setVideoState(videoState);
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        addConnection(mPendingMO);
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!holdBeforeDial) {
45204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
453c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, clirMode, videoState, intentExtras);
45404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            } else {
45504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                try {
45604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    getEcbmInterface().exitEmergencyCallbackMode();
45704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                } catch (ImsException e) {
45804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    e.printStackTrace();
45904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    throw new CallStateException("service not available");
46004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
46104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
46204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallClirMode = clirMode;
463288268d5528e0df03f348e303954813cb188c55bRekha Kumar                mPendingCallVideoState = videoState;
46404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallInEcm = true;
46504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mPendingMO;
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4748560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    /**
47537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Caches frequently used carrier configuration items locally.
4768560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     *
4778560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     * @param subId The sub id.
4788560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn     */
47937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private void cacheCarrierConfiguration(int subId) {
4808560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
4818560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
4828560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfigManager == null) {
48337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: No carrier config service found.");
48437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
4858560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
4868560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
487025c01920e4cf357594379ef35fe89c715e3507eEtan Cohen        PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(subId);
4888560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        if (carrierConfig == null) {
48937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            loge("cacheCarrierConfiguration: Empty carrier config.");
49037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return;
4918560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn        }
4928560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
49337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mAllowEmergencyVideoCalls =
49437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
49537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mTreatDowngradedVideoCallsAsVideoCalls =
49637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
49737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL);
49837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        mDropVideoCallWhenAnsweringAudioCall =
49937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                carrierConfig.getBoolean(
50037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        CarrierConfigManager.KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL);
5018582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu        mAllowAddCallDuringVideoCall =
5028582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                carrierConfig.getBoolean(
5038582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu                        CarrierConfigManager.KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL);
5048560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn    }
5058560465c584604ff51ceb4492bb7daca023e7d52Tyler Gunn
50604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private void handleEcmTimer(int action) {
50704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        mPhone.handleTimerInEmergencyCallbackMode(action);
50804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        switch (action) {
50904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.CANCEL_ECM_TIMER:
51004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
51104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.RESTART_ECM_TIMER:
51204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
51304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            default:
51404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                log("handleEcmTimer, unsupported action " + action);
51504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
51604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
51704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
518c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private void dialInternal(ImsPhoneConnection conn, int clirMode, int videoState,
519c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            Bundle intentExtras) {
520c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getAddress()== null || conn.getAddress().length() == 0
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Phone number is invalid
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Always unmute when initiating a new call
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setMute(false);
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
5366bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
53764e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
53864e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
53964e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        conn.setVideoState(videoState);
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { conn.getAddress() };
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
5446bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                    serviceType, callType);
545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
547c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // Translate call subject intent-extra from Telecom-specific extra key to the
548c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // ImsCallProfile key.
549c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            if (intentExtras != null) {
550c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                if (intentExtras.containsKey(android.telecom.TelecomManager.EXTRA_CALL_SUBJECT)) {
551c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                    intentExtras.putString(ImsCallProfile.EXTRA_DISPLAY_TEXT,
5525c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                            cleanseInstantLetteringMessage(intentExtras.getString(
553d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                                    android.telecom.TelecomManager.EXTRA_CALL_SUBJECT))
554d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                    );
555c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                }
556c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
55767f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                if (intentExtras.containsKey(ImsCallProfile.EXTRA_IS_CALL_PULL)) {
55867f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                    profile.mCallExtras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL,
55967f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                            intentExtras.getBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL));
56067f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn                }
56167f3535dbfa1e4ca1ed846dd649015e8bd1f7328Tyler Gunn
562c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // Pack the OEM-specific call extras.
563c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                profile.mCallExtras.putBundle(ImsCallProfile.EXTRA_OEM_EXTRAS, intentExtras);
564c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
565c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // NOTE: Extras to be sent over the network are packed into the
566c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // intentExtras individually, with uniquely defined keys.
567c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // These key-value pairs are processed by IMS Service before
568c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // being sent to the lower layers/to the network.
569c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            }
570c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mImsManager.makeCall(mServiceId, profile,
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsCallListener);
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setImsCall(imsCall);
574ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
5755054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallStart(imsCall.getSession(), callees[0]);
5765054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
577288268d5528e0df03f348e303954813cb188c55bRekha Kumar            setVideoCallProvider(conn, imsCall);
5788582f01cac98266bfd86c42e58eab3bf810328c4Hall Liu            conn.setAllowAddCallDuringVideoCall(mAllowAddCallDuringVideoCall);
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("dialInternal : " + e);
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
583ea8cb63201520592011a92849ad3661d22776c87Andrew Lee        } catch (RemoteException e) {
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5872999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    /**
5882999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * Accepts a call with the specified video state.  The video state is the video state that the
5892999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * user has agreed upon in the InCall UI.
5902999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     *
5912999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @param videoState The video State
5922999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @throws CallStateException
5932999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     */
59475ba09a17a669f4906268088a769836aa87d8241fionaxu    public void acceptCall (int videoState) throws CallStateException {
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("acceptCall");
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState().isAlive()
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mBackgroundCall.getState().isAlive()) {
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot accept call");
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING)
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mForegroundCall.getState().isAlive()) {
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
60537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
60637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            boolean answeringWillDisconnect = false;
60737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall activeCall = mForegroundCall.getImsCall();
60837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall ringingCall = mRingingCall.getImsCall();
60937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (mForegroundCall.hasConnections() && mRingingCall.hasConnections()) {
61037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                answeringWillDisconnect =
61137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                        shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall);
61237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
61337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
614288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache video state for pending MT call.
615288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
61637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
61737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            if (answeringWillDisconnect) {
61837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                // We need to disconnect the foreground call before answering the background call.
61937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                mForegroundCall.hangup();
62037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                try {
62137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    ringingCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
62237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                } catch (ImsException e) {
62337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                    throw new CallStateException("cannot accept call");
62437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                }
62537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            } else {
62637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                switchWaitingOrHoldingAndActive();
62737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            }
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mRingingCall.getState().isRinging()) {
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("acceptCall: incoming...");
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Always unmute when answering a new call
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) {
6352999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                    imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
6365054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallAccept(imsCall.getSession());
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("no valid ims call");
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot accept call");
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
64875ba09a17a669f4906268088a769836aa87d8241fionaxu    public void rejectCall () throws CallStateException {
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("rejectCall");
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState().isRinging()) {
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            hangup(mRingingCall);
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
658007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
659007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    private void switchAfterConferenceSuccess() {
660007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (DBG) log("switchAfterConferenceSuccess fg =" + mForegroundCall.getState() +
661007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                ", bg = " + mBackgroundCall.getState());
662007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
663007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
664007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            log("switchAfterConferenceSuccess");
665007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            mForegroundCall.switchWith(mBackgroundCall);
666007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        }
667007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    }
668007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
66975ba09a17a669f4906268088a769836aa87d8241fionaxu    public void switchWaitingOrHoldingAndActive() throws CallStateException {
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("switchWaitingOrHoldingAndActive");
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState() == ImsPhoneCall.State.INCOMING) {
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot be in the incoming state");
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mForegroundCall.getImsCall();
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == null) {
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("no ims call");
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
682276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Swap the ImsCalls pointed to by the foreground and background ImsPhoneCalls.
683276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If hold or resume later fails, we will swap them back.
684276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mSwitchingFgAndBgCalls = true;
685276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mCallExpectedToResume = mBackgroundCall.getImsCall();
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.switchWith(mBackgroundCall);
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
688276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Hold the foreground call; once the foreground call is held, the background call will
689276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // be resumed.
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                imsCall.hold();
6925054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCallHold(imsCall.getSession());
693707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
694707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                // If there is no background call to resume, then don't expect there to be a switch.
695707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mCallExpectedToResume == null) {
696707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    mSwitchingFgAndBgCalls = false;
697707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mForegroundCall.switchWith(mBackgroundCall);
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException(e.getMessage());
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            resumeWaitingOrHolding();
704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7077dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    conference() {
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("conference");
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall fgImsCall = mForegroundCall.getImsCall();
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (fgImsCall == null) {
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no foreground ims call");
714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
715a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
716a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
717a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall bgImsCall = mBackgroundCall.getImsCall();
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (bgImsCall == null) {
719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no background ims call");
720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
721a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
723fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // Keep track of the connect time of the earliest call so that it can be set on the
724fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // {@code ImsConference} when it is created.
7257ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long foregroundConnectTime = mForegroundCall.getEarliestConnectTime();
7267ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long backgroundConnectTime = mBackgroundCall.getEarliestConnectTime();
7277ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long conferenceConnectTime;
7287ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        if (foregroundConnectTime > 0 && backgroundConnectTime > 0) {
7297ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = Math.min(mForegroundCall.getEarliestConnectTime(),
7307ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn                    mBackgroundCall.getEarliestConnectTime());
7317ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - using connect time = " + conferenceConnectTime);
7327ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else if (foregroundConnectTime > 0) {
7337ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - bg call connect time is 0; using fg = " + foregroundConnectTime);
7347ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = foregroundConnectTime;
7357ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else {
7367ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - fg call connect time is 0; using bg = " + backgroundConnectTime);
7377ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = backgroundConnectTime;
7387ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        }
7397ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn
740fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        ImsPhoneConnection foregroundConnection = mForegroundCall.getFirstConnection();
741fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        if (foregroundConnection != null) {
742fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            foregroundConnection.setConferenceConnectTime(conferenceConnectTime);
743fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        }
744fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
745a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
746a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            fgImsCall.merge(bgImsCall);
747a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
748a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference " + e.getMessage());
749a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7527dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    explicitCallTransfer() {
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //TODO : implement
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7577dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clearDisconnected() {
759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("clearDisconnected");
760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        internalClearDisconnected();
762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
765a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7677dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canConference() {
769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING
771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mBackgroundCall.isFull()
772a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mForegroundCall.isFull();
773a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
774a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7757dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
776a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canDial() {
777a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean ret;
778a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceState = mPhone.getServiceState().getState();
779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        String disableCall = SystemProperties.get(
780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mPendingMO == null
784a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mRingingCall.isRinging()
785a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !disableCall.equals("true")
786a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && (!mForegroundCall.getState().isAlive()
787a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    || !mBackgroundCall.getState().isAlive());
788a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
789a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ret;
790a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
791a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
7927dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public boolean
793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canTransfer() {
794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING;
796a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
797a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
798a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Private Instance Methods
799a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
800a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
801a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    internalClearDisconnected() {
802a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.clearDisconnected();
803a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.clearDisconnected();
804a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.clearDisconnected();
805a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.clearDisconnected();
806a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
807a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
808a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
809a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    updatePhoneState() {
810a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PhoneConstants.State oldState = mState;
811a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.isRinging()) {
813a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.RINGING;
814a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPendingMO != null ||
815a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())) {
816a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.OFFHOOK;
817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
818a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.IDLE;
819a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
820a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
821a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState == PhoneConstants.State.IDLE && oldState != mState) {
822a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallEndedRegistrants.notifyRegistrants(
823a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
824a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
825a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallStartedRegistrants.notifyRegistrants (
826a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
827a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
828a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
829a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("updatePhoneState oldState=" + oldState + ", newState=" + mState);
830a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
831a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState != oldState) {
832a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPhoneStateChanged();
8339746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writePhoneState(mState);
834a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
835a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
836a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
837a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleRadioNotAvailable() {
839a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // handlePollCalls will clear out its
840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // call list when it gets the CommandException
841a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // error result from this
842a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pollCallsWhenSafe();
843a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
844a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
845a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
846a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    dumpState() {
847a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        List l;
848a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
849a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Phone State:" + mState);
850a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
851a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Ringing call: " + mRingingCall.toString());
852a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
853a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mRingingCall.getConnections();
854a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
855a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
856a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
857a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
858a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Foreground call: " + mForegroundCall.toString());
859a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
860a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mForegroundCall.getConnections();
861a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
862a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
863a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
864a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
865a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Background call: " + mBackgroundCall.toString());
866a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
867a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mBackgroundCall.getConnections();
868a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
869a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
870a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
871a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
872a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
873a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
874a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhone
875a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
87693c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setUiTTYMode(int uiTtyMode, Message onComplete) {
877cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        if (mImsManager == null) {
878cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            mPhone.sendErrorResponse(onComplete, getImsManagerIsNullException());
879cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            return;
880cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        }
881cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
882b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        try {
883f1099a9dfe0250a6b343de0646413db4034381deEtan Cohen            mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, uiTtyMode, onComplete);
884b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        } catch (ImsException e) {
885b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            loge("setTTYMode : " + e);
886b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            mPhone.sendErrorResponse(onComplete, e);
887b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        }
888b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh    }
889b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
89093c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public void setMute(boolean mute) {
891a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDesiredMute = mute;
892a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.setMute(mute);
893a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
89593c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public boolean getMute() {
896a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDesiredMute;
897a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
898a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
899f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void sendDtmf(char c, Message result) {
900a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendDtmf");
901a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
902a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imscall = mForegroundCall.getImsCall();
903a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imscall != null) {
904d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            imscall.sendDtmf(c, result);
905a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
906a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
907a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
9087dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
909c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    startDtmf(char c) {
910c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("startDtmf");
911c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
912c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
913c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
914c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.startDtmf(c);
915c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
916c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("startDtmf : no foreground call");
917c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
918c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
919c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
9207dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void
921c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    stopDtmf() {
922c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("stopDtmf");
923c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
924c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
925c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
926c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.stopDtmf();
927c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
928c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("stopDtmf : no foreground call");
929c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
930c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
931c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
932a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneConnection
933a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
934f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneConnection conn) throws CallStateException {
935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup connection");
936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getOwner() != this) {
938a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("ImsPhoneConnection " + conn
939a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "does not belong to ImsPhoneCallTracker " + this);
940a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
941a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
942a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        hangup(conn.getCall());
943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneCall
946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
947f9b150b221db15e88b97a0b9c0971ca3c71c0313fionaxu    public void hangup (ImsPhoneCall call) throws CallStateException {
948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup call");
949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call.getConnections().size() == 0) {
951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("no connections");
952a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
953a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
954a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imsCall = call.getImsCall();
955a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean rejectCall = false;
956a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
957a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call == mRingingCall) {
958a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
959a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            rejectCall = true;
960a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mForegroundCall) {
961a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (call.isDialingOrAlerting()) {
962a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
963a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup dialing or alerting...");
964a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
966a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
967a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup foreground");
968a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
969a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //held call will be resumed by onCallTerminated
970a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
971a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mBackgroundCall) {
972a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) {
973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("(backgnd) hangup waiting or background");
974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
975a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
976ac82d4da0473991006a752e2337ccb93e85f0946Etan Cohen            throw new CallStateException ("ImsPhoneCall " + call +
977a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    "does not belong to ImsPhoneCallTracker " + this);
978a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
979a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
980a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        call.onHangupLocal();
981a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
982a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall != null) {
9845054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (rejectCall) {
9855054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE);
9865054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallReject(imsCall.getSession());
9875054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                } else {
9885054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
9895054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallTerminate(imsCall.getSession());
9905054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
991a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mPendingMO != null && call == mForegroundCall) {
992a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // is holding a foreground call
993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED);
994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.onDisconnect();
995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeConnection(mPendingMO);
996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
997a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeMessages(EVENT_DIAL_PENDINGMO);
999a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1000a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1001a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1002a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1004a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
1005a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1006a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
100769e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    void callEndCleanupHandOverCallIfAny() {
100869e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        if (mHandoverCall.mConnections.size() > 0) {
100969e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            if (DBG) log("callEndCleanupHandOverCallIfAny, mHandoverCall.mConnections="
101069e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com                    + mHandoverCall.mConnections);
101169e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mHandoverCall.mConnections.clear();
1012d45e0852699f073cb67ef957eadffd4e8130aff5Shriram Ganesh            mConnections.clear();
101369e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mState = PhoneConstants.State.IDLE;
101469e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        }
101569e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    }
101669e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com
1017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void resumeWaitingOrHolding() throws CallStateException {
1019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("resumeWaitingOrHolding");
1020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getState().isAlive()) {
1023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //resume foreground call after holding background call
1024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //they were switched before holding
1025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mForegroundCall.getImsCall();
10265054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
10275054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
10285054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallResume(imsCall.getSession());
10295054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1030a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
1031a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //accept waiting call after holding background call
1032a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
1033288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (imsCall != null) {
1034288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    imsCall.accept(
1035288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        ImsCallProfile.getCallTypeFromVideoState(mPendingCallVideoState));
10365054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallAccept(imsCall.getSession());
1037288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
1038a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
1039a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //Just resume background call.
1040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //To distinguish resuming call with swapping calls
1041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we do not switch calls.here
1042a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //ImsPhoneConnection.update will chnage the parent when completed
1043a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mBackgroundCall.getImsCall();
10445054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                if (imsCall != null) {
10455054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    imsCall.resume();
10465054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    mEventLog.writeOnImsCallResume(imsCall.getSession());
10475054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                }
1048a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1049a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1050a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
1051a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1052a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1053a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
10547dc57a87610b8f203605639338c5aca12886ec53Amit Mahajan    public void sendUSSD (String ussdString, Message response) {
1055a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendUSSD");
1056a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1057a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1058a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mUssdSession != null) {
1059a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession.sendUssd(ussdString);
1060a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                AsyncResult.forMessage(response, null, null);
1061a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                response.sendToTarget();
1062a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
1063a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1065cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            if (mImsManager == null) {
1066cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                mPhone.sendErrorResponse(response, getImsManagerIsNullException());
1067cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak                return;
1068cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            }
1069cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
1070a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { ussdString };
1071a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
1072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE);
1073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_DIALSTRING,
1074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.DIALSTRING_USSD);
1075a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1076a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession = mImsManager.makeCall(mServiceId, profile,
1077a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsUssdListener);
1078a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1079a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("sendUSSD : " + e);
1080a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.sendErrorResponse(response, e);
1081a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1082a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1083a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1084cc8ea4abbe4f1f755dc5cf1b576d51ceb24fe79dAmit Mahajan    public void cancelUSSD() {
1085a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUssdSession == null) return;
1086a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1087a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
1088a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
1089a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
1090a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1091a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1092a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1093a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1094288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private synchronized ImsPhoneConnection findConnection(final ImsCall imsCall) {
1095a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (ImsPhoneConnection conn : mConnections) {
1096a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getImsCall() == imsCall) {
1097a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return conn;
1098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1099a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
1101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void removeConnection(ImsPhoneConnection conn) {
1104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.remove(conn);
11058bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        // If not emergency call is remaining, notify emergency call registrants
11068bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (mIsInEmergencyCall) {
11078bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            boolean isEmergencyCallInList = false;
11088bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            // if no emergency calls pending, set this to false
11098bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            for (ImsPhoneConnection imsPhoneConnection : mConnections) {
11108bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                if (imsPhoneConnection != null && imsPhoneConnection.isEmergency() == true) {
11118bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyCallInList = true;
11128bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    break;
11138bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                }
11148bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            }
11158bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
1116a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            if (!isEmergencyCallInList) {
1117a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mIsInEmergencyCall = false;
1118a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan                mPhone.sendEmergencyCallStateChange(false);
1119a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            }
11208bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void addConnection(ImsPhoneConnection conn) {
1124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.add(conn);
11258bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (conn.isEmergency()) {
11268bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            mIsInEmergencyCall = true;
1127a579e9c631d70bb6dbd39283438212d5ff8f19c0Amit Mahajan            mPhone.sendEmergencyCallStateChange(true);
11288bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
1129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
11320db65ec818e58fb5b83a492e082db4536f3b83e0Tyler Gunn        if (DBG) log("processCallStateChange " + imsCall + " state=" + state + " cause=" + cause);
1133d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // This method is called on onCallUpdate() where there is not necessarily a call state
1134d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // change. In these situations, we'll ignore the state related updates and only process
1135d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // the change in media capabilities (as expected).  The default is to not ignore state
1136d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // changes so we do not change existing behavior.
1137d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        processCallStateChange(imsCall, state, cause, false /* do not ignore state update */);
1138d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    }
1139d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati
1140d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause,
1141d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            boolean ignoreState) {
1142d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (DBG) {
1143d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            log("processCallStateChange state=" + state + " cause=" + cause
1144d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                    + " ignoreState=" + ignoreState);
1145d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        }
1146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imsCall == null) return;
1148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
1150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneConnection conn = findConnection(imsCall);
1151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
1153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : what should be done?
1154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
1155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1157d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // processCallStateChange is triggered for onCallUpdated as well.
1158d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // onCallUpdated should not modify the state of the call
1159d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // It should modify only other capabilities of call through updateMediaCapabilities
1160d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // State updates will be triggered through individual callbacks
1161d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // i.e. onCallHeld, onCallResume, etc and conn.update will be responsible for the update
116257d5bd9f23c9b380ddd205665758ece8784578a4Omkar Kolangade        conn.updateMediaCapabilities(imsCall);
1163d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (ignoreState) {
116427e0378194d55fdcb23f4a3a85dc620a234b5855Anju Mathapati            conn.updateAddressDisplay(imsCall);
116521048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            conn.updateExtras(imsCall);
11663652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
11673652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            maybeSetVideoCallProvider(conn, imsCall);
1168d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            return;
1169d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        }
1170d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn
1171d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        changed = conn.update(imsCall, state);
1172d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        if (state == ImsPhoneCall.State.DISCONNECTED) {
1173d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            changed = conn.onDisconnect(cause) || changed;
1174d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            //detach the disconnected connections
1175d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            conn.getCall().detach(conn);
1176d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            removeConnection(conn);
1177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (changed) {
1180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getCall() == mHandoverCall) return;
1181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
1182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
1183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11863652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    private void maybeSetVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall) {
11873652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        android.telecom.Connection.VideoProvider connVideoProvider = conn.getVideoProvider();
11883652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        if (connVideoProvider != null || imsCall.getCallSession().getVideoCallProvider() == null) {
11893652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            return;
11903652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
11913652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
11923652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        try {
11933652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            setVideoCallProvider(conn, imsCall);
11943652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        } catch (RemoteException e) {
11953652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan            loge("maybeSetVideoCallProvider: exception " + e);
11963652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan        }
11973652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan    }
11983652067799a38973435c8663ab9cdb2a8290e48fGarik Badalyan
1199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int getDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
1200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int cause = DisconnectCause.ERROR_UNSPECIFIED;
1201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //int type = reasonInfo.getReasonType();
1203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int code = reasonInfo.getCode();
1204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (code) {
1205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_ADDRESS:
1206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_REACHABLE:
1207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NUMBER_UNREACHABLE;
1208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BUSY:
1210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.BUSY;
1211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED:
1213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.LOCAL;
1214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
12153b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com            case ImsReasonInfo.CODE_LOCAL_CALL_DECLINE:
12163b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                return DisconnectCause.INCOMING_REJECTED;
12173b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com
1218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE:
1219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NORMAL;
1220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REDIRECTED:
1222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_REQUEST:
1223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_FORBIDDEN:
1224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE:
1225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_USER_REJECTED:
1226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_GLOBAL_ERROR:
1227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_ERROR;
1228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE:
1230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_FOUND:
1231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVER_ERROR:
1232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_UNREACHABLE;
1233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING:
1235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED:
1236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN:
1237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE:
1238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED:
1239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE:
1240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE:
1241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING:
1242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.OUT_OF_SERVICE;
1243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT:
1245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING:
1246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER:
1247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE:
1248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.TIMED_OUT;
1249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_LOW_BATTERY:
1251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_POWER_OFF:
1252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.POWER_OFF;
1253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
125408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            case ImsReasonInfo.CODE_FDN_BLOCKED:
125508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                return DisconnectCause.FDN_BLOCKED;
12561c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn
12571c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_ANSWERED_ELSEWHERE:
12585deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn                return DisconnectCause.ANSWERED_ELSEWHERE;
12595deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn
12601c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn            case ImsReasonInfo.CODE_CALL_END_CAUSE_CALL_PULL:
12611c23d391a314ffdb71874b06e9a0e54607208832Tyler Gunn                return DisconnectCause.CALL_PULLED;
1262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            default:
1263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return cause;
1266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1269e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * @return true if the phone is in Emergency Callback mode, otherwise false
1270e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1271e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private boolean isPhoneInEcbMode() {
1272e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        return SystemProperties.getBoolean(TelephonyProperties.PROPERTY_INECM_MODE, false);
1273e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1274e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1275e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1276e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * Before dialing pending MO request, check for the Emergency Callback mode.
1277e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     * If device is in Emergency callback mode, then exit the mode before dialing pending MO.
1278e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati     */
1279e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    private void dialPendingMO() {
1280e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isPhoneInEcmMode = isPhoneInEcbMode();
1281e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        boolean isEmergencyNumber = mPendingMO.isEmergency();
1282e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
1283e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_DIAL_PENDINGMO);
1284e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        } else {
1285e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            sendEmptyMessage(EVENT_EXIT_ECBM_BEFORE_PENDINGMO);
1286e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati        }
1287e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    }
1288e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
1289e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati    /**
1290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsCallListener = new ImsCall.Listener() {
1293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallProgressing(ImsCall imsCall) {
1295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallProgressing");
1296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ALERTING,
1299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
13005054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallProgressing(imsCall.getCallSession());
1301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStarted");
1306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
13105054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallStarted(imsCall.getCallSession());
1311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1313288268d5528e0df03f348e303954813cb188c55bRekha Kumar        @Override
1314288268d5528e0df03f348e303954813cb188c55bRekha Kumar        public void onCallUpdated(ImsCall imsCall) {
1315288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (DBG) log("onCallUpdated");
1316288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (imsCall == null) {
1317288268d5528e0df03f348e303954813cb188c55bRekha Kumar                return;
1318288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1319288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsPhoneConnection conn = findConnection(imsCall);
1320288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (conn != null) {
1321288268d5528e0df03f348e303954813cb188c55bRekha Kumar                processCallStateChange(imsCall, conn.getCall().mState,
1322d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                        DisconnectCause.NOT_DISCONNECTED, true /*ignore state update*/);
13235054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeImsCallState(imsCall.getCallSession(), conn.getCall().mState);
1324288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1325288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
1326288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /**
1328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * onCallStartFailed will be invoked when:
1329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 1) Dialing fails
1330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 2) Ringing call is disconnected by local or remote user
1331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
1332a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
1335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPendingMO != null) {
1337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // To initiate dialing circuit-switched call
1338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
1339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mBackgroundCall.getState() == ImsPhoneCall.State.IDLE
1340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mRingingCall.getState() == ImsPhoneCall.State.IDLE) {
1341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.detach(mPendingMO);
1342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.finalize();
1344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.initiateSilentRedial();
1346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return;
1347990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                } else {
13482770b0f5449670eadab1d68ea8d5fa4788f4704aSantos Cordon                    mPendingMO = null;
1349990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1350990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
1351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
13525054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCallStartFailed(imsCall.getCallSession(), reasonInfo);
1353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallTerminated reasonCode=" + reasonInfo.getCode());
1359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneCall.State oldState = mForegroundCall.getState();
1361bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1362bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            ImsPhoneConnection conn = findConnection(imsCall);
1363bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            if (DBG) log("cause = " + cause + " conn = " + conn);
1364bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com
1365ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            if (mOnHoldToneId == System.identityHashCode(conn)) {
1366ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                if (conn != null && mOnHoldToneStarted) {
1367ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.stopOnHoldTone(conn);
1368ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                }
1369ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneStarted = false;
1370ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mOnHoldToneId = -1;
1371ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            }
13725deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn            if (conn != null && conn.isIncoming() && conn.getConnectTime() == 0
13735deeeef8a7c8685abda3bdf00464bc2582c2b5c6Tyler Gunn                    && cause != DisconnectCause.ANSWERED_ELSEWHERE) {
13743b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                // Missed
13753b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                if (cause == DisconnectCause.NORMAL) {
1376bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com                    cause = DisconnectCause.INCOMING_MISSED;
137708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else {
137808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    cause = DisconnectCause.INCOMING_REJECTED;
137917e77849f88cf20dc5a28aeede66b839fbbdb831Uma Maheswari Ramalingam                }
13805fbf6bed80437e092a93e6137de56e6b409910b1Etan Cohen                if (DBG) log("Incoming connection of 0 connect time detected - translated cause = "
13815fbf6bed80437e092a93e6137de56e6b409910b1Etan Cohen                        + cause);
1382f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com
1383bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            }
1384f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1385f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            if (cause == DisconnectCause.NORMAL && conn != null && conn.getImsCall().isMerged()) {
1386f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                // Call was terminated while it is merged instead of a remote disconnect.
1387f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                cause = DisconnectCause.IMS_MERGED_SUCCESSFULLY;
1388f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            }
1389f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
13909746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writeOnImsCallTerminated(imsCall.getCallSession(), reasonInfo);
13919746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
1392bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
139308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (mForegroundCall.getState() != ImsPhoneCall.State.ACTIVE) {
139408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                if (mRingingCall.getState().isRinging()) {
139508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Drop pending MO. We should address incoming call first
139608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    mPendingMO = null;
139708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else if (mPendingMO != null) {
139808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    sendEmptyMessage(EVENT_DIAL_PENDINGMO);
139908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                }
140008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            }
14011a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu
14021a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            if (mSwitchingFgAndBgCalls) {
14031a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (DBG) {
14041a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    log("onCallTerminated: Call terminated in the midst of Switching " +
14051a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                            "Fg and Bg calls.");
14061a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
14071a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // If we are the in midst of swapping FG and BG calls and the call that was
14081a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // terminated was the one that we expected to resume, we need to swap the FG and
14091a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // BG calls back.
14101a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (imsCall == mCallExpectedToResume) {
14111a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (DBG) {
14121a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        log("onCallTerminated: switching " + mForegroundCall + " with "
14131a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                                + mBackgroundCall);
14141a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
14151a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mForegroundCall.switchWith(mBackgroundCall);
14161a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
14171a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // This call terminated in the midst of a switch after the other call was held, so
14181a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                // resume it back to ACTIVE state since the switch failed.
14191a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
14201a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    sendEmptyMessage(EVENT_RESUME_BACKGROUND);
14211a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mSwitchingFgAndBgCalls = false;
14221a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    mCallExpectedToResume = null;
14231a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                }
14241a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu            }
1425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHeld(ImsCall imsCall) {
1429707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (DBG) {
1430707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mForegroundCall.getImsCall() == imsCall) {
1431707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (fg) " + imsCall);
1432707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                } else if (mBackgroundCall.getImsCall() == imsCall) {
1433707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (bg) " + imsCall);
1434707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1435707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
1436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State oldState = mBackgroundCall.getState();
1439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
1440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        DisconnectCause.NOT_DISCONNECTED);
1441c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1442c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // Note: If we're performing a switchWaitingOrHoldingAndActive, the call to
1443c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // processCallStateChange above may have caused the mBackgroundCall and
1444c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // mForegroundCall references below to change meaning.  Watch out for this if you
1445c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // are reading through this code.
1446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (oldState == ImsPhoneCall.State.ACTIVE) {
1447276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // Note: This case comes up when we have just held a call in response to a
1448276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // switchWaitingOrHoldingAndActive.  We now need to resume the background call.
1449276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // The EVENT_RESUME_BACKGROUND causes resumeWaitingOrHolding to be called.
1450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
1451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
1452f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    } else {
1454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //when multiple connections belong to background call,
1455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //only the first callback reaches here
1456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //otherwise the oldState is already HOLDING
1457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mPendingMO != null) {
1458e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                            dialPendingMO();
1459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
1460c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1461c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // In this case there will be no call resumed, so we can assume that we
1462c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // are done switching fg and bg calls now.
1463c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // This may happen if there is no BG call and we are holding a call so that
1464c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // we can dial another one.
1465c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        mSwitchingFgAndBgCalls = false;
1466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
14671a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                } else if (oldState == ImsPhoneCall.State.IDLE && mSwitchingFgAndBgCalls) {
14681a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // The other call terminated in the midst of a switch before this call was held,
14691a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    // so resume the foreground call back to ACTIVE state since the switch failed.
14701a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
14711a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        sendEmptyMessage(EVENT_RESUME_BACKGROUND);
14721a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mSwitchingFgAndBgCalls = false;
14731a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                        mCallExpectedToResume = null;
14741a87ab3d7170d618f048c4f5af8c7504a587aaa5Jack Yu                    }
1475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
14775054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHeld(imsCall.getCallSession());
1478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldFailed reasonCode=" + reasonInfo.getCode());
1483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State bgState = mBackgroundCall.getState();
1486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
1487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // disconnected while processing hold
1488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1489e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        dialPendingMO();
1490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else if (bgState == ImsPhoneCall.State.ACTIVE) {
1492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.switchWith(mBackgroundCall);
1493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
1496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
1497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
14995326ba5f8e9488416fd7160680dc6b6319c6b00eAnju Mathapati                mPhone.notifySuppServiceFailed(Phone.SuppService.HOLD);
1500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
15015054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHoldFailed(imsCall.getCallSession(), reasonInfo);
1502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumed(ImsCall imsCall) {
1506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumed");
1507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1508276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If we are the in midst of swapping FG and BG calls and the call we end up resuming
1509276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // is not the one we expected, we likely had a resume failure and we need to swap the
1510276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // FG and BG calls back.
15110ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn            if (mSwitchingFgAndBgCalls) {
15120ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                if (imsCall != mCallExpectedToResume) {
15130ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // If the call which resumed isn't as expected, we need to swap back to the
15140ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // previous configuration; the swap has failed.
15150ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
15160ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : switching " + mForegroundCall + " with "
15170ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                                + mBackgroundCall);
15180ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
15190ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    mForegroundCall.switchWith(mBackgroundCall);
15200ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                } else {
15210ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // The call which resumed is the one we expected to resume, so we can clear out
15220ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    // the mSwitchingFgAndBgCalls flag.
15230ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    if (DBG) {
15240ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                        log("onCallResumed : expected call resumed.");
15250ae749285976deff6f73db0d414f36548c5682b3Tyler Gunn                    }
1526707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1527276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1528276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1529276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
15325054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumed(imsCall.getCallSession());
1533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1537afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati            if (mSwitchingFgAndBgCalls) {
1538afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // If we are in the midst of swapping the FG and BG calls and
1539afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // we got a resume fail, we need to swap back the FG and BG calls.
1540afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                // Since the FG call was held, will also try to resume the same.
1541afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                if (imsCall == mCallExpectedToResume) {
1542afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (DBG) {
1543afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                        log("onCallResumeFailed : switching " + mForegroundCall + " with "
1544afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                                + mBackgroundCall);
1545afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
1546afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    mForegroundCall.switchWith(mBackgroundCall);
1547afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    if (mForegroundCall.getState() == ImsPhoneCall.State.HOLDING) {
1548afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1549afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                    }
1550707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1551afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati
1552afb0fad639cdaff9abb4d405e039bd61cd8d3cb6Anju Mathapati                //Call swap is done, reset the relevant variables
1553276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1554276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1555276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1556276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mPhone.notifySuppServiceFailed(Phone.SuppService.RESUME);
15575054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumeFailed(imsCall.getCallSession(), reasonInfo);
1558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1561a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeReceived(ImsCall imsCall) {
1562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumeReceived");
1563ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
1564ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn            if (conn != null && mOnHoldToneStarted) {
1565ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                mPhone.stopOnHoldTone(conn);
1566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mOnHoldToneStarted = false;
1567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
156808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
156908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
157008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
157108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
157208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
157308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_RETRIEVED;
157408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
15755054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallResumeReceived(imsCall.getCallSession());
1576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldReceived(ImsCall imsCall) {
1580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldReceived");
1581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneConnection conn = findConnection(imsCall);
1583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn != null && conn.getState() == ImsPhoneCall.State.ACTIVE) {
1584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (!mOnHoldToneStarted && ImsPhoneCall.isLocalTone(imsCall)) {
1585ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mPhone.startOnHoldTone(conn);
1586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mOnHoldToneStarted = true;
1587ad03bd3454a9dd0e8edb61b8794f07d8a26f8187Tyler Gunn                    mOnHoldToneId = System.identityHashCode(conn);
1588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
159008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
159108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
159208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
159308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
159408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
159508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_ON_HOLD;
159608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
15975054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHoldReceived(imsCall.getCallSession());
159808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        }
159908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
160008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        @Override
160108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
160208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                ImsSuppServiceNotification suppServiceInfo) {
160308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (DBG) log("onCallSuppServiceReceived: suppServiceInfo=" + suppServiceInfo);
160408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
160508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
16068762e33ba987774e43aa9f4e216ebdb084d3a03eTyler Gunn            supp.notificationType = suppServiceInfo.notificationType;
160708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = suppServiceInfo.code;
160808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.index = suppServiceInfo.index;
160908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.number = suppServiceInfo.number;
161008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.history = suppServiceInfo.history;
161108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
161208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
1613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1616007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        public void onCallMerged(final ImsCall call, final ImsCall peerCall, boolean swapCalls) {
1617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallMerged");
1618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1619707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall foregroundImsPhoneCall = findConnection(call).getCall();
1620007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            ImsPhoneConnection peerConnection = findConnection(peerCall);
1621707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall peerImsPhoneCall = peerConnection == null ? null
1622707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    : peerConnection.getCall();
1623007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1624fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            if (swapCalls) {
1625007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                switchAfterConferenceSuccess();
1626fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            }
1627707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            foregroundImsPhoneCall.merge(peerImsPhoneCall, ImsPhoneCall.State.ACTIVE);
1628007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1629ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            try {
1630ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                final ImsPhoneConnection conn = findConnection(call);
1631ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: ImsPhoneConnection=" + conn);
1632ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1633ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                setVideoCallProvider(conn, call);
1634ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1635ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            } catch (Exception e) {
1636ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade                loge("onCallMerged: exception " + e);
1637ee275ae7d45847e3eb84ce7725df3717d3addee3Omkar Kolangade            }
1638288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1639007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // After merge complete, update foreground as Active
1640007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // and background call as Held, if background call exists
1641007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            processCallStateChange(mForegroundCall.getImsCall(), ImsPhoneCall.State.ACTIVE,
1642007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1643007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (peerConnection != null) {
1644007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                processCallStateChange(mBackgroundCall.getImsCall(), ImsPhoneCall.State.HOLDING,
1645007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1646007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1647df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon
1648007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // Check if the merge was requested by an existing conference call. In that
1649007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // case, no further action is required.
1650007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (!call.isMergeRequestedByConf()) {
1651007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: calling onMultipartyStateChanged()");
1652007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                onMultipartyStateChanged(call, true);
1653007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            } else {
1654007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: Merge requested by existing conference.");
1655007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                // Reset the flag.
1656007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                call.resetIsMergeRequestedByConf(false);
1657007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1658707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            logState();
1659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
16634e47e27d1d2cbd8e533cdd2081c5bc8e51b79ad9Anthony Lee            if (DBG) log("onCallMergeFailed reasonInfo=" + reasonInfo);
166452c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
166552c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // TODO: the call to notifySuppServiceFailed throws up the "merge failed" dialog
166652c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // We should move this into the InCallService so that it is handled appropriately
166752c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // based on the user facing UI.
1668bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
166952c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
167052c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // Start plumbing this even through Telecom so other components can take
167152c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // appropriate action.
167252c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            ImsPhoneConnection conn = findConnection(call);
167352c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            if (conn != null) {
167452c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee                conn.onConferenceMergeFailed();
167552c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            }
1676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1677fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1678fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        /**
1679f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
1680fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         *
1681fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         * @param call the call object that carries out the IMS call.
1682f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * @param participants the participant(s) and their new state information.
1683fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         */
1684fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        @Override
1685f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
1686f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                List<ConferenceParticipant> participants) {
1687f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn            if (DBG) log("onConferenceParticipantsStateChanged");
1688fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1689fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            ImsPhoneConnection conn = findConnection(call);
1690fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            if (conn != null) {
1691f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                conn.updateConferenceParticipants(participants);
1692fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            }
1693fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        }
16946d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak
16956d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        @Override
16966d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
16976d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak            mPhone.onTtyModeReceived(mode);
16986d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        }
16990ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
17000ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
17010ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
17020ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
17030ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
17040ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech=" +
17050ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    targetAccessTech + ", reasonInfo=" + reasonInfo);
17060ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
17075054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHandover(imsCall.getCallSession(),
17085054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    srcAccessTech, targetAccessTech, reasonInfo);
17090ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
17100ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
17110ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
17120ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
17130ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
17140ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
17150ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandoverFailed :: srcAccessTech=" + srcAccessTech +
17160ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" + reasonInfo);
17170ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
17185054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsCallHandoverFailed(imsCall.getCallSession(),
17195054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    srcAccessTech, targetAccessTech, reasonInfo);
17200ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
1721ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1722ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        /**
1723ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
1724ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * {@link ImsPhoneConnection} of the change.
1725ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *
1726ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param imsCall The IMS call.
1727ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
1728ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *      otherwise.
1729ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         */
1730ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        @Override
1731ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
1732ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (DBG) log("onMultipartyStateChanged to " + (isMultiParty ? "Y" : "N"));
1733ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1734ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
1735ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (conn != null) {
1736ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                conn.updateMultipartyState(isMultiParty);
1737ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            }
1738ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        }
1739a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1740a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1742a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1743a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1744a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsUssdListener = new ImsCall.Listener() {
1745a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1746a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1747a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStarted");
1748a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1749a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd);
1752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStartFailed reasonCode=" + reasonInfo.getCode());
1761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
1763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1765a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallTerminated reasonCode=" + reasonInfo.getCode());
1768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession = null;
1771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1772a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    CommandException ex =
1773a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            new CommandException(CommandException.Error.GENERIC_FAILURE);
1774a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd, null, ex);
1775a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1776a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1777a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1778a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imsCall.close();
1780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallUssdMessageReceived(ImsCall call,
1784a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                int mode, String ussdMessage) {
1785a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallUssdMessageReceived mode=" + mode);
1786a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1787a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int ussdMode = -1;
1788a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1789a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch(mode) {
1790a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_REQUEST:
1791a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_REQUEST;
1792a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_NOTIFY:
1795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_NOTIFY;
1796a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1797a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1798a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1799a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.onIncomingUSSD(ussdMode, ussdMessage);
1800a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1801a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1802a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1803a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1804a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS service state change
1805a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     *
1806a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1807a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsConnectionStateListener mImsConnectionStateListener =
1808a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        new ImsConnectionStateListener() {
1809a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1810a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsConnected() {
1811a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsConnected");
1812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1813bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(true);
18145054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
18155054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_CONNECTED, null);
1816a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1818a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
18190ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
18200ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);
1821a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1822bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(false);
182353f2bb9ba3118ff4c22e20ab3ad46ec97a72ac24Pavel Zhamaitsiak            mPhone.processDisconnectReason(imsReasonInfo);
18245054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
18255054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_DISCONNECTED, imsReasonInfo);
1826a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1827a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1828a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
18290ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsProgressing() {
18300ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsProgressing");
183108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
183208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setImsRegistered(false);
18335054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
18345054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_PROGRESSING, null);
18350ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
18360ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
18370ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
1838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsResumed() {
1839a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsResumed");
1840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
18415054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
18425054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_RESUMED, null);
1843a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1844a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1845a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1846a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsSuspended() {
1847a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsSuspended");
1848a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
18495054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak            mEventLog.writeOnImsConnectionState(
18505054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                    TelephonyEventLog.IMS_CONNECTION_STATE_SUSPENDED, null);
1851a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1852cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
1853cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        @Override
1854cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        public void onFeatureCapabilityChanged(int serviceClass,
1855cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                int[] enabledFeatures, int[] disabledFeatures) {
1856cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            if (serviceClass == ImsServiceClass.MMTEL) {
1857288268d5528e0df03f348e303954813cb188c55bRekha Kumar                boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
185804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
1859c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                StringBuilder sb;
1860c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
1861c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb = new StringBuilder(120);
1862c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    sb.append("onFeatureCapabilityChanged: ");
1863c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
186462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                for (int  i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
186508111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI &&
186608111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i < enabledFeatures.length; i++) {
186762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    if (enabledFeatures[i] == i) {
186804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // If the feature is set to its own integer value it is enabled.
1869c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
1870c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
1871c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":true ");
1872c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
1873c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
187462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = true;
187504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else if (enabledFeatures[i]
187604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                            == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
187704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled.
1878c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        if (DBG) {
1879c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(mImsFeatureStrings[i]);
1880c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            sb.append(":false ");
1881c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                        }
1882c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu
188362a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = false;
188404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else {
188504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // Feature has unknown state; it is not its own value or -1.
188604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        if (DBG) {
1887c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                            loge("onFeatureCapabilityChanged(" + i + ", " + mImsFeatureStrings[i]
1888c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                                    + "): unexpectedValue=" + enabledFeatures[i]);
188904b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        }
189062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    }
1891cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                }
1892c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                if (DBG) {
1893c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                    log(sb.toString());
1894c1b229b7389e4cd682452c8d662afa1b3af14345Jack Yu                }
1895288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {
1896288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
1897288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
189804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee
189904b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // TODO: Use the ImsCallSession or ImsCallProfile to tell the initial Wifi state and
190004b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // {@link ImsCallSession.Listener#callSessionHandover} to listen for changes to
190104b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // wifi capability caused by a handover.
1902164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                if (DBG) log("onFeatureCapabilityChanged: isVolteEnabled=" + isVolteEnabled()
1903164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVideoCallEnabled=" + isVideoCallEnabled()
1904164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVowifiEnabled=" + isVowifiEnabled()
1905164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isUtEnabled=" + isUtEnabled());
190604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                for (ImsPhoneConnection connection : mConnections) {
190704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    connection.updateWifiState();
190804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                }
1909e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak
1910e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak                mPhone.onFeatureCapabilityChanged();
19115054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak
19125054dfa7fd9b0520d30a102ed5a2107af11590c8Pavel Zhamaitsiak                mEventLog.writeOnImsCapabilities(mImsFeatureEnabled);
1913cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            }
1914cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        }
191503545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade
191603545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        @Override
191703545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        public void onVoiceMessageCountChanged(int count) {
191803545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            if (DBG) log("onVoiceMessageCountChanged :: count=" + count);
191903545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            mPhone.mDefaultPhone.setVoiceMessageCount(count);
192003545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        }
1921a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1922a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19239746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    private ImsConfigListener.Stub mImsConfigListener = new ImsConfigListener.Stub() {
19249746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
19259746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetFeatureResponse(int feature, int network, int value, int status) {}
19269746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
19279746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
19289746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetFeatureResponse(int feature, int network, int value, int status) {
19299746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak            mEventLog.writeImsSetFeatureValue(feature, network, value, status);
19309746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        }
19319746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
19329746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
19339746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onGetVideoQuality(int status, int quality) {}
19349746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
19359746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        @Override
19369746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak        public void onSetVideoQuality(int status) {}
19379746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
19389746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak    };
19399746fca2d7389f0fce6d5d031d87acd87b9de723Pavel Zhamaitsiak
194093c62c8a71821f46194e16ca3e84f95e101edb90Amit Mahajan    public ImsUtInterface getUtInterface() throws ImsException {
1941a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
1942cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
1943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration(mServiceId);
1946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ut;
1947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19494be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    private void transferHandoverConnections(ImsPhoneCall call) {
19504be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.mConnections != null) {
19514be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : call.mConnections) {
19524be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                c.mPreHandoverState = call.mState;
19534be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                log ("Connection state before handover is " + c.getStateBeforeHandover());
19544be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
19554be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
19564be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections == null ) {
19574be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections = call.mConnections;
19584be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        } else { // Multi-call SRVCC
19594be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections.addAll(call.mConnections);
19604be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
19614be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections != null) {
19624be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            if (call.getImsCall() != null) {
19634be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                call.getImsCall().close();
19644be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
19654be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : mHandoverCall.mConnections) {
19664be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                ((ImsPhoneConnection)c).changeParent(mHandoverCall);
196752c193f0c615a9153a702ea2597217202613e413Libin.Tang@motorola.com                ((ImsPhoneConnection)c).releaseWakeLock();
19684be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
19694be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
19704be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.getState().isAlive()) {
19714be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            log ("Call is alive and state is " + call.mState);
19724be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mState = call.mState;
19734be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
19744be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mConnections.clear();
19754be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mState = ImsPhoneCall.State.IDLE;
19764be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    }
19774be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam
1978a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1979a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void notifySrvccState(Call.SrvccState state) {
1980a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("notifySrvccState state=" + state);
1981a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1982a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mSrvccState = state;
1983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1984a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mSrvccState == Call.SrvccState.COMPLETED) {
19854be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mForegroundCall);
19864be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mBackgroundCall);
19874be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mRingingCall);
1988a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1989a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1990a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1991a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //****** Overridden from Handler
1992a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void
1995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleMessage (Message msg) {
1996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
1997a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("handleMessage what=" + msg.what);
1998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1999a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (msg.what) {
2000a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_HANGUP_PENDINGMO:
2001a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingMO != null) {
2002a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.onDisconnect();
2003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
2004a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
2005a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2006c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2007a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
2008a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.notifyPreciseCallStateChanged();
2009a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2010a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_RESUME_BACKGROUND:
2011a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
2012a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    resumeWaitingOrHolding();
2013a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (CallStateException e) {
2014a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (Phone.DEBUG_PHONE) {
2015a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e);
2016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
2017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
2018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
2019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_DIAL_PENDINGMO:
2020c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, mClirMode, mPendingCallVideoState, mPendingIntentExtras);
2021c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
2022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
202304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
2024e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati            case EVENT_EXIT_ECBM_BEFORE_PENDINGMO:
2025e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                if (mPendingMO != null) {
2026e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    //Send ECBM exit request
2027e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    try {
2028e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        getEcbmInterface().exitEmergencyCallbackMode();
2029e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
2030e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallClirMode = mClirMode;
2031e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        pendingCallInEcm = true;
2032e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    } catch (ImsException e) {
2033e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        e.printStackTrace();
2034e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
2035e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
2036e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                    }
2037e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                }
2038e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati                break;
2039e5c2995cec720cb3f0ba6609378574683770108dAnju Mathapati
204004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case EVENT_EXIT_ECM_RESPONSE_CDMA:
204104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // no matter the result, we still do the same here
204204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                if (pendingCallInEcm) {
2043288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    dialInternal(mPendingMO, pendingCallClirMode,
2044c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                            mPendingCallVideoState, mPendingIntentExtras);
2045c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                    mPendingIntentExtras = null;
204604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    pendingCallInEcm = false;
204704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
204804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.unsetOnEcbModeExitResponse(this);
204904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
205048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            case EVENT_VT_DATA_USAGE_UPDATE:
205148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ar = (AsyncResult) msg.obj;
205248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                ImsCall call = (ImsCall) ar.userObj;
205348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long usage = (long) ar.result;
205448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                log("VT data usage update. usage = " + usage + ", imsCall = " + call);
205548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
205648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                Long oldUsage = 0L;
205748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                if (mVtDataUsageMap.containsKey(call.uniqueId)) {
205848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    oldUsage = mVtDataUsageMap.get(call.uniqueId);
205948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                }
206048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mTotalVtDataUsage += (usage - oldUsage);
206148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                mVtDataUsageMap.put(call.uniqueId, usage);
206248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                break;
2063a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
2064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2065a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2066a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2067a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void log(String msg) {
2068a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2069a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2070a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2071a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void loge(String msg) {
2072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.e(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
2073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2075707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /**
2076707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * Logs the current state of the ImsPhoneCallTracker.  Useful for debugging issues with
2077707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * call tracking.
2078707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     */
2079707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /* package */
2080707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    void logState() {
2081707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        if (!VERBOSE_STATE_LOGGING) {
2082707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            return;
2083707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        }
2084707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2085707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        StringBuilder sb = new StringBuilder();
2086707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("Current IMS PhoneCall State:\n");
2087707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Foreground: ");
2088707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mForegroundCall);
2089707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2090707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Background: ");
2091707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mBackgroundCall);
2092707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2093707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Ringing: ");
2094707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mRingingCall);
2095707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2096707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Handover: ");
2097707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mHandoverCall);
2098707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
2099707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        Rlog.v(LOG_TAG, sb.toString());
2100707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    }
2101707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
2102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println("ImsPhoneCallTracker extends:");
2105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        super.dump(fd, pw, args);
2106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallEndedRegistrants=" + mVoiceCallEndedRegistrants);
2107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallStartedRegistrants=" + mVoiceCallStartedRegistrants);
2108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mRingingCall=" + mRingingCall);
2109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mForegroundCall=" + mForegroundCall);
2110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mBackgroundCall=" + mBackgroundCall);
2111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mHandoverCall=" + mHandoverCall);
2112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPendingMO=" + mPendingMO);
2113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //pw.println(" mHangupPendingMO=" + mHangupPendingMO);
2114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPhone=" + mPhone);
2115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mDesiredMute=" + mDesiredMute);
2116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mState=" + mState);
2117dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        for (int i = 0; i < mImsFeatureEnabled.length; i++) {
2118dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println(" " + mImsFeatureStrings[i] + ": "
2119dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                    + ((mImsFeatureEnabled[i]) ? "enabled" : "disabled"));
2120dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
212148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        pw.println(" mTotalVtDataUsage=" + mTotalVtDataUsage);
212248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        for (Map.Entry<Integer, Long> entry : mVtDataUsageMap.entrySet()) {
212348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            pw.println("    id=" + entry.getKey() + " ,usage=" + entry.getValue());
212448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
212548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
2126dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.flush();
2127dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        pw.println("++++++++++++++++++++++++++++++++");
2128dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2129dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        try {
2130dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            if (mImsManager != null) {
2131dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                mImsManager.dump(fd, pw, args);
2132dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2133dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        } catch (Exception e) {
2134dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            e.printStackTrace();
2135dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2136dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu
2137dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        if (mConnections != null && mConnections.size() > 0) {
2138dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            pw.println("mConnections:");
2139dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            for (int i = 0; i < mConnections.size(); i++) {
2140dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu                pw.println("  [" + i + "]: " + mConnections.get(i));
2141dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu            }
2142dc3b93d59312b84dcfa776f7691f6a87462b45a2Jack Yu        }
2143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
2144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
2145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
2146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void handlePollCalls(AsyncResult ar) {
2147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
214804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
214904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    /* package */
215004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    ImsEcbm getEcbmInterface() throws ImsException {
215104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (mImsManager == null) {
2152cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
215304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
215404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
215504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        ImsEcbm ecbm = mImsManager.getEcbmInterface(mServiceId);
215604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return ecbm;
215704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
215804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
215993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /* package */
216093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
216193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        if (mImsManager == null) {
2162cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak            throw getImsManagerIsNullException();
216393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
216493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
2165b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        try {
2166b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            return mImsManager.getMultiEndpointInterface(mServiceId);
2167b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        } catch (ImsException e) {
2168b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            if (e.getCode() == ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED) {
2169b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                return null;
2170b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            } else {
2171b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn                throw e;
2172b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn            }
2173b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn
2174b25b43f0497f1a476598a0277e109f786ed3f817Tyler Gunn        }
217593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
217693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
217704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    public boolean isInEmergencyCall() {
217804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return mIsInEmergencyCall;
217904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
2180cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2181cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    public boolean isVolteEnabled() {
218262a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE];
218362a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    }
218462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com
218562a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    public boolean isVowifiEnabled() {
218662a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI];
2187cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2188cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
2189288268d5528e0df03f348e303954813cb188c55bRekha Kumar    public boolean isVideoCallEnabled() {
219062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE]
219162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI]);
2192cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
2193288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2194b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    @Override
2195b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    public PhoneConstants.State getState() {
2196b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com        return mState;
2197b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    }
2198288268d5528e0df03f348e303954813cb188c55bRekha Kumar
2199288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private void setVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall)
2200288268d5528e0df03f348e303954813cb188c55bRekha Kumar            throws RemoteException {
2201288268d5528e0df03f348e303954813cb188c55bRekha Kumar        IImsVideoCallProvider imsVideoCallProvider =
2202288268d5528e0df03f348e303954813cb188c55bRekha Kumar                imsCall.getCallSession().getVideoCallProvider();
2203288268d5528e0df03f348e303954813cb188c55bRekha Kumar        if (imsVideoCallProvider != null) {
2204288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsVideoCallProviderWrapper imsVideoCallProviderWrapper =
2205288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    new ImsVideoCallProviderWrapper(imsVideoCallProvider);
2206288268d5528e0df03f348e303954813cb188c55bRekha Kumar            conn.setVideoProvider(imsVideoCallProviderWrapper);
220748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            imsVideoCallProviderWrapper.registerForDataUsageUpdate
220848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                    (this, EVENT_VT_DATA_USAGE_UPDATE, imsCall);
2209288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
2210288268d5528e0df03f348e303954813cb188c55bRekha Kumar    }
2211164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati
2212164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    public boolean isUtEnabled() {
2213164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE]
2214164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI]);
2215164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    }
2216d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2217d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
2218d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * Given a call subject, removes any characters considered by the current carrier to be
22195c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * invalid, as well as escaping (using \) any characters which the carrier requires to be
22205c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * escaped.
2221d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
2222d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * @param callSubject The call subject.
22235c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The call subject with invalid characters removed and escaping applied as required.
2224d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
22255c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String cleanseInstantLetteringMessage(String callSubject) {
22264677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        if (TextUtils.isEmpty(callSubject)) {
22274677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn            return callSubject;
22284677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        }
22294677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn
22305c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Get the carrier config for the current sub.
22315c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        CarrierConfigManager configMgr = (CarrierConfigManager)
22325c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
22335c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if we can't find the carrier config service.
22345c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (configMgr == null) {
2235d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn            return callSubject;
2236d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
2237d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
22385c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        PersistableBundle carrierConfig = configMgr.getConfigForSubId(mPhone.getSubId());
22395c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if no carrier config found.
22405c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (carrierConfig == null) {
22415c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            return callSubject;
22425c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
22435c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
22445c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to replace invalid characters
22455c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String invalidCharacters = carrierConfig.getString(
22465c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING);
22475c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(invalidCharacters)) {
22485c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = callSubject.replaceAll(invalidCharacters, "");
22495c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
22505c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
22515c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to escape characters which need to be escaped.
22525c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String escapedCharacters = carrierConfig.getString(
22535c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING);
22545c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(escapedCharacters)) {
22555c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = escapeChars(escapedCharacters, callSubject);
22565c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
22575c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return callSubject;
2258d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
2259d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
2260d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
22615c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * Given a source string, return a string where a set of characters are escaped using the
22625c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * backslash character.
2263d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
22645c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param toEscape The characters to escape with a backslash.
22655c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param source The source string.
22665c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The source string with characters escaped.
2267d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
22685c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String escapeChars(String toEscape, String source) {
22695c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        StringBuilder escaped = new StringBuilder();
22705c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        for (char c : source.toCharArray()) {
22715c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            if (toEscape.contains(Character.toString(c))) {
22725c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                escaped.append("\\");
22735c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            }
22745c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            escaped.append(c);
2275d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
22765c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
22775c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return escaped.toString();
2278d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
227993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn
228093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    /**
228193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull of an external call.
228293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
228393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Initiates a pull by making a dial request with the {@link ImsCallProfile#EXTRA_IS_CALL_PULL}
228493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * extra specified.  We call {@link ImsPhone#notifyUnknownConnection(Connection)} which notifies
228593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * Telecom of the new dialed connection.  The
228693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@code PstnIncomingCallNotifier#maybeSwapWithUnknownConnection} logic ensures that the new
228793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsPhoneConnection} resulting from the dial gets swapped with the
228893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * {@link ImsExternalConnection}, which effectively makes the external call become a regular
228993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * call.  Magic!
229093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     *
229193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param number The phone number of the call to be pulled.
229293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     * @param videoState The desired video state of the pulled call.
229393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn     */
229493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    @Override
229593da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    public void pullExternalCall(String number, int videoState) {
229693da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        Bundle extras = new Bundle();
229793da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        extras.putBoolean(ImsCallProfile.EXTRA_IS_CALL_PULL, true);
229893da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        try {
229993da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            Connection connection = dial(number, videoState, extras);
230093da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            mPhone.notifyUnknownConnection(connection);
230193da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        } catch (CallStateException e) {
230293da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn            loge("pullExternalCall failed - " + e);
230393da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn        }
230493da8529345711fd1a5617f3c8b15c0921eececbTyler Gunn    }
2305cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak
2306cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    private ImsException getImsManagerIsNullException() {
2307cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak        return new ImsException("no ims manager", ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
2308cf3a2925c10f87f4b6af0f3a1c369f57954f7733Pavel Zhamaitsiak    }
230937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
231037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    /**
231137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * Determines if answering an incoming call will cause the active call to be disconnected.
231237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * <p>
231337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * This will be the case if
231437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@link CarrierConfigManager#KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL} is
231537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * {@code true} for the carrier, the active call is a video call over WIFI, and the incoming
231637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * call is an audio call.
231737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *
231837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param activeCall The active call.
231937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @param incomingCall The incoming call.
232037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     * @return {@code true} if answering the incoming call will cause the active call to be
232137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     *      disconnected, {@code false} otherwise.
232237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn     */
232337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    private boolean shouldDisconnectActiveCallOnAnswer(ImsCall activeCall,
232437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            ImsCall incomingCall) {
232537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
232637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        if (!mDropVideoCallWhenAnsweringAudioCall) {
232737c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn            return false;
232837c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        }
232937c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
233037c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallVideo = activeCall.isVideoCall() ||
233137c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn                (mTreatDowngradedVideoCallsAsVideoCalls && activeCall.wasVideoCall());
233237c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isActiveCallOnWifi = activeCall.isWifiCall();
233337c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        boolean isIncomingCallAudio = !incomingCall.isVideoCall();
233437c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn
233537c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn        return isActiveCallVideo && isActiveCallOnWifi && isIncomingCallAudio;
233637c0d71f5221943f25a36613d52618b37126d1c2Tyler Gunn    }
233748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
233848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    /** Get aggregated video call data usage since boot.
233948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     *
234048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     * @return data usage in bytes
234148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu     */
234248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    public long getVtDataUsage() {
234348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
234448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // If there is an ongoing VT call, request the latest VT usage from the modem. The latest
234548921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // usage will return asynchronously so it won't be counted in this round, but it will be
234648921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        // eventually counted when next getVtDataUsage is called.
234748921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        if (mState != PhoneConstants.State.IDLE) {
234848921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            for (ImsPhoneConnection conn : mConnections) {
234948921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu                conn.getVideoProvider().onRequestConnectionDataUsage();
235048921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu            }
235148921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        }
235248921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu
235348921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu        return mTotalVtDataUsage;
235448921d863bf4d93c89071dfde4d44cd27fec6314Jack Yu    }
2355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
2356