ImsPhoneCallTracker.java revision 2999afbcfeab69bf7473e1b9bcabb1c9c6935b19
1a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/*
2a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Copyright (C) 2013 The Android Open Source Project
3a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
4a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Licensed under the Apache License, Version 2.0 (the "License");
5a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * you may not use this file except in compliance with the License.
6a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * You may obtain a copy of the License at
7a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
8a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *      http://www.apache.org/licenses/LICENSE-2.0
9a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville *
10a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * Unless required by applicable law or agreed to in writing, software
11a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * distributed under the License is distributed on an "AS IS" BASIS,
12a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * See the License for the specific language governing permissions and
14a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * limitations under the License.
15a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
16a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
17a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepackage com.android.internal.telephony.imsphone;
18a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
19a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.app.PendingIntent;
20a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.BroadcastReceiver;
21a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Context;
22a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.Intent;
23a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.IntentFilter;
24a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.content.SharedPreferences;
25a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.AsyncResult;
26a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Handler;
27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Message;
28a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.Registrant;
29a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.RegistrantList;
30a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.os.SystemProperties;
31a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.preference.PreferenceManager;
326bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunnimport android.telecomm.VideoCallProfile;
33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.DisconnectCause;
34a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.PhoneNumberUtils;
35a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.ServiceState;
36a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.Rlog;
37a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
38a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Call;
39a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallStateException;
40a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CallTracker;
41a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandException;
42a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.CommandsInterface;
43a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Connection;
44a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.EventLogTags;
45a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.Phone;
46a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneBase;
47a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants;
48a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.TelephonyProperties;
49a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
50a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsCall;
51a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsCallProfile;
52a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsConnectionStateListener;
53a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsException;
54a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsManager;
55a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsReasonInfo;
56a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsServiceClass;
57a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.ims.ImsUtInterface;
58a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
59a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
60a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport java.io.FileDescriptor;
61a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport java.io.PrintWriter;
62a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport java.util.List;
63a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport java.util.ArrayList;
64a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
65a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville/**
66a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * {@hide}
67a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */
68a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savillepublic final class ImsPhoneCallTracker extends CallTracker {
69a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final String LOG_TAG = "ImsPhoneCallTracker";
70a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
71a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final boolean DBG = true;
72a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
73a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
74a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
75a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onReceive(Context context, Intent intent) {
76a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (intent.getAction().equals(ImsManager.ACTION_IMS_INCOMING_CALL)) {
77a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (DBG) log("onReceive : incoming call intent");
78a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
79a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mImsManager == null) return;
80a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
81a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mServiceId < 0) return;
82a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
83a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
84a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Network initiated USSD will be treated by mImsUssdListener
85a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    boolean isUssd = intent.getBooleanExtra(ImsManager.EXTRA_USSD, false);
86a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (isUssd) {
87a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (DBG) log("onReceive : USSD");
88a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mUssdSession = mImsManager.takeCall(mServiceId, intent, mImsUssdListener);
89a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mUssdSession != null) {
902999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                            mUssdSession.accept(ImsCallProfile.CALL_TYPE_VOICE);
91a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
92a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        return;
93a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
94a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
95a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // Normal MT call
96a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);
97a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
98a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone.getContext(), imsCall,
99a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            ImsPhoneCallTracker.this, mRingingCall);
100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    addConnection(conn);
101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() != ImsPhoneCall.State.IDLE) ||
103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE)) {
104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        conn.update(imsCall, ImsPhoneCall.State.WAITING);
105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyNewRingingConnection(conn);
108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyIncomingRing();
109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    updatePhoneState();
111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.notifyPreciseCallStateChanged();
112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (ImsException e) {
113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    loge("onReceive : exception " + e);
114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constants
120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS = 7;
122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5;
123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_HANGUP_PENDINGMO = 18;
125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_RESUME_BACKGROUND = 19;
126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int EVENT_DIAL_PENDINGMO = 20;
127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private static final int TIMEOUT_HANGUP_PENDINGMO = 500;
129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Variables
131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ArrayList<ImsPhoneConnection> mConnections = new ArrayList<ImsPhoneConnection>();
132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallEndedRegistrants = new RegistrantList();
133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private RegistrantList mVoiceCallStartedRegistrants = new RegistrantList();
134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCall mRingingCall = new ImsPhoneCall(this);
136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCall mForegroundCall = new ImsPhoneCall(this);
137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCall mBackgroundCall = new ImsPhoneCall(this);
138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCall mHandoverCall = new ImsPhoneCall(this);
139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsPhoneConnection mPendingMO;
141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mClirMode = CommandsInterface.CLIR_DEFAULT;
142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Object mSyncHold = new Object();
143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall mUssdSession = null;
145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Message mPendingUssd = null;
146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhone mPhone;
148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mDesiredMute = false;    // false = mute off
150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private boolean mOnHoldToneStarted = false;
151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    PhoneConstants.State mState = PhoneConstants.State.IDLE;
153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsManager mImsManager;
155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int mServiceId = -1;
156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private Call.SrvccState mSrvccState = Call.SrvccState.NONE;
158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Events
160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Constructors
163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsPhoneCallTracker(ImsPhone phone) {
165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        this.mPhone = phone;
166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        IntentFilter intentfilter = new IntentFilter();
168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        intentfilter.addAction(ImsManager.ACTION_IMS_INCOMING_CALL);
169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().registerReceiver(mReceiver, intentfilter);
170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Thread t = new Thread() {
172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            public void run() {
173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                getImsService();
174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        };
176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        t.start();
177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private PendingIntent createIncomingCallPendingIntent() {
180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Intent intent = new Intent(ImsManager.ACTION_IMS_INCOMING_CALL);
181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                PendingIntent.FLAG_UPDATE_CURRENT);
183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void getImsService() {
186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("getImsService");
1879f9aadee921db335adc891412a6e1e828153cfc6Etan Cohen        mImsManager = ImsManager.getInstance(mPhone.getContext(), mPhone.getSubId());
188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mServiceId = mImsManager.open(ImsServiceClass.MMTEL,
190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    createIncomingCallPendingIntent(),
191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mImsConnectionStateListener);
192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("getImsService: " + e);
194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            //Leave mImsManager as null, then CallStateException will be thrown when dialing
195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mImsManager = null;
196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
199a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dispose() {
200a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dispose");
201a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.dispose();
202a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.dispose();
203a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.dispose();
204a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.dispose();
205a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
206a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
207a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.getContext().unregisterReceiver(mReceiver);
208a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
209a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
210a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void finalize() {
212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("ImsPhoneCallTracker finalized");
213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Instance Methods
216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Public Methods
218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.add(r);
222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
223a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
224a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
225a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallStartedRegistrants.remove(h);
227a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
228a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
229a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
231a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Registrant r = new Registrant(h, what, obj);
232a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.add(r);
233a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
234a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
235a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
236a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
237a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mVoiceCallEndedRegistrants.remove(h);
238a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
239a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
240a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    Connection
2416bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn    dial(String dialString, int videoState) throws CallStateException {
242a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
243a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int oirMode = sp.getInt(PhoneBase.CLIR_KEY, CommandsInterface.CLIR_DEFAULT);
2446bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn        return dial(dialString, oirMode, videoState);
245a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * oirMode is one of the CLIR_ constants
249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    synchronized Connection
2516bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn    dial(String dialString, int clirMode, int videoState) throws CallStateException {
252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("dial clirMode=" + clirMode);
253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // note that this triggers call state changed notif
255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        clearDisconnected();
256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("service not available");
259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!canDial()) {
262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot dial in current state");
263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean holdBeforeDial = false;
266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // The new call must be assigned to the foreground call.
268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // That call must be idle, so place anything that's
269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // there on hold
270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mBackgroundCall.getState() != ImsPhoneCall.State.IDLE) {
272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we should have failed in !canDial() above before we get here
273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot dial in current state");
274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // foreground call is empty for the newly dialed connection
276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            holdBeforeDial = true;
277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State fgState = ImsPhoneCall.State.IDLE;
281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneCall.State bgState = ImsPhoneCall.State.IDLE;
282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mClirMode = clirMode;
284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        synchronized (mSyncHold) {
286a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (holdBeforeDial) {
287a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                fgState = mForegroundCall.getState();
288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                bgState = mBackgroundCall.getState();
289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call failed
291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (fgState == ImsPhoneCall.State.ACTIVE) {
292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("cannot dial in current state");
293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //holding foreground call succeeded
296a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (bgState == ImsPhoneCall.State.HOLDING) {
297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    holdBeforeDial = false;
298a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = new ImsPhoneConnection(mPhone.getContext(),
302a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    checkForTestEmergencyNumber(dialString), this, mForegroundCall);
303a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        addConnection(mPendingMO);
305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (!holdBeforeDial) {
3076bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn            dialInternal(mPendingMO, clirMode, videoState);
308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
312a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
313a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mPendingMO;
314a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
315a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
3166bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn    private void dialInternal(ImsPhoneConnection conn, int clirMode, int videoState) {
317a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
318a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
319a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
320a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
321a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getAddress()== null || conn.getAddress().length() == 0
322a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                || conn.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
323a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Phone number is invalid
324a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.INVALID_NUMBER);
325a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
326a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
327a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
328a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
329a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // Always unmute when initiating a new call
330a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        setMute(false);
331a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceType = PhoneNumberUtils.isEmergencyNumber(conn.getAddress()) ?
3326bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                ImsCallProfile.SERVICE_TYPE_EMERGENCY : ImsCallProfile.SERVICE_TYPE_NORMAL;
33364e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        int callType = ImsCallProfile.getCallTypeFromVideoState(videoState);
33464e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        //TODO(vt): Is this sufficient?  At what point do we know the video state of the call?
33564e62340aae85179a6468ccac4a401900eb4dc2fTyler Gunn        conn.setVideoState(videoState);
336a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
337a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
338a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { conn.getAddress() };
339a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
3406bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                    serviceType, callType);
341a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_OIR, clirMode);
342a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
343a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mImsManager.makeCall(mServiceId, profile,
344a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsCallListener);
345a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setImsCall(imsCall);
346a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("dialInternal : " + e);
348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            conn.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
349a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
350a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
3532999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    /**
3542999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * Accepts a call with the specified video state.  The video state is the video state that the
3552999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * user has agreed upon in the InCall UI.
3562999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     *
3572999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @param videoState The video State
3582999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     * @throws CallStateException
3592999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn     */
3602999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn    void acceptCall (int videoState) throws CallStateException {
361a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("acceptCall");
362a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
363a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState().isAlive()
364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mBackgroundCall.getState().isAlive()) {
365a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot accept call");
366a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
367a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((mRingingCall.getState() == ImsPhoneCall.State.WAITING)
369a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                && mForegroundCall.getState().isAlive()) {
370a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
371a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switchWaitingOrHoldingAndActive();
372a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mRingingCall.getState().isRinging()) {
373a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("acceptCall: incoming...");
374a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // Always unmute when answering a new call
375a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            setMute(false);
376a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
377a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
378a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) {
3792999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                    imsCall.accept(ImsCallProfile.getCallTypeFromVideoState(videoState));
380a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else {
381a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new CallStateException("no valid ims call");
382a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
383a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
384a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("cannot accept call");
385a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
386a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
387a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
388a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
389a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
390a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
391a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
392a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    rejectCall () throws CallStateException {
393a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("rejectCall");
394a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
395a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState().isRinging()) {
396a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            hangup(mRingingCall);
397a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
398a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("phone not ringing");
399a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
400a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
401a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
402a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
403a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    switchWaitingOrHoldingAndActive() throws CallStateException {
404a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("switchWaitingOrHoldingAndActive");
405a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
406a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.getState() == ImsPhoneCall.State.INCOMING) {
407a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("cannot be in the incoming state");
408a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
409a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
410a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE) {
411a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCall imsCall = mForegroundCall.getImsCall();
412a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == null) {
413a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException("no ims call");
414a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
415a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
416a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.switchWith(mBackgroundCall);
417a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
418a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            try {
419a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                imsCall.hold();
420a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } catch (ImsException e) {
421a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mForegroundCall.switchWith(mBackgroundCall);
422a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                throw new CallStateException(e.getMessage());
423a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
424a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING) {
425a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            resumeWaitingOrHolding();
426a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
427a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
428a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
429a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
430a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    conference() {
431a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("conference");
432a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
433a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall fgImsCall = mForegroundCall.getImsCall();
434a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (fgImsCall == null) {
435a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no foreground ims call");
436a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
437a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
438a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
439a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall bgImsCall = mBackgroundCall.getImsCall();
440a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (bgImsCall == null) {
441a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference no background ims call");
442a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
443a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
444a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
445a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
446a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            fgImsCall.merge(bgImsCall);
447a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
448a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log("conference " + e.getMessage());
449a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
450a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
451a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
452a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
453a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    explicitCallTransfer() {
454a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //TODO : implement
455a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
456a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
457a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void
458a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    clearDisconnected() {
459a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("clearDisconnected");
460a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
461a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        internalClearDisconnected();
462a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
463a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        updatePhoneState();
464a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
465a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
466a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
467a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
468a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canConference() {
469a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
470a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING
471a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mBackgroundCall.isFull()
472a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mForegroundCall.isFull();
473a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
474a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
475a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
476a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canDial() {
477a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean ret;
478a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int serviceState = mPhone.getServiceState().getState();
479a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        String disableCall = SystemProperties.get(
480a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
481a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
482a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
483a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mPendingMO == null
484a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !mRingingCall.isRinging()
485a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && !disableCall.equals("true")
486a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && (!mForegroundCall.getState().isAlive()
487a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    || !mBackgroundCall.getState().isAlive());
488a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
489a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ret;
490a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
491a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
492a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    boolean
493a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    canTransfer() {
494a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mForegroundCall.getState() == ImsPhoneCall.State.ACTIVE
495a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            && mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING;
496a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
497a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
498a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Private Instance Methods
499a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
500a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
501a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    internalClearDisconnected() {
502a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mRingingCall.clearDisconnected();
503a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.clearDisconnected();
504a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mBackgroundCall.clearDisconnected();
505a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mHandoverCall.clearDisconnected();
506a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
507a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
508a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
509a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    updatePhoneState() {
510a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        PhoneConstants.State oldState = mState;
511a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
512a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mRingingCall.isRinging()) {
513a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.RINGING;
514a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (mPendingMO != null ||
515a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                !(mForegroundCall.isIdle() && mBackgroundCall.isIdle())) {
516a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.OFFHOOK;
517a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
518a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mState = PhoneConstants.State.IDLE;
519a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
520a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
521a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState == PhoneConstants.State.IDLE && oldState != mState) {
522a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallEndedRegistrants.notifyRegistrants(
523a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
524a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != mState) {
525a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mVoiceCallStartedRegistrants.notifyRegistrants (
526a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    new AsyncResult(null, null, null));
527a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
528a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
529a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("updatePhoneState oldState=" + oldState + ", newState=" + mState);
530a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
531a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mState != oldState) {
532a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPhoneStateChanged();
533a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
534a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
535a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
536a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
537a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleRadioNotAvailable() {
538a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // handlePollCalls will clear out its
539a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // call list when it gets the CommandException
540a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        // error result from this
541a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pollCallsWhenSafe();
542a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
543a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
544a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void
545a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    dumpState() {
546a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        List l;
547a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
548a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Phone State:" + mState);
549a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
550a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Ringing call: " + mRingingCall.toString());
551a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
552a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mRingingCall.getConnections();
553a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
554a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
555a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
556a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
557a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Foreground call: " + mForegroundCall.toString());
558a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
559a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mForegroundCall.getConnections();
560a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
561a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
562a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
563a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
564a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        log("Background call: " + mBackgroundCall.toString());
565a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
566a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        l = mBackgroundCall.getConnections();
567a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (int i = 0, s = l.size(); i < s; i++) {
568a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            log(l.get(i).toString());
569a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
570a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
571a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
572a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
573a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhone
574a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
575a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
576a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    setMute(boolean mute) {
577a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mDesiredMute = mute;
578a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mForegroundCall.setMute(mute);
579a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
580a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
581a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ boolean
582a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    getMute() {
583a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return mDesiredMute;
584a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
585a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
586a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
587a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    sendDtmf(char c) {
588a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendDtmf");
589a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
590a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imscall = mForegroundCall.getImsCall();
591a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imscall != null) {
592a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imscall.sendDtmf(convertDtmf(c));
593a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
594a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
595a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
596a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int convertDtmf(char c) {
597a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int code = c - '0';
598a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if ((code < 0) || (code > 9)) {
599a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch (c) {
600a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case '*': return 10;
601a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case '#': return 11;
602a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case 'A': return 12;
603a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case 'B': return 13;
604a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case 'C': return 14;
605a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case 'D': return 15;
606a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                default:
607a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    throw new IllegalArgumentException(
608a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            "invalid DTMF char: " + (int) c);
609a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
610a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
611a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return code;
612a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
613a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
614a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneConnection
615a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
616a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /*package*/ void
617a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    hangup (ImsPhoneConnection conn) throws CallStateException {
618a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup connection");
619a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
620a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn.getOwner() != this) {
621a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException ("ImsPhoneConnection " + conn
622a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    + "does not belong to ImsPhoneCallTracker " + this);
623a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
624a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
625a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        hangup(conn.getCall());
626a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
627a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
628a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //***** Called from ImsPhoneCall
629a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
630a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */ void
631a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    hangup (ImsPhoneCall call) throws CallStateException {
632a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("hangup call");
633a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
634a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call.getConnections().size() == 0) {
635a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException("no connections");
636a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
637a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
638a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsCall imsCall = call.getImsCall();
639a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean rejectCall = false;
640a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
641a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (call == mRingingCall) {
642a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming");
643a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            rejectCall = true;
644a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mForegroundCall) {
645a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (call.isDialingOrAlerting()) {
646a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
647a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup dialing or alerting...");
648a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
649a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
650a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (Phone.DEBUG_PHONE) {
651a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    log("(foregnd) hangup foreground");
652a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
653a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //held call will be resumed by onCallTerminated
654a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
655a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else if (call == mBackgroundCall) {
656a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (Phone.DEBUG_PHONE) {
657a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                log("(backgnd) hangup waiting or background");
658a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
659a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } else {
660a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new RuntimeException ("ImsPhoneCall " + call +
661a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    "does not belong to ImsPhoneCallTracker " + this);
662a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
663a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
664a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        call.onHangupLocal();
665a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
666a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
667a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall != null) {
668a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (rejectCall) imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE);
669a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                else imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
670a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mPendingMO != null && call == mForegroundCall) {
671a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // is holding a foreground call
672a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED);
673a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO.onDisconnect();
674a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeConnection(mPendingMO);
675a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
676a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
677a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                removeMessages(EVENT_DIAL_PENDINGMO);
678a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
679a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
680a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
681a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
682a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
683a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mPhone.notifyPreciseCallStateChanged();
684a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
685a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
686a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
687a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void resumeWaitingOrHolding() throws CallStateException {
688a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("resumeWaitingOrHolding");
689a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
690a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
691a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getState().isAlive()) {
692a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //resume foreground call after holding background call
693a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //they were switched before holding
694a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mForegroundCall.getImsCall();
695a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) imsCall.resume();
696a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mRingingCall.getState() == ImsPhoneCall.State.WAITING) {
697a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //accept waiting call after holding background call
698a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mRingingCall.getImsCall();
6992999afbcfeab69bf7473e1b9bcabb1c9c6935b19Tyler Gunn                if (imsCall != null) imsCall.accept(ImsCallProfile.CALL_TYPE_VOICE);
700a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else {
701a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //Just resume background call.
702a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //To distinguish resuming call with swapping calls
703a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //we do not switch calls.here
704a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                //ImsPhoneConnection.update will chnage the parent when completed
705a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsCall imsCall = mBackgroundCall.getImsCall();
706a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (imsCall != null) imsCall.resume();
707a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
708a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
709a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new CallStateException(e.getMessage());
710a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
711a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
712a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
713a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
714a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void sendUSSD (String ussdString, Message response) {
715a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("sendUSSD");
716a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
717a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
718a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mUssdSession != null) {
719a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession.sendUssd(ussdString);
720a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                AsyncResult.forMessage(response, null, null);
721a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                response.sendToTarget();
722a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return;
723a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
724a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
725a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            String[] callees = new String[] { ussdString };
726a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsCallProfile profile = mImsManager.createCallProfile(mServiceId,
727a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.SERVICE_TYPE_NORMAL, ImsCallProfile.CALL_TYPE_VOICE);
728a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            profile.setCallExtraInt(ImsCallProfile.EXTRA_DIALSTRING,
729a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ImsCallProfile.DIALSTRING_USSD);
730a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
731a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession = mImsManager.makeCall(mServiceId, profile,
732a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    callees, mImsUssdListener);
733a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
734a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            loge("sendUSSD : " + e);
735a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.sendErrorResponse(response, e);
736a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
737a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
738a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
739a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
740a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void cancelUSSD() {
741a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mUssdSession == null) return;
742a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
743a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        try {
744a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mUssdSession.terminate(ImsReasonInfo.CODE_USER_TERMINATED);
745a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        } catch (ImsException e) {
746a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
747a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
748a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
749a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
750a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized ImsPhoneConnection findConnection(ImsCall imsCall) {
751a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        for (ImsPhoneConnection conn : mConnections) {
752a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getImsCall() == imsCall) {
753a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return conn;
754a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
755a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
756a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return null;
757a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
758a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
759a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void removeConnection(ImsPhoneConnection conn) {
760a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.remove(conn);
761a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
762a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
763a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private synchronized void addConnection(ImsPhoneConnection conn) {
764a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mConnections.add(conn);
765a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
766a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
767a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) {
768a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("processCallStateChange state=" + state + " cause=" + cause);
769a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
770a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (imsCall == null) return;
771a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
772a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        boolean changed = false;
773a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsPhoneConnection conn = findConnection(imsCall);
774a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
775a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (conn == null) {
776a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : what should be done?
777a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            return;
778a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
779a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
780a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        changed = conn.update(imsCall, state);
781a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
782a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (state == ImsPhoneCall.State.DISCONNECTED) {
783a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            changed = conn.onDisconnect(cause) || changed;
784a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            removeConnection(conn);
785a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
786a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
787a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (changed) {
788a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn.getCall() == mHandoverCall) return;
789a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
790a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
791a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
792a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
793a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
794a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private int getDisconnectCauseFromReasonInfo(ImsReasonInfo reasonInfo) {
795a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int cause = DisconnectCause.ERROR_UNSPECIFIED;
796a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
797a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //int type = reasonInfo.getReasonType();
798a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        int code = reasonInfo.getCode();
799a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (code) {
800a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_ADDRESS:
801a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_REACHABLE:
802a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NUMBER_UNREACHABLE;
803a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
804a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BUSY:
805a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.BUSY;
806a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
807a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED:
808a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.LOCAL;
809a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
810a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE:
811a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.NORMAL;
812a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
813a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REDIRECTED:
814a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_BAD_REQUEST:
815a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_FORBIDDEN:
816a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_ACCEPTABLE:
817a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_USER_REJECTED:
818a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_GLOBAL_ERROR:
819a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_ERROR;
820a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
821a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVICE_UNAVAILABLE:
822a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_NOT_FOUND:
823a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_SERVER_ERROR:
824a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.SERVER_UNREACHABLE;
825a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
826a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_ROAMING:
827a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_IP_CHANGED:
828a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN:
829a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE:
830a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED:
831a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE:
832a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_NETWORK_NO_SERVICE:
833a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_CALL_VCC_ON_PROGRESSING:
834a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.OUT_OF_SERVICE;
835a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
836a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_SIP_REQUEST_TIMEOUT:
837a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_1XX_WAITING:
838a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER:
839a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE:
840a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.TIMED_OUT;
841a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
842a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_LOW_BATTERY:
843a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case ImsReasonInfo.CODE_LOCAL_POWER_OFF:
844a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                return DisconnectCause.POWER_OFF;
845a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
846a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            default:
847a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
848a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
849a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return cause;
850a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
851a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
852a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
853a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
854a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
855a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsCallListener = new ImsCall.Listener() {
856a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
857a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallProgressing(ImsCall imsCall) {
858a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallProgressing");
859a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
860a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
861a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ALERTING,
862a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
863a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
864a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
865a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
866a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
867a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStarted");
868a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
869a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPendingMO = null;
870a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
871a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
872a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
873a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
874a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        /**
875a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * onCallStartFailed will be invoked when:
876a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 1) Dialing fails
877a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         * case 2) Ringing call is disconnected by local or remote user
878a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville         */
879a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
880a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
881a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
882a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
883a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mPendingMO != null) {
884a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                // To initiate dialing circuit-switched call
885a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
886a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mBackgroundCall.getState() == ImsPhoneCall.State.IDLE
887a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && mRingingCall.getState() == ImsPhoneCall.State.IDLE) {
888a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.detach(mPendingMO);
889a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
890a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.finalize();
891a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
892a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.initiateSilentRedial();
893a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    return;
894a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
895a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPendingMO = null;
896a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
897a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
898a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
899a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
900a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
901a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
902a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallTerminated reasonCode=" + reasonInfo.getCode());
903a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
904a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneCall.State oldState = mForegroundCall.getState();
905a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
906a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED,
907a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    getDisconnectCauseFromReasonInfo(reasonInfo));
908a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
909a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (reasonInfo.getCode() == ImsReasonInfo.CODE_USER_TERMINATED) {
910a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if ((oldState == ImsPhoneCall.State.DISCONNECTING)
911a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && (mForegroundCall.getState() == ImsPhoneCall.State.DISCONNECTED)
912a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        && (mBackgroundCall.getState() == ImsPhoneCall.State.HOLDING)) {
913a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    sendEmptyMessage(EVENT_RESUME_BACKGROUND);
914a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
915a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
916a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
917a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
918a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
919a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHeld(ImsCall imsCall) {
920a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHeld");
921a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
922a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
923a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State oldState = mBackgroundCall.getState();
924a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
925a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        DisconnectCause.NOT_DISCONNECTED);
926a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
927a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (oldState == ImsPhoneCall.State.ACTIVE) {
928a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
929a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
930a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessage(EVENT_RESUME_BACKGROUND);
931a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    } else {
932a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //when multiple connections belong to background call,
933a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //only the first callback reaches here
934a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        //otherwise the oldState is already HOLDING
935a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        if (mPendingMO != null) {
936a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            sendEmptyMessage(EVENT_DIAL_PENDINGMO);
937a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        }
938a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
939a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
940a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
941a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
942a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
943a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
944a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
945a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldFailed reasonCode=" + reasonInfo.getCode());
946a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
947a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            synchronized (mSyncHold) {
948a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                ImsPhoneCall.State bgState = mBackgroundCall.getState();
949a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED) {
950a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    // disconnected while processing hold
951a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
952a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessage(EVENT_DIAL_PENDINGMO);
953a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
954a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } else if (bgState == ImsPhoneCall.State.ACTIVE) {
955a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mForegroundCall.switchWith(mBackgroundCall);
956a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
957a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (mPendingMO != null) {
958a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        mPendingMO.setDisconnectCause(DisconnectCause.ERROR_UNSPECIFIED);
959a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        sendEmptyMessageDelayed(EVENT_HANGUP_PENDINGMO, TIMEOUT_HANGUP_PENDINGMO);
960a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
961a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
962a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
963a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
964a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
965a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
966a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumed(ImsCall imsCall) {
967a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumed");
968a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
969a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            processCallStateChange(imsCall, ImsPhoneCall.State.ACTIVE,
970a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    DisconnectCause.NOT_DISCONNECTED);
971a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
972a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
973a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
974a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
975a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            // TODO : What should be done?
976a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
977a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
978a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
979a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallResumeReceived(ImsCall imsCall) {
980a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallResumeReceived");
981a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
982a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mOnHoldToneStarted) {
983a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.stopOnHoldTone();
984a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mOnHoldToneStarted = false;
985a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
986a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
987a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
988a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
989a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallHoldReceived(ImsCall imsCall) {
990a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallHoldReceived");
991a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
992a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            ImsPhoneConnection conn = findConnection(imsCall);
993a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (conn != null && conn.getState() == ImsPhoneCall.State.ACTIVE) {
994a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (!mOnHoldToneStarted && ImsPhoneCall.isLocalTone(imsCall)) {
995a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPhone.startOnHoldTone();
996a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mOnHoldToneStarted = true;
997a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
998a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
999a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1000a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1001a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1002a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMerged(ImsCall call, ImsCall newCall) {
1003a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onCallMerged");
1004a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1005a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mForegroundCall.merge(mBackgroundCall, mForegroundCall.getState());
1006a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            updatePhoneState();
1007a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.notifyPreciseCallStateChanged();
1008a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1009a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1010a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1011a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
1012bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            if (DBG) log("onCallMergeFailed reasonCode=" + reasonInfo.getCode());
1013bd4d6093314c0d2afc4b4f69f352957d01d9bc58Uma Maheswari Ramalingam            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
1014a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1015a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1016a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1017a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1018a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS call state change
1019a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1020a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsCall.Listener mImsUssdListener = new ImsCall.Listener() {
1021a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1022a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStarted(ImsCall imsCall) {
1023a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStarted");
1024a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1025a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1026a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1027a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd);
1028a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1029a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1030a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1031a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1032a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1033a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1034a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1035a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallStartFailed(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1036a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallStartFailed reasonCode=" + reasonInfo.getCode());
1037a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1038a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            onCallTerminated(imsCall, reasonInfo);
1039a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1040a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1041a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1042a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallTerminated(ImsCall imsCall, ImsReasonInfo reasonInfo) {
1043a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallTerminated reasonCode=" + reasonInfo.getCode());
1044a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1045a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (imsCall == mUssdSession) {
1046a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mUssdSession = null;
1047a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingUssd != null) {
1048a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    CommandException ex =
1049a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                            new CommandException(CommandException.Error.GENERIC_FAILURE);
1050a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    AsyncResult.forMessage(mPendingUssd, null, ex);
1051a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd.sendToTarget();
1052a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingUssd = null;
1053a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1054a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1055a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            imsCall.close();
1056a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1057a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1058a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1059a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onCallUssdMessageReceived(ImsCall call,
1060a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                int mode, String ussdMessage) {
1061a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("mImsUssdListener onCallUssdMessageReceived mode=" + mode);
1062a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1063a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            int ussdMode = -1;
1064a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1065a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            switch(mode) {
1066a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_REQUEST:
1067a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_REQUEST;
1068a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1069a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1070a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                case ImsCall.USSD_MODE_NOTIFY:
1071a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    ussdMode = CommandsInterface.USSD_MODE_NOTIFY;
1072a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    break;
1073a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1074a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1075a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.onIncomingUSSD(ussdMode, ussdMessage);
1076a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1077a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1078a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1079a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /**
1080a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     * Listen to the IMS service state change
1081a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     *
1082a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville     */
1083a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    private ImsConnectionStateListener mImsConnectionStateListener =
1084a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        new ImsConnectionStateListener() {
1085a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1086a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsConnected() {
1087a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsConnected");
1088a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1089a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1090a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1091a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1092a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsDisconnected() {
1093a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsDisconnected");
1094a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1095a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1096a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1097a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1098a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsResumed() {
1099a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsResumed");
1100a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_IN_SERVICE);
1101a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1103a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        @Override
1104a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        public void onImsSuspended() {
1105a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (DBG) log("onImsSuspended");
1106a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            mPhone.setServiceState(ServiceState.STATE_OUT_OF_SERVICE);
1107a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    };
1109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    ImsUtInterface getUtInterface() throws ImsException {
1112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mImsManager == null) {
1113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            throw new ImsException("no ims manager", ImsReasonInfo.CODE_UNSPECIFIED);
1114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration(mServiceId);
1117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        return ut;
1118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    /* package */
1121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    void notifySrvccState(Call.SrvccState state) {
1122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("notifySrvccState state=" + state);
1123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        mSrvccState = state;
1125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (mSrvccState == Call.SrvccState.COMPLETED) {
1127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            if (mForegroundCall.getConnections().size() > 0) {
1128a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandoverCall.switchWith(mForegroundCall);
1129a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            } else if (mBackgroundCall.getConnections().size() > 0) {
1130a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mHandoverCall.switchWith(mBackgroundCall);
1131a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            }
1132a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1133a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1134a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1135a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    //****** Overridden from Handler
1136a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1137a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void
1139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    handleMessage (Message msg) {
1140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        AsyncResult ar;
1141a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        if (DBG) log("handleMessage what=" + msg.what);
1142a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        switch (msg.what) {
1144a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_HANGUP_PENDINGMO:
1145a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                if (mPendingMO != null) {
1146a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO.onDisconnect();
1147a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    removeConnection(mPendingMO);
1148a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    mPendingMO = null;
1149a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1150a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1151a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                updatePhoneState();
1152a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                mPhone.notifyPreciseCallStateChanged();
1153a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
1154a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_RESUME_BACKGROUND:
1155a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                try {
1156a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    resumeWaitingOrHolding();
1157a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                } catch (CallStateException e) {
1158a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    if (Phone.DEBUG_PHONE) {
1159a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                        loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e);
1160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                    }
1161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                }
1162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
1163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville            case EVENT_DIAL_PENDINGMO:
11646bbcbfd62c9aa5787e7c33936e2246ff05b59d58Tyler Gunn                dialInternal(mPendingMO, mClirMode, VideoCallProfile.VIDEO_STATE_AUDIO_ONLY);
1165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville                break;
1166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        }
1167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void log(String msg) {
1171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.d(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
1172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void loge(String msg) {
1175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        Rlog.e(LOG_TAG, "[ImsPhoneCallTracker] " + msg);
1176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println("ImsPhoneCallTracker extends:");
1181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        super.dump(fd, pw, args);
1182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallEndedRegistrants=" + mVoiceCallEndedRegistrants);
1183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mVoiceCallStartedRegistrants=" + mVoiceCallStartedRegistrants);
1184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mRingingCall=" + mRingingCall);
1185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mForegroundCall=" + mForegroundCall);
1186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mBackgroundCall=" + mBackgroundCall);
1187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mHandoverCall=" + mHandoverCall);
1188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPendingMO=" + mPendingMO);
1189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        //pw.println(" mHangupPendingMO=" + mHangupPendingMO);
1190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mPhone=" + mPhone);
1191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mDesiredMute=" + mDesiredMute);
1192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville        pw.println(" mState=" + mState);
1193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1194a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville
1195a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    @Override
1196a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    protected void handlePollCalls(AsyncResult ar) {
1197a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville    }
1198a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville}
1199