ImsPhoneCallTracker.java revision 08111609eb4e838de7bff4960bbbd7f9c54a060e
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;
2204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport java.util.List;
2304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
24a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.app.PendingIntent;
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.BroadcastReceiver;
26a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Intent;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.IntentFilter;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.SharedPreferences;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
31df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordonimport android.os.Bundle;
32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
34d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.os.PersistableBundle;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
36a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.RegistrantList;
37ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport android.os.RemoteException;
38a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemProperties;
39b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganeshimport android.provider.Settings;
40d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.telephony.CarrierConfigManager;
41d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunnimport android.text.TextUtils;
4208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport android.widget.Toast;
435c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunnimport android.telephony.CarrierConfigManager;
445c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunnimport android.text.TextUtils;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.preference.PreferenceManager;
46fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunnimport android.telecom.ConferenceParticipant;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
5004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport android.telephony.ServiceState;
51a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
5204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCall;
5304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsCallProfile;
54cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.comimport com.android.ims.ImsConfig;
5504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsConnectionStateListener;
5604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsEcbm;
5704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsException;
5804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsManager;
5904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsReasonInfo;
6004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsServiceClass;
6108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.ims.ImsSuppServiceNotification;
6204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingamimport com.android.ims.ImsUtInterface;
63ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.IImsVideoCallProvider;
64ea8cb63201520592011a92849ad3661d22776c87Andrew Leeimport com.android.ims.internal.ImsVideoCallProviderWrapper;
65a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Call;
66a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallTracker;
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandException;
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandsInterface;
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneBase;
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.TelephonyProperties;
7508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganeshimport com.android.internal.telephony.gsm.SuppServiceNotification;
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic final class ImsPhoneCallTracker extends CallTracker {
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ImsPhoneCallTracker";
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
85707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // When true, dumps the state of ImsPhoneCallTracker after changes to foreground and background
86707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    // calls.  This is helpful for debugging.
87707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    private static final boolean VERBOSE_STATE_LOGGING = false; /* stopship if true */
88707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
89915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold    //Indices map to ImsConfig.FeatureConstants
90164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private boolean[] mImsFeatureEnabled = {false, false, false, false, false, false};
91164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    private final String[] mImsFeatureStrings = {"VoLTE", "ViLTE", "VoWiFi", "ViWiFi",
92164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            "UTLTE", "UTWiFi"};
93cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
94a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
95a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
96a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onReceive(Context context, Intent intent) {
97a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (intent.getAction().equals(ImsManager.ACTION_IMS_INCOMING_CALL)) {
98a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (DBG) log("onReceive : incoming call intent");
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mImsManager == null) return;
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mServiceId < 0) return;
103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Network initiated USSD will be treated by mImsUssdListener
106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    boolean isUssd = intent.getBooleanExtra(ImsManager.EXTRA_USSD, false);
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (isUssd) {
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (DBG) log("onReceive : USSD");
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mUssdSession = mImsManager.takeCall(mServiceId, intent, mImsUssdListener);
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mUssdSession != null) {
1112999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                            mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        return;
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
11608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    boolean isUnknown = intent.getBooleanExtra(ImsManager.EXTRA_IS_UNKNOWN_CALL,
11708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            false);
11808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (DBG) {
11908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        log("onReceive : isUnknown = " + isUnknown +
12008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " fg = " + mForegroundCall.getState() +
12108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                " bg = " + mBackgroundCall.getState());
12208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
12308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
12408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Normal MT/Unknown call
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);
1266bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone, imsCall,
12708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            ImsPhoneCallTracker.this,
12808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            (isUnknown? mForegroundCall: mRingingCall), isUnknown);
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    addConnection(conn);
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
131288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    setVideoCallProvider(conn, imsCall);
132ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
13308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    if (isUnknown) {
13408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyUnknownConnection(conn);
13508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    } else {
13608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) ||
13708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                                (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE)) {
13808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                            conn.update(imsCall, ImsPhoneCall.State.WAITING);
13908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        }
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
14108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyNewRingingConnection(conn);
14208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                        mPhone.notifyIncomingRing();
14308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    }
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    updatePhoneState();
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyPreciseCallStateChanged();
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (ImsException e) {
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    loge("onReceive : exception " + e);
149ea8cb63201520592011a92849ad3661d22776c87Andrew Lee                } catch (RemoteException e) {
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS = 7;
158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5;
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_HANGUP_PENDINGMO = 18;
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_RESUME_BACKGROUND = 19;
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DIAL_PENDINGMO = 20;
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int TIMEOUT_HANGUP_PENDINGMO = 500;
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ArrayList<ImsPhoneConnection> mConnections = new ArrayList<ImsPhoneConnection>();
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallEndedRegistrants = new RegistrantList();
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallStartedRegistrants = new RegistrantList();
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
171707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    final ImsPhoneCall mRingingCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_RINGING);
172707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    final ImsPhoneCall mForegroundCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_FOREGROUND);
173707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    final ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_BACKGROUND);
174707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    final ImsPhoneCall mHandoverCall = new ImsPhoneCall(this, ImsPhoneCall.CONTEXT_HANDOVER);
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneConnection mPendingMO;
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mClirMode = CommandsInterface.CLIR_DEFAULT;
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Object mSyncHold = new Object();
179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mUssdSession = null;
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Message mPendingUssd = null;
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhone mPhone;
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDesiredMute = false;    // false = mute off
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mOnHoldToneStarted = false;
187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    PhoneConstants.State mState = PhoneConstants.State.IDLE;
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsManager mImsManager;
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mServiceId = -1;
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean mIsInEmergencyCall = false;
19604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
19704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private int pendingCallClirMode;
198288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private int mPendingCallVideoState;
199c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private Bundle mPendingIntentExtras;
20004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private boolean pendingCallInEcm = false;
201276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private boolean mSwitchingFgAndBgCalls = false;
202276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn    private ImsCall mCallExpectedToResume = null;
20304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Events
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCallTracker(ImsPhone phone) {
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        this.mPhone = phone;
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        IntentFilter intentfilter = new IntentFilter();
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().registerReceiver(mReceiver, intentfilter);
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Thread t = new Thread() {
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            public void run() {
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                getImsService();
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        };
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        t.start();
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PendingIntent createIncomingCallPendingIntent() {
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
226a89314bcc94c43512299131609feea0c2c8167cfLibin.Tang@motorola.com        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                PendingIntent.FLAG_UPDATE_CURRENT);
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void getImsService() {
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("getImsService");
23353dde7e076954c250e55d156cc1df1202c3a8a9eEtan Cohen        mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId());
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mServiceId = mImsManager.open(ImsServiceClass.MMTEL,
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    createIncomingCallPendingIntent(),
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mImsConnectionStateListener);
23804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
23904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            // Get the ECBM interface and set IMSPhone's listener object for notifications
24004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            getEcbmInterface().setEcbmStateListener(mPhone.mImsEcbmStateListener);
24104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if (mPhone.isInEcm()) {
24204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // Call exit ECBM which will invoke onECBMExited
24304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.exitEmergencyCallbackMode();
24404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
245b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            int mPreferredTtyMode = Settings.Secure.getInt(
246b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                mPhone.getContext().getContentResolver(),
247b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                Settings.Secure.PREFERRED_TTY_MODE,
248b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh                Phone.TTY_MODE_OFF);
249f1099a9dfe0250a6b343de0646413db4034381deEtan Cohen           mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, mPreferredTtyMode, null);
250b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("getImsService: " + e);
253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Leave mImsManager as null, then CallStateException will be thrown when dialing
254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mImsManager = null;
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dispose");
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.dispose();
261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.dispose();
262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.dispose();
263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.dispose();
264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().unregisterReceiver(mReceiver);
267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void finalize() {
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("ImsPhoneCallTracker finalized");
272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Methods
275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Public Methods
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.add(r);
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.remove(h);
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.add(r);
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.remove(h);
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    Connection
300df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon    dial(String dialString, int videoState, Bundle intentExtras) throws CallStateException {
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int oirMode = sp.getInt(PhoneBase.CLIR_KEY, CommandsInterface.CLIR_DEFAULT);
303df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon        return dial(dialString, oirMode, videoState, intentExtras);
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * oirMode is one of the CLIR_ constants
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    synchronized Connection
310df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon    dial(String dialString, int clirMode, int videoState, Bundle intentExtras)
311df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon            throws CallStateException {
31204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        boolean isPhoneInEcmMode = SystemProperties.getBoolean(
31304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                TelephonyProperties.PROPERTY_INECM_MODE, false);
31404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        boolean isEmergencyNumber = PhoneNumberUtils.isEmergencyNumber(dialString);
31504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dial clirMode=" + clirMode);
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // note that this triggers call state changed notif
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("service not available");
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!canDial()) {
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot dial in current state");
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
32904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (isPhoneInEcmMode && isEmergencyNumber) {
33004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            handleEcmTimer(ImsPhone.CANCEL_ECM_TIMER);
33104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
33204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
333a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean holdBeforeDial = false;
334a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
335a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // The new call must be assigned to the foreground call.
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // That call must be idle, so place anything that's
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // there on hold
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
340a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we should have failed in !canDial() above before we get here
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot dial in current state");
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // foreground call is empty for the newly dialed connection
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            holdBeforeDial = true;
345288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache the video state for pending MO call.
346288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
347c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            mPendingIntentExtras = intentExtras;
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
353a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
354a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mClirMode = clirMode;
355a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
356a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mSyncHold) {
357a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (holdBeforeDial) {
358a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                fgState = mForegroundCall.getState();
359a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                bgState = mBackgroundCall.getState();
360a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call failed
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (fgState == ImsPhoneCall.State.ACTIVE) {
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("cannot dial in current state");
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call succeeded
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (bgState == ImsPhoneCall.State.HOLDING) {
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    holdBeforeDial = false;
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
3726bb557b243f3fc9984b82319026519608ada2c9cRoshan Pius            mPendingMO = new ImsPhoneConnection(mPhone,
3738bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    checkForTestEmergencyNumber(dialString), this, mForegroundCall,
3748bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyNumber);
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        addConnection(mPendingMO);
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!holdBeforeDial) {
37904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            if ((!isPhoneInEcmMode) || (isPhoneInEcmMode && isEmergencyNumber)) {
380c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, clirMode, videoState, intentExtras);
38104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            } else {
38204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                try {
38304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    getEcbmInterface().exitEmergencyCallbackMode();
38404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                } catch (ImsException e) {
38504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    e.printStackTrace();
38604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    throw new CallStateException("service not available");
38704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
38804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
38904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallClirMode = clirMode;
390288268d5528e0df03f348e303954813cb188c55bRekha Kumar                mPendingCallVideoState = videoState;
39104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                pendingCallInEcm = true;
39204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            }
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mPendingMO;
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
40104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    private void handleEcmTimer(int action) {
40204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        mPhone.handleTimerInEmergencyCallbackMode(action);
40304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        switch (action) {
40404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.CANCEL_ECM_TIMER:
40504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
40604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case ImsPhone.RESTART_ECM_TIMER:
40704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
40804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            default:
40904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                log("handleEcmTimer, unsupported action " + action);
41004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
41104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
41204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
413c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn    private void dialInternal(ImsPhoneConnection conn, int clirMode, int videoState,
414c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            Bundle intentExtras) {
415c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getAddress()== null || conn.getAddress().length() == 0
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Phone number is invalid
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Always unmute when initiating a new call
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setMute(false);
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
4316bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
43264e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
43364e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
43464e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        conn.setVideoState(videoState);
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { conn.getAddress() };
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
4396bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                    serviceType, callType);
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
442c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // Translate call subject intent-extra from Telecom-specific extra key to the
443c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            // ImsCallProfile key.
444c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn            if (intentExtras != null) {
445c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                if (intentExtras.containsKey(android.telecom.TelecomManager.EXTRA_CALL_SUBJECT)) {
446c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                    intentExtras.putString(ImsCallProfile.EXTRA_DISPLAY_TEXT,
4475c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                            cleanseInstantLetteringMessage(intentExtras.getString(
448d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                                    android.telecom.TelecomManager.EXTRA_CALL_SUBJECT))
449d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn                    );
450c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                }
451c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
452c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // Pack the OEM-specific call extras.
453c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                profile.mCallExtras.putBundle(ImsCallProfile.EXTRA_OEM_EXTRAS, intentExtras);
454c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn
455c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // NOTE: Extras to be sent over the network are packed into the
456c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // intentExtras individually, with uniquely defined keys.
457c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // These key-value pairs are processed by IMS Service before
458c02d6b7f2f48a291b42892424e6858f71c3d84a9Tyler Gunn                // being sent to the lower layers/to the network.
459c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn            }
460c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mImsManager.makeCall(mServiceId, profile,
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsCallListener);
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setImsCall(imsCall);
464ea8cb63201520592011a92849ad3661d22776c87Andrew Lee
465288268d5528e0df03f348e303954813cb188c55bRekha Kumar            setVideoCallProvider(conn, imsCall);
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("dialInternal : " + e);
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
470ea8cb63201520592011a92849ad3661d22776c87Andrew Lee        } catch (RemoteException e) {
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
4742999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    /**
4752999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * Accepts a call with the specified video state.  The video state is the video state that the
4762999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * user has agreed upon in the InCall UI.
4772999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     *
4782999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @param videoState The video State
4792999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @throws CallStateException
4802999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     */
4812999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    void acceptCall (int videoState) throws CallStateException {
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("acceptCall");
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState().isAlive()
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mBackgroundCall.getState().isAlive()) {
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot accept call");
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING)
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mForegroundCall.getState().isAlive()) {
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
492288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // Cache video state for pending MT call.
493288268d5528e0df03f348e303954813cb188c55bRekha Kumar            mPendingCallVideoState = videoState;
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mRingingCall.getState().isRinging()) {
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("acceptCall: incoming...");
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Always unmute when answering a new call
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) {
5022999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                    imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("no valid ims call");
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot accept call");
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    rejectCall () throws CallStateException {
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("rejectCall");
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState().isRinging()) {
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            hangup(mRingingCall);
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
525007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
526007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    private void switchAfterConferenceSuccess() {
527007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (DBG) log("switchAfterConferenceSuccess fg =" + mForegroundCall.getState() +
528007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                ", bg = " + mBackgroundCall.getState());
529007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
530007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
531007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            log("switchAfterConferenceSuccess");
532007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            mForegroundCall.switchWith(mBackgroundCall);
533007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        }
534007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam    }
535007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    switchWaitingOrHoldingAndActive() throws CallStateException {
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("switchWaitingOrHoldingAndActive");
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState() == ImsPhoneCall.State.INCOMING) {
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot be in the incoming state");
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mForegroundCall.getImsCall();
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == null) {
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("no ims call");
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
550276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Swap the ImsCalls pointed to by the foreground and background ImsPhoneCalls.
551276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If hold or resume later fails, we will swap them back.
552276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mSwitchingFgAndBgCalls = true;
553276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mCallExpectedToResume = mBackgroundCall.getImsCall();
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.switchWith(mBackgroundCall);
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
556276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // Hold the foreground call; once the foreground call is held, the background call will
557276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // be resumed.
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                imsCall.hold();
560707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
561707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                // If there is no background call to resume, then don't expect there to be a switch.
562707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mCallExpectedToResume == null) {
563707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    mSwitchingFgAndBgCalls = false;
564707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mForegroundCall.switchWith(mBackgroundCall);
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException(e.getMessage());
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            resumeWaitingOrHolding();
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    conference() {
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("conference");
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall fgImsCall = mForegroundCall.getImsCall();
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (fgImsCall == null) {
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no foreground ims call");
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall bgImsCall = mBackgroundCall.getImsCall();
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (bgImsCall == null) {
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no background ims call");
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
590fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // Keep track of the connect time of the earliest call so that it can be set on the
591fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        // {@code ImsConference} when it is created.
5927ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long foregroundConnectTime = mForegroundCall.getEarliestConnectTime();
5937ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long backgroundConnectTime = mBackgroundCall.getEarliestConnectTime();
5947ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        long conferenceConnectTime;
5957ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        if (foregroundConnectTime > 0 && backgroundConnectTime > 0) {
5967ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = Math.min(mForegroundCall.getEarliestConnectTime(),
5977ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn                    mBackgroundCall.getEarliestConnectTime());
5987ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - using connect time = " + conferenceConnectTime);
5997ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else if (foregroundConnectTime > 0) {
6007ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - bg call connect time is 0; using fg = " + foregroundConnectTime);
6017ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = foregroundConnectTime;
6027ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        } else {
6037ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            log("conference - fg call connect time is 0; using bg = " + backgroundConnectTime);
6047ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn            conferenceConnectTime = backgroundConnectTime;
6057ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn        }
6067ee3f31d9670662a3d4a652860396340b386c29eTyler Gunn
607fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        ImsPhoneConnection foregroundConnection = mForegroundCall.getFirstConnection();
608fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        if (foregroundConnection != null) {
609fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            foregroundConnection.setConferenceConnectTime(conferenceConnectTime);
610fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn        }
611fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn
612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            fgImsCall.merge(bgImsCall);
614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference " + e.getMessage());
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
620a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    explicitCallTransfer() {
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //TODO : implement
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
625a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clearDisconnected() {
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("clearDisconnected");
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        internalClearDisconnected();
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canConference() {
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING
638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mBackgroundCall.isFull()
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mForegroundCall.isFull();
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canDial() {
644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean ret;
645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceState = mPhone.getServiceState().getState();
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        String disableCall = SystemProperties.get(
647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mPendingMO == null
651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mRingingCall.isRinging()
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !disableCall.equals("true")
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && (!mForegroundCall.getState().isAlive()
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    || !mBackgroundCall.getState().isAlive());
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ret;
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canTransfer() {
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING;
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Private Instance Methods
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
667a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    internalClearDisconnected() {
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.clearDisconnected();
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.clearDisconnected();
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.clearDisconnected();
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.clearDisconnected();
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    updatePhoneState() {
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PhoneConstants.State oldState = mState;
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.isRinging()) {
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.RINGING;
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPendingMO != null ||
682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())) {
683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.OFFHOOK;
684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.IDLE;
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState == PhoneConstants.State.IDLE && oldState != mState) {
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallEndedRegistrants.notifyRegistrants(
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallStartedRegistrants.notifyRegistrants (
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
696a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("updatePhoneState oldState=" + oldState + ", newState=" + mState);
697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState != oldState) {
699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPhoneStateChanged();
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleRadioNotAvailable() {
705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // handlePollCalls will clear out its
706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // call list when it gets the CommandException
707a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // error result from this
708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pollCallsWhenSafe();
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    dumpState() {
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        List l;
714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
715a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Phone State:" + mState);
716a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
717a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Ringing call: " + mRingingCall.toString());
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mRingingCall.getConnections();
720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
721a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
723a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Foreground call: " + mForegroundCall.toString());
725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mForegroundCall.getConnections();
727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
728a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Background call: " + mBackgroundCall.toString());
732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mBackgroundCall.getConnections();
734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
738a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
739a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
740a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhone
741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
742b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh    void setUiTTYMode(int uiTtyMode, Message onComplete) {
743b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        try {
744f1099a9dfe0250a6b343de0646413db4034381deEtan Cohen            mImsManager.setUiTTYMode(mPhone.getContext(), mServiceId, uiTtyMode, onComplete);
745b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        } catch (ImsException e) {
746b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            loge("setTTYMode : " + e);
747b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh            mPhone.sendErrorResponse(onComplete, e);
748b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh        }
749b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh    }
750b7aff911e1106eb2eb16fd2bafae0ed8f4d4d4f7Shriram Ganesh
751d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee    /*package*/ void setMute(boolean mute) {
752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDesiredMute = mute;
753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.setMute(mute);
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
756d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee    /*package*/ boolean getMute() {
757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDesiredMute;
758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
760d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee    /* package */ void sendDtmf(char c, Message result) {
761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendDtmf");
762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imscall = mForegroundCall.getImsCall();
764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imscall != null) {
765d9aa1a75304b1c04c352198b9269f40a2a059f74Andrew Lee            imscall.sendDtmf(c, result);
766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
769c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    /*package*/ void
770c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    startDtmf(char c) {
771c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("startDtmf");
772c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
773c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
774c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
775c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.startDtmf(c);
776c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
777c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("startDtmf : no foreground call");
778c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
779c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
780c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
781c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    /*package*/ void
782c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    stopDtmf() {
783c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (DBG) log("stopDtmf");
784c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
785c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        ImsCall imscall = mForegroundCall.getImsCall();
786c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        if (imscall != null) {
787c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            imscall.stopDtmf();
788c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        } else {
789c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam            loge("stopDtmf : no foreground call");
790c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam        }
791c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam    }
792c204cc0f515864b36187d60f6ab79af28885d36eUma Maheswari Ramalingam
793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneConnection
794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
796a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    hangup (ImsPhoneConnection conn) throws CallStateException {
797a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup connection");
798a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
799a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getOwner() != this) {
800a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("ImsPhoneConnection " + conn
801a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "does not belong to ImsPhoneCallTracker " + this);
802a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
803a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
804a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        hangup(conn.getCall());
805a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
806a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
807a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneCall
808a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
809a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */ void
810a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    hangup (ImsPhoneCall call) throws CallStateException {
811a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup call");
812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
813a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call.getConnections().size() == 0) {
814a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("no connections");
815a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
816a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imsCall = call.getImsCall();
818a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean rejectCall = false;
819a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
820a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call == mRingingCall) {
821a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
822a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            rejectCall = true;
823a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mForegroundCall) {
824a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (call.isDialingOrAlerting()) {
825a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
826a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup dialing or alerting...");
827a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
828a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
829a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
830a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup foreground");
831a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
832a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //held call will be resumed by onCallTerminated
833a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
834a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mBackgroundCall) {
835a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) {
836a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("(backgnd) hangup waiting or background");
837a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
839ac82d4da0473991006a752e2337ccb93e85f0946Etan Cohen            throw new CallStateException ("ImsPhoneCall " + call +
840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    "does not belong to ImsPhoneCallTracker " + this);
841a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
842a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
843a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        call.onHangupLocal();
844a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
845a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
846a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall != null) {
847a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (rejectCall) imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE);
848a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                else imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
849a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mPendingMO != null && call == mForegroundCall) {
850a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // is holding a foreground call
851a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED);
852a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.onDisconnect();
853a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeConnection(mPendingMO);
854a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
855a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
856a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeMessages(EVENT_DIAL_PENDINGMO);
857a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
858a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
859a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
860a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
861a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
862a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
863a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
864a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
86569e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    void callEndCleanupHandOverCallIfAny() {
86669e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        if (mHandoverCall.mConnections.size() > 0) {
86769e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            if (DBG) log("callEndCleanupHandOverCallIfAny, mHandoverCall.mConnections="
86869e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com                    + mHandoverCall.mConnections);
86969e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mHandoverCall.mConnections.clear();
87069e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com            mState = PhoneConstants.State.IDLE;
87169e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com        }
87269e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com    }
87369e989aceb5660b39932049daad2299f75f07201Libin.Tang@motorola.com
874a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
875a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void resumeWaitingOrHolding() throws CallStateException {
876a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("resumeWaitingOrHolding");
877a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
878a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
879a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getState().isAlive()) {
880a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //resume foreground call after holding background call
881a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //they were switched before holding
882a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mForegroundCall.getImsCall();
883a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) imsCall.resume();
884a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
885a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //accept waiting call after holding background call
886a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
887288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (imsCall != null) {
888288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    imsCall.accept(
889288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        ImsCallProfile.getCallTypeFromVideoState(mPendingCallVideoState));
890288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
891a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
892a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //Just resume background call.
893a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //To distinguish resuming call with swapping calls
894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we do not switch calls.here
895a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //ImsPhoneConnection.update will chnage the parent when completed
896a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mBackgroundCall.getImsCall();
897a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) imsCall.resume();
898a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
899a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
900a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
901a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
902a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
903a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
904a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
905a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void sendUSSD (String ussdString, Message response) {
906a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendUSSD");
907a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
908a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
909a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mUssdSession != null) {
910a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession.sendUssd(ussdString);
911a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                AsyncResult.forMessage(response, null, null);
912a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                response.sendToTarget();
913a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
914a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
915a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
916a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { ussdString };
917a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
918a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE);
919a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_DIALSTRING,
920a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.DIALSTRING_USSD);
921a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
922a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession = mImsManager.makeCall(mServiceId, profile,
923a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsUssdListener);
924a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
925a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("sendUSSD : " + e);
926a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.sendErrorResponse(response, e);
927a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
928a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
929a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
930a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
931a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void cancelUSSD() {
932a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUssdSession == null) return;
933a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
934a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
938a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
939a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
940a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
941288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private synchronized ImsPhoneConnection findConnection(final ImsCall imsCall) {
942a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (ImsPhoneConnection conn : mConnections) {
943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getImsCall() == imsCall) {
944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return conn;
945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void removeConnection(ImsPhoneConnection conn) {
951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.remove(conn);
9528bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        // If not emergency call is remaining, notify emergency call registrants
9538bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (mIsInEmergencyCall) {
9548bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            boolean isEmergencyCallInList = false;
9558bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            // if no emergency calls pending, set this to false
9568bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            for (ImsPhoneConnection imsPhoneConnection : mConnections) {
9578bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                if (imsPhoneConnection != null && imsPhoneConnection.isEmergency() == true) {
9588bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    isEmergencyCallInList = true;
9598bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                    break;
9608bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan                }
9618bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            }
9628bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan
9638bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            mIsInEmergencyCall = isEmergencyCallInList;
9648bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
966a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
967a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void addConnection(ImsPhoneConnection conn) {
968a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.add(conn);
9698bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        if (conn.isEmergency()) {
9708bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan            mIsInEmergencyCall = true;
9718bfa1b42f0ffebf33239546ceaf5d6f5ca813191Amit Mahajan        }
972a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
9750db65ec818e58fb5b83a492e082db4536f3b83e0Tyler Gunn        if (DBG) log("processCallStateChange " + imsCall + " state=" + state + " cause=" + cause);
976d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // This method is called on onCallUpdate() where there is not necessarily a call state
977d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // change. In these situations, we'll ignore the state related updates and only process
978d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // the change in media capabilities (as expected).  The default is to not ignore state
979d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // changes so we do not change existing behavior.
980d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        processCallStateChange(imsCall, state, cause, false /* do not ignore state update */);
981d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    }
982d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati
983d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause,
984d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            boolean ignoreState) {
985d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (DBG) {
986d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati            log("processCallStateChange state=" + state + " cause=" + cause
987d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                    + " ignoreState=" + ignoreState);
988d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        }
989a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
990a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imsCall == null) return;
991a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
992a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneConnection conn = findConnection(imsCall);
994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : what should be done?
997a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
999a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1000d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // processCallStateChange is triggered for onCallUpdated as well.
1001d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // onCallUpdated should not modify the state of the call
1002d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // It should modify only other capabilities of call through updateMediaCapabilities
1003d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // State updates will be triggered through individual callbacks
1004d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        // i.e. onCallHeld, onCallResume, etc and conn.update will be responsible for the update
1005d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati        if (ignoreState) {
1006d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            conn.updateMediaCapabilities(imsCall);
100721048a2bc97d932a3ddecdfd79003a03f34263ecNivedita Sarkar            conn.updateExtras(imsCall);
1008d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            return;
1009d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        }
1010d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn
1011d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        changed = conn.update(imsCall, state);
1012d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn        if (state == ImsPhoneCall.State.DISCONNECTED) {
1013d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            changed = conn.onDisconnect(cause) || changed;
1014d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            //detach the disconnected connections
1015d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            conn.getCall().detach(conn);
1016d8413260e889d5b4db43e652304553ed29fa3e41Tyler Gunn            removeConnection(conn);
1017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (changed) {
1020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getCall() == mHandoverCall) return;
1021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
1022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
1023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1026a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int getDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
1027a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int cause = DisconnectCause.ERROR_UNSPECIFIED;
1028a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1029a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //int type = reasonInfo.getReasonType();
1030a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int code = reasonInfo.getCode();
1031a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (code) {
1032a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_ADDRESS:
1033a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_REACHABLE:
1034a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NUMBER_UNREACHABLE;
1035a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1036a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BUSY:
1037a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.BUSY;
1038a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1039a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED:
1040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.LOCAL;
1041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
10423b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com            case ImsReasonInfo.CODE_LOCAL_CALL_DECLINE:
10433b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                return DisconnectCause.INCOMING_REJECTED;
10443b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com
1045a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE:
1046a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NORMAL;
1047a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1048a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REDIRECTED:
1049a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_REQUEST:
1050a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_FORBIDDEN:
1051a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE:
1052a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_USER_REJECTED:
1053a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_GLOBAL_ERROR:
1054a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_ERROR;
1055a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1056a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE:
1057a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_FOUND:
1058a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVER_ERROR:
1059a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_UNREACHABLE;
1060a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1061a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING:
1062a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED:
1063a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN:
1064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE:
1065a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED:
1066a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE:
1067a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE:
1068a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING:
1069a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.OUT_OF_SERVICE;
1070a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1071a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT:
1072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING:
1073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER:
1074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE:
1075a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.TIMED_OUT;
1076a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1077a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_LOW_BATTERY:
1078a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_POWER_OFF:
1079a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.POWER_OFF;
1080a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
108108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            case ImsReasonInfo.CODE_FDN_BLOCKED:
108208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                return DisconnectCause.FDN_BLOCKED;
1083a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            default:
1084a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1085a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1086a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return cause;
1087a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1088a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1089a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1090a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1091a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1092a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsCallListener = new ImsCall.Listener() {
1093a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1094a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallProgressing(ImsCall imsCall) {
1095a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallProgressing");
1096a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1097a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ALERTING,
1099a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStarted");
1105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
1107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1111288268d5528e0df03f348e303954813cb188c55bRekha Kumar        @Override
1112288268d5528e0df03f348e303954813cb188c55bRekha Kumar        public void onCallUpdated(ImsCall imsCall) {
1113288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (DBG) log("onCallUpdated");
1114288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (imsCall == null) {
1115288268d5528e0df03f348e303954813cb188c55bRekha Kumar                return;
1116288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1117288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsPhoneConnection conn = findConnection(imsCall);
1118288268d5528e0df03f348e303954813cb188c55bRekha Kumar            if (conn != null) {
1119288268d5528e0df03f348e303954813cb188c55bRekha Kumar                processCallStateChange(imsCall, conn.getCall().mState,
1120d9c3a08d5958e5ced0c0c9f7aabf376a5fe59bb2Anju Mathapati                        DisconnectCause.NOT_DISCONNECTED, true /*ignore state update*/);
1121288268d5528e0df03f348e303954813cb188c55bRekha Kumar            }
1122288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
1123288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /**
1125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * onCallStartFailed will be invoked when:
1126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 1) Dialing fails
1127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 2) Ringing call is disconnected by local or remote user
1128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
1129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
1132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPendingMO != null) {
1134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // To initiate dialing circuit-switched call
1135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
1136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mBackgroundCall.getState() == ImsPhoneCall.State.IDLE
1137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mRingingCall.getState() == ImsPhoneCall.State.IDLE) {
1138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.detach(mPendingMO);
1139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.finalize();
1141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.initiateSilentRedial();
1143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return;
1144990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                } else {
11452770b0f5449670eadab1d68ea8d5fa4788f4704aSantos Cordon                    mPendingMO = null;
1146990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1147990c42d788cb2f39cd7a6ddd97e5ebdefb298f75Libin.Tang@motorola.com                    processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
1148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallTerminated reasonCode=" + reasonInfo.getCode());
1155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneCall.State oldState = mForegroundCall.getState();
1157bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            int cause = getDisconnectCauseFromReasonInfo(reasonInfo);
1158bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            ImsPhoneConnection conn = findConnection(imsCall);
1159bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            if (DBG) log("cause = " + cause + " conn = " + conn);
1160bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com
116117e77849f88cf20dc5a28aeede66b839fbbdb831Uma Maheswari Ramalingam            if (conn != null && conn.isIncoming() && conn.getConnectTime() == 0) {
11623b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                // Missed
11633b2b1bd2293667d4de32920cdad2c19f77777e2fLibin.Tang@motorola.com                if (cause == DisconnectCause.NORMAL) {
1164bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com                    cause = DisconnectCause.INCOMING_MISSED;
116508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else {
116608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    cause = DisconnectCause.INCOMING_REJECTED;
116717e77849f88cf20dc5a28aeede66b839fbbdb831Uma Maheswari Ramalingam                }
11685fbf6bed80437e092a93e6137de56e6b409910b1Etan Cohen                if (DBG) log("Incoming connection of 0 connect time detected - translated cause = "
11695fbf6bed80437e092a93e6137de56e6b409910b1Etan Cohen                        + cause);
1170f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com
1171bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            }
1172f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1173f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            if (cause == DisconnectCause.NORMAL && conn != null && conn.getImsCall().isMerged()) {
1174f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                // Call was terminated while it is merged instead of a remote disconnect.
1175f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee                cause = DisconnectCause.IMS_MERGED_SUCCESSFULLY;
1176f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee            }
1177f885059bcd0c294e9830bfe5aeb16974c0717fa3Andrew Lee
1178bc0406859056e2de6d36cbddf39e15fcfa8155b0Libin.Tang@motorola.com            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
117908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (mForegroundCall.getState() != ImsPhoneCall.State.ACTIVE) {
118008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                if (mRingingCall.getState().isRinging()) {
118108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    // Drop pending MO. We should address incoming call first
118208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    mPendingMO = null;
118308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                } else if (mPendingMO != null) {
118408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                    sendEmptyMessage(EVENT_DIAL_PENDINGMO);
118508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                }
118608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            }
1187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHeld(ImsCall imsCall) {
1191707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            if (DBG) {
1192707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (mForegroundCall.getImsCall() == imsCall) {
1193707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (fg) " + imsCall);
1194707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                } else if (mBackgroundCall.getImsCall() == imsCall) {
1195707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallHeld (bg) " + imsCall);
1196707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1197707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            }
1198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State oldState = mBackgroundCall.getState();
1201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
1202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        DisconnectCause.NOT_DISCONNECTED);
1203c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1204c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // Note: If we're performing a switchWaitingOrHoldingAndActive, the call to
1205c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // processCallStateChange above may have caused the mBackgroundCall and
1206c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // mForegroundCall references below to change meaning.  Watch out for this if you
1207c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                // are reading through this code.
1208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (oldState == ImsPhoneCall.State.ACTIVE) {
1209276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // Note: This case comes up when we have just held a call in response to a
1210276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // switchWaitingOrHoldingAndActive.  We now need to resume the background call.
1211276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                    // The EVENT_RESUME_BACKGROUND causes resumeWaitingOrHolding to be called.
1212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
1213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
12140db65ec818e58fb5b83a492e082db4536f3b83e0Tyler Gunn
1215f1227d71324a4d1916c3fd441ca688cc76129583Libin.Tang@motorola.com                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
1216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    } else {
1217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //when multiple connections belong to background call,
1218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //only the first callback reaches here
1219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //otherwise the oldState is already HOLDING
1220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mPendingMO != null) {
1221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            sendEmptyMessage(EVENT_DIAL_PENDINGMO);
1222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
1223c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn
1224c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // In this case there will be no call resumed, so we can assume that we
1225c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // are done switching fg and bg calls now.
1226c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // This may happen if there is no BG call and we are holding a call so that
1227c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        // we can dial another one.
1228c7c2aff39afb425b34ea6cc17d172cc28f5ab4f0Tyler Gunn                        mSwitchingFgAndBgCalls = false;
1229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldFailed reasonCode=" + reasonInfo.getCode());
1237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
1239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State bgState = mBackgroundCall.getState();
1240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
1241a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // disconnected while processing hold
1242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessage(EVENT_DIAL_PENDINGMO);
1244a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else if (bgState == ImsPhoneCall.State.ACTIVE) {
1246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.switchWith(mBackgroundCall);
1247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
1249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
1250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
1251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumed(ImsCall imsCall) {
1258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumed");
1259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1260276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If we are the in midst of swapping FG and BG calls and the call we end up resuming
1261276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // is not the one we expected, we likely had a resume failure and we need to swap the
1262276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // FG and BG calls back.
1263276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            if (mSwitchingFgAndBgCalls && imsCall != mCallExpectedToResume) {
1264707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (DBG) {
1265707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallResumed : switching " + mForegroundCall + " with "
1266707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                            + mBackgroundCall);
1267707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1268276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mForegroundCall.switchWith(mBackgroundCall);
1269276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1270276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1271276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
1273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
1274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1278276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // If we are in the midst of swapping the FG and BG calls and we got a resume fail, we
1279276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            // need to swap back the FG and BG calls.
1280276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            if (mSwitchingFgAndBgCalls && imsCall == mCallExpectedToResume) {
1281707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                if (DBG) {
1282707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    log("onCallResumeFailed : switching " + mForegroundCall + " with "
1283707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                            + mBackgroundCall);
1284707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                }
1285276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mForegroundCall.switchWith(mBackgroundCall);
1286276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mCallExpectedToResume = null;
1287276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn                mSwitchingFgAndBgCalls = false;
1288276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            }
1289276bc50374a46461b334fef28fdf07b536d96c71Tyler Gunn            mPhone.notifySuppServiceFailed(Phone.SuppService.RESUME);
1290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeReceived(ImsCall imsCall) {
1294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumeReceived");
1295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mOnHoldToneStarted) {
1297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.stopOnHoldTone();
1298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mOnHoldToneStarted = false;
1299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
130008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
130108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
130208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
130308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
130408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
130508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_RETRIEVED;
130608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
1307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldReceived(ImsCall imsCall) {
1311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldReceived");
1312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneConnection conn = findConnection(imsCall);
1314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn != null && conn.getState() == ImsPhoneCall.State.ACTIVE) {
1315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (!mOnHoldToneStarted && ImsPhoneCall.isLocalTone(imsCall)) {
1316a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.startOnHoldTone();
1317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mOnHoldToneStarted = true;
1318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
132008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
132108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
132208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Type of notification: 0 = MO; 1 = MT
132308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            // Refer SuppServiceNotification class documentation.
132408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.notificationType = 1;
132508e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = SuppServiceNotification.MT_CODE_CALL_ON_HOLD;
132608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
132708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        }
132808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
132908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        @Override
133008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh        public void onCallSuppServiceReceived(ImsCall call,
133108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh                ImsSuppServiceNotification suppServiceInfo) {
133208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            if (DBG) log("onCallSuppServiceReceived: suppServiceInfo=" + suppServiceInfo);
133308e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
133408e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            SuppServiceNotification supp = new SuppServiceNotification();
13358762e33ba987774e43aa9f4e216ebdb084d3a03eTyler Gunn            supp.notificationType = suppServiceInfo.notificationType;
133608e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.code = suppServiceInfo.code;
133708e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.index = suppServiceInfo.index;
133808e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.number = suppServiceInfo.number;
133908e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            supp.history = suppServiceInfo.history;
134008e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh
134108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.notifySuppSvcNotification(supp);
1342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1345007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam        public void onCallMerged(final ImsCall call, final ImsCall peerCall, boolean swapCalls) {
1346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallMerged");
1347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1348707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall foregroundImsPhoneCall = findConnection(call).getCall();
1349007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            ImsPhoneConnection peerConnection = findConnection(peerCall);
1350707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            ImsPhoneCall peerImsPhoneCall = peerConnection == null ? null
1351707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn                    : peerConnection.getCall();
1352007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1353fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            if (swapCalls) {
1354007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                switchAfterConferenceSuccess();
1355fd2305639e3761c2bf3213463c4f17cc8310f4d0Tyler Gunn            }
1356707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            foregroundImsPhoneCall.merge(peerImsPhoneCall, ImsPhoneCall.State.ACTIVE);
1357007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam
1358288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // TODO Temporary code. Remove the try-catch block from the runnable once thread
1359288268d5528e0df03f348e303954813cb188c55bRekha Kumar            // synchronization is fixed.
1360288268d5528e0df03f348e303954813cb188c55bRekha Kumar            Runnable r = new Runnable() {
1361288268d5528e0df03f348e303954813cb188c55bRekha Kumar                @Override
1362288268d5528e0df03f348e303954813cb188c55bRekha Kumar                public void run() {
1363288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    try {
1364288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        final ImsPhoneConnection conn = findConnection(call);
1365288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        log("onCallMerged: ImsPhoneConnection=" + conn);
1366288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1367288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        setVideoCallProvider(conn, call);
1368288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        log("onCallMerged: CurrentVideoProvider=" + conn.getVideoProvider());
1369288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    } catch (Exception e) {
1370288268d5528e0df03f348e303954813cb188c55bRekha Kumar                        loge("onCallMerged: exception " + e);
1371288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    }
1372288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
1373288268d5528e0df03f348e303954813cb188c55bRekha Kumar            };
1374288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1375288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsPhoneCallTracker.this.post(r);
1376288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1377007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // After merge complete, update foreground as Active
1378007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // and background call as Held, if background call exists
1379007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            processCallStateChange(mForegroundCall.getImsCall(), ImsPhoneCall.State.ACTIVE,
1380007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1381007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (peerConnection != null) {
1382007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                processCallStateChange(mBackgroundCall.getImsCall(), ImsPhoneCall.State.HOLDING,
1383007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                    DisconnectCause.NOT_DISCONNECTED);
1384007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1385df0280231c51a24a0b66c24034827d7f73d6e1acSantos Cordon
1386007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // Check if the merge was requested by an existing conference call. In that
1387007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            // case, no further action is required.
1388007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            if (!call.isMergeRequestedByConf()) {
1389007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: calling onMultipartyStateChanged()");
1390007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                onMultipartyStateChanged(call, true);
1391007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            } else {
1392007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                log("onCallMerged :: Merge requested by existing conference.");
1393007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                // Reset the flag.
1394007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam                call.resetIsMergeRequestedByConf(false);
1395007b8ea24251ebb713780be787c069cedb3a4c6aUma Maheswari Ramalingam            }
1396707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            logState();
1397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
14014e47e27d1d2cbd8e533cdd2081c5bc8e51b79ad9Anthony Lee            if (DBG) log("onCallMergeFailed reasonInfo=" + reasonInfo);
140252c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
140352c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // TODO: the call to notifySuppServiceFailed throws up the "merge failed" dialog
140452c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // We should move this into the InCallService so that it is handled appropriately
140552c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // based on the user facing UI.
1406bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
140752c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee
140852c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // Start plumbing this even through Telecom so other components can take
140952c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            // appropriate action.
141052c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            ImsPhoneConnection conn = findConnection(call);
141152c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            if (conn != null) {
141252c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee                conn.onConferenceMergeFailed();
141352c1bebcaf545d679923ffbac870eb581faf2b13Anthony Lee            }
1414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1415fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1416fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        /**
1417f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * Called when the state of IMS conference participant(s) has changed.
1418fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         *
1419fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         * @param call the call object that carries out the IMS call.
1420f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn         * @param participants the participant(s) and their new state information.
1421fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn         */
1422fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        @Override
1423f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn        public void onConferenceParticipantsStateChanged(ImsCall call,
1424f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                List<ConferenceParticipant> participants) {
1425f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn            if (DBG) log("onConferenceParticipantsStateChanged");
1426fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn
1427fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            ImsPhoneConnection conn = findConnection(call);
1428fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            if (conn != null) {
1429f53559f13dc272115f27f3b23955933da45ce127Tyler Gunn                conn.updateConferenceParticipants(participants);
1430fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn            }
1431fdca22cc56b0e1ef1504e36a5aacb2ebbc4d146cTyler Gunn        }
14326d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak
14336d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        @Override
14346d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
14356d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak            mPhone.onTtyModeReceived(mode);
14366d91e295add44a5b7e611cb51401a20b3caa6571Pavel Zhamaitsiak        }
14370ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
14380ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
14390ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
14400ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
14410ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
14420ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandover ::  srcAccessTech=" + srcAccessTech + ", targetAccessTech=" +
14430ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    targetAccessTech + ", reasonInfo=" + reasonInfo);
14440ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
14450ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
14460ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
14470ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
14480ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
14490ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            ImsReasonInfo reasonInfo) {
14500ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) {
14510ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                log("onCallHandoverFailed :: srcAccessTech=" + srcAccessTech +
14520ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar                    ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" + reasonInfo);
14530ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            }
14540ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
1455ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1456ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        /**
1457ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * Handles a change to the multiparty state for an {@code ImsCall}.  Notifies the associated
1458ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * {@link ImsPhoneConnection} of the change.
1459ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *
1460ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param imsCall The IMS call.
1461ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
1462ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         *      otherwise.
1463ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn         */
1464ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        @Override
1465ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
1466ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (DBG) log("onMultipartyStateChanged to " + (isMultiParty ? "Y" : "N"));
1467ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn
1468ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            ImsPhoneConnection conn = findConnection(imsCall);
1469ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            if (conn != null) {
1470ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn                conn.updateMultipartyState(isMultiParty);
1471ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn            }
1472ce67e30bf7a91a3ff63f86020c2d91c248c3a71bTyler Gunn        }
1473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsUssdListener = new ImsCall.Listener() {
1479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStarted");
1482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd);
1486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStartFailed reasonCode=" + reasonInfo.getCode());
1495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
1497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallTerminated reasonCode=" + reasonInfo.getCode());
1502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession = null;
1505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    CommandException ex =
1507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            new CommandException(CommandException.Error.GENERIC_FAILURE);
1508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd, null, ex);
1509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imsCall.close();
1514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallUssdMessageReceived(ImsCall call,
1518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                int mode, String ussdMessage) {
1519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallUssdMessageReceived mode=" + mode);
1520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int ussdMode = -1;
1522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch(mode) {
1524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_REQUEST:
1525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_REQUEST;
1526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_NOTIFY:
1529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_NOTIFY;
1530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.onIncomingUSSD(ussdMode, ussdMessage);
1534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS service state change
1539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     *
1540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsConnectionStateListener mImsConnectionStateListener =
1542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        new ImsConnectionStateListener() {
1543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsConnected() {
1545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsConnected");
1546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1547bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(true);
1548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
15510ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsDisconnected(ImsReasonInfo imsReasonInfo) {
15520ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsDisconnected imsReasonInfo=" + imsReasonInfo);
1553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1554bd4bb4f2250463ba59dc98be649f6aa4df9fb682Libin.Tang@motorola.com            mPhone.setImsRegistered(false);
155553f2bb9ba3118ff4c22e20ab3ad46ec97a72ac24Pavel Zhamaitsiak            mPhone.processDisconnectReason(imsReasonInfo);
1556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
15590ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        public void onImsProgressing() {
15600ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar            if (DBG) log("onImsProgressing");
156108e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
156208e9c4b483dac2cbf1b7fe4cbad22f003ff92bcbShriram Ganesh            mPhone.setImsRegistered(false);
15630ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        }
15640ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar
15650ba5c4a978fba0c15c8539c790a3ae1793bd99e3Rekha Kumar        @Override
1566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsResumed() {
1567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsResumed");
1568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsSuspended() {
1573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsSuspended");
1574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1576cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
1577cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        @Override
1578cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        public void onFeatureCapabilityChanged(int serviceClass,
1579cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                int[] enabledFeatures, int[] disabledFeatures) {
1580cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            if (serviceClass == ImsServiceClass.MMTEL) {
1581288268d5528e0df03f348e303954813cb188c55bRekha Kumar                boolean tmpIsVideoCallEnabled = isVideoCallEnabled();
158204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // Check enabledFeatures to determine capabilities. We ignore disabledFeatures.
158362a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                for (int  i = ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE;
158408111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i <= ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI &&
158508111609eb4e838de7bff4960bbbd7f9c54a060ePavel Zhamaitsiak                        i < enabledFeatures.length; i++) {
158662a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    if (enabledFeatures[i] == i) {
158704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // If the feature is set to its own integer value it is enabled.
1588915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold                        if (DBG) log("onFeatureCapabilityChanged(" + i + ", " + mImsFeatureStrings[i] + "): value=true");
158962a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = true;
159004b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else if (enabledFeatures[i]
159104b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                            == ImsConfig.FeatureConstants.FEATURE_TYPE_UNKNOWN) {
159204b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // FEATURE_TYPE_UNKNOWN indicates that a feature is disabled.
1593915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold                        if (DBG) log("onFeatureCapabilityChanged(" + i + ", " + mImsFeatureStrings[i] + "): value=false");
159462a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                        mImsFeatureEnabled[i] = false;
159504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    } else {
159604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        // Feature has unknown state; it is not its own value or -1.
159704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        if (DBG) {
1598915b8a421c34b0872c96199d4390a70d5a76ed98Nathan Harold                            loge("onFeatureCapabilityChanged(" + i + ", " +mImsFeatureStrings[i] + "): unexpectedValue="
159904b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                                + enabledFeatures[i]);
160004b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                        }
160162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                    }
1602cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com                }
1603288268d5528e0df03f348e303954813cb188c55bRekha Kumar                if (tmpIsVideoCallEnabled != isVideoCallEnabled()) {
1604288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    mPhone.notifyForVideoCapabilityChanged(isVideoCallEnabled());
1605288268d5528e0df03f348e303954813cb188c55bRekha Kumar                }
160604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee
160704b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // TODO: Use the ImsCallSession or ImsCallProfile to tell the initial Wifi state and
160804b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // {@link ImsCallSession.Listener#callSessionHandover} to listen for changes to
160904b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                // wifi capability caused by a handover.
1610164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                if (DBG) log("onFeatureCapabilityChanged: isVolteEnabled=" + isVolteEnabled()
1611164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVideoCallEnabled=" + isVideoCallEnabled()
1612164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isVowifiEnabled=" + isVowifiEnabled()
1613164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati                            + ", isUtEnabled=" + isUtEnabled());
161404b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                for (ImsPhoneConnection connection : mConnections) {
161504b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                    connection.updateWifiState();
161604b0216a5f64b70ec4b06f129946fff4ef359878Andrew Lee                }
1617e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak
1618e51d918511afab905399d9fda7f51442f15bd8a7Pavel Zhamaitsiak                mPhone.onFeatureCapabilityChanged();
1619cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com            }
1620cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com        }
162103545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade
162203545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        @Override
162303545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        public void onVoiceMessageCountChanged(int count) {
162403545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            if (DBG) log("onVoiceMessageCountChanged :: count=" + count);
162503545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade            mPhone.mDefaultPhone.setVoiceMessageCount(count);
162603545e6c17da992dc0087fcd0db1262277e8da37Omkar Kolangade        }
1627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsUtInterface getUtInterface() throws ImsException {
1631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
1632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new ImsException("no ims manager", ImsReasonInfo.CODE_UNSPECIFIED);
1633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration(mServiceId);
1636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ut;
1637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
16394be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    private void transferHandoverConnections(ImsPhoneCall call) {
16404be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.mConnections != null) {
16414be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : call.mConnections) {
16424be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                c.mPreHandoverState = call.mState;
16434be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                log ("Connection state before handover is " + c.getStateBeforeHandover());
16444be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
16454be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
16464be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections == null ) {
16474be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections = call.mConnections;
16484be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        } else { // Multi-call SRVCC
16494be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mConnections.addAll(call.mConnections);
16504be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
16514be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (mHandoverCall.mConnections != null) {
16524be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            if (call.getImsCall() != null) {
16534be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                call.getImsCall().close();
16544be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
16554be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            for (Connection c : mHandoverCall.mConnections) {
16564be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam                ((ImsPhoneConnection)c).changeParent(mHandoverCall);
165752c193f0c615a9153a702ea2597217202613e413Libin.Tang@motorola.com                ((ImsPhoneConnection)c).releaseWakeLock();
16584be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            }
16594be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
16604be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        if (call.getState().isAlive()) {
16614be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            log ("Call is alive and state is " + call.mState);
16624be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            mHandoverCall.mState = call.mState;
16634be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        }
16644be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mConnections.clear();
16654be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam        call.mState = ImsPhoneCall.State.IDLE;
16664be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam    }
16674be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam
1668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void notifySrvccState(Call.SrvccState state) {
1670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("notifySrvccState state=" + state);
1671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mSrvccState = state;
1673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mSrvccState == Call.SrvccState.COMPLETED) {
16754be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mForegroundCall);
16764be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mBackgroundCall);
16774be56374921b52d54b80889540d982f39d26e3abUma Maheswari Ramalingam            transferHandoverConnections(mRingingCall);
1678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //****** Overridden from Handler
1682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void
1685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleMessage (Message msg) {
1686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
1687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("handleMessage what=" + msg.what);
1688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (msg.what) {
1690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_HANGUP_PENDINGMO:
1691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingMO != null) {
1692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.onDisconnect();
1693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1696c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
1697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
1698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.notifyPreciseCallStateChanged();
1699a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
1700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_RESUME_BACKGROUND:
1701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
1702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    resumeWaitingOrHolding();
1703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (CallStateException e) {
1704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (Phone.DEBUG_PHONE) {
1705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e);
1706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1707a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
1709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_DIAL_PENDINGMO:
1710c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                dialInternal(mPendingMO, mClirMode, mPendingCallVideoState, mPendingIntentExtras);
1711c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                mPendingIntentExtras = null;
1712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
171304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
171404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            case EVENT_EXIT_ECM_RESPONSE_CDMA:
171504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                // no matter the result, we still do the same here
171604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                if (pendingCallInEcm) {
1717288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    dialInternal(mPendingMO, pendingCallClirMode,
1718c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                            mPendingCallVideoState, mPendingIntentExtras);
1719c1d9e728264af06808d4374d39c71dd81642cafcTyler Gunn                    mPendingIntentExtras = null;
172004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                    pendingCallInEcm = false;
172104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                }
172204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                mPhone.unsetOnEcbModeExitResponse(this);
172304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam                break;
1724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1728a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void log(String msg) {
1729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
1730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void loge(String msg) {
1733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.e(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
1734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1736707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /**
1737707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * Logs the current state of the ImsPhoneCallTracker.  Useful for debugging issues with
1738707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     * call tracking.
1739707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn     */
1740707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    /* package */
1741707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    void logState() {
1742707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        if (!VERBOSE_STATE_LOGGING) {
1743707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn            return;
1744707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        }
1745707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
1746707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        StringBuilder sb = new StringBuilder();
1747707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("Current IMS PhoneCall State:\n");
1748707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Foreground: ");
1749707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mForegroundCall);
1750707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
1751707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Background: ");
1752707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mBackgroundCall);
1753707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
1754707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Ringing: ");
1755707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mRingingCall);
1756707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
1757707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(" Handover: ");
1758707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append(mHandoverCall);
1759707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        sb.append("\n");
1760707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn        Rlog.v(LOG_TAG, sb.toString());
1761707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn    }
1762707644d8250cc5c3c2287068a9df210d7eb3e863Tyler Gunn
1763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1765a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println("ImsPhoneCallTracker extends:");
1766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        super.dump(fd, pw, args);
1767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallEndedRegistrants=" + mVoiceCallEndedRegistrants);
1768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallStartedRegistrants=" + mVoiceCallStartedRegistrants);
1769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mRingingCall=" + mRingingCall);
1770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mForegroundCall=" + mForegroundCall);
1771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mBackgroundCall=" + mBackgroundCall);
1772a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mHandoverCall=" + mHandoverCall);
1773a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPendingMO=" + mPendingMO);
1774a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //pw.println(" mHangupPendingMO=" + mHangupPendingMO);
1775a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPhone=" + mPhone);
1776a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mDesiredMute=" + mDesiredMute);
1777a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mState=" + mState);
1778a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void handlePollCalls(AsyncResult ar) {
1782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
178304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
178404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    /* package */
178504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    ImsEcbm getEcbmInterface() throws ImsException {
178604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        if (mImsManager == null) {
178704e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam            throw new ImsException("no ims manager", ImsReasonInfo.CODE_UNSPECIFIED);
178804e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        }
178904e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
179004e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        ImsEcbm ecbm = mImsManager.getEcbmInterface(mServiceId);
179104e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return ecbm;
179204e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
179304e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam
179404e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    public boolean isInEmergencyCall() {
179504e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam        return mIsInEmergencyCall;
179604e36a78936967df68d9175ac09dd3f087727888Uma Maheswari Ramalingam    }
1797cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
1798cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    public boolean isVolteEnabled() {
179962a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE];
180062a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    }
180162a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com
180262a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com    public boolean isVowifiEnabled() {
180362a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_WIFI];
1804cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
1805cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com
1806288268d5528e0df03f348e303954813cb188c55bRekha Kumar    public boolean isVideoCallEnabled() {
180762a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_LTE]
180862a2b2f341be6130e4022b487648ff2fee06db8cLibin.Tang@motorola.com                || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_VIDEO_OVER_WIFI]);
1809cf91ae7acc62eba22d9e652e5de5fb90a89e2ac8Libin.Tang@motorola.com    }
1810288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1811b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    @Override
1812b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    public PhoneConstants.State getState() {
1813b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com        return mState;
1814b79f845a0451895b0f0b8a926a8571511d476ce8Libin.Tang@motorola.com    }
1815288268d5528e0df03f348e303954813cb188c55bRekha Kumar
1816288268d5528e0df03f348e303954813cb188c55bRekha Kumar    private void setVideoCallProvider(ImsPhoneConnection conn, ImsCall imsCall)
1817288268d5528e0df03f348e303954813cb188c55bRekha Kumar            throws RemoteException {
1818288268d5528e0df03f348e303954813cb188c55bRekha Kumar        IImsVideoCallProvider imsVideoCallProvider =
1819288268d5528e0df03f348e303954813cb188c55bRekha Kumar                imsCall.getCallSession().getVideoCallProvider();
1820288268d5528e0df03f348e303954813cb188c55bRekha Kumar        if (imsVideoCallProvider != null) {
1821288268d5528e0df03f348e303954813cb188c55bRekha Kumar            ImsVideoCallProviderWrapper imsVideoCallProviderWrapper =
1822288268d5528e0df03f348e303954813cb188c55bRekha Kumar                    new ImsVideoCallProviderWrapper(imsVideoCallProvider);
1823288268d5528e0df03f348e303954813cb188c55bRekha Kumar            conn.setVideoProvider(imsVideoCallProviderWrapper);
1824288268d5528e0df03f348e303954813cb188c55bRekha Kumar        }
1825288268d5528e0df03f348e303954813cb188c55bRekha Kumar    }
1826164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati
1827164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    public boolean isUtEnabled() {
1828164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati        return (mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_LTE]
1829164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati            || mImsFeatureEnabled[ImsConfig.FeatureConstants.FEATURE_TYPE_UT_OVER_WIFI]);
1830164cea0175c29fa2da4652253b1f3b3c03707c3eAnju Mathapati    }
1831d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
1832d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
1833d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * Given a call subject, removes any characters considered by the current carrier to be
18345c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * invalid, as well as escaping (using \) any characters which the carrier requires to be
18355c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * escaped.
1836d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
1837d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     * @param callSubject The call subject.
18385c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The call subject with invalid characters removed and escaping applied as required.
1839d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
18405c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String cleanseInstantLetteringMessage(String callSubject) {
18414677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        if (TextUtils.isEmpty(callSubject)) {
18424677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn            return callSubject;
18434677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn        }
18444677e1d9088a0cc787112b5daa0b70896021920eTyler Gunn
18455c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Get the carrier config for the current sub.
18465c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        CarrierConfigManager configMgr = (CarrierConfigManager)
18475c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
18485c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if we can't find the carrier config service.
18495c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (configMgr == null) {
1850d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn            return callSubject;
1851d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
1852d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
18535c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        PersistableBundle carrierConfig = configMgr.getConfigForSubId(mPhone.getSubId());
18545c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Bail if no carrier config found.
18555c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (carrierConfig == null) {
18565c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            return callSubject;
18575c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
18585c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
18595c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to replace invalid characters
18605c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String invalidCharacters = carrierConfig.getString(
18615c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING);
18625c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(invalidCharacters)) {
18635c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = callSubject.replaceAll(invalidCharacters, "");
18645c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
18655c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
18665c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        // Try to escape characters which need to be escaped.
18675c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        String escapedCharacters = carrierConfig.getString(
18685c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING);
18695c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        if (!TextUtils.isEmpty(escapedCharacters)) {
18705c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            callSubject = escapeChars(escapedCharacters, callSubject);
18715c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        }
18725c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return callSubject;
1873d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
1874d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn
1875d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    /**
18765c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * Given a source string, return a string where a set of characters are escaped using the
18775c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * backslash character.
1878d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     *
18795c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param toEscape The characters to escape with a backslash.
18805c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @param source The source string.
18815c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn     * @return The source string with characters escaped.
1882d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn     */
18835c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn    private String escapeChars(String toEscape, String source) {
18845c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        StringBuilder escaped = new StringBuilder();
18855c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        for (char c : source.toCharArray()) {
18865c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            if (toEscape.contains(Character.toString(c))) {
18875c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn                escaped.append("\\");
18885c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            }
18895c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn            escaped.append(c);
1890d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn        }
18915c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn
18925c0859c8c66d65f066fedf300ff75eee42114657Tyler Gunn        return escaped.toString();
1893d6345bfe54d2fa3e1e8d6997cef73105be07f660Tyler Gunn    }
1894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1895