CallManager.java revision 3a96b0ee1d152549279c58ba24a0a035cc9a557b
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony;
18
19import com.android.internal.telephony.imsphone.ImsPhone;
20import com.android.internal.telephony.sip.SipPhone;
21
22import android.content.Context;
23import android.os.AsyncResult;
24import android.os.Handler;
25import android.os.Message;
26import android.os.RegistrantList;
27import android.os.Registrant;
28import android.telecom.VideoProfile;
29import android.telephony.PhoneNumberUtils;
30import android.telephony.TelephonyManager;
31import android.telephony.PhoneStateListener;
32import android.telephony.ServiceState;
33import android.telephony.Rlog;
34
35import java.util.ArrayList;
36import java.util.Collections;
37import java.util.HashMap;
38import java.util.List;
39
40
41
42/**
43 * @hide
44 *
45 * CallManager class provides an abstract layer for PhoneApp to access
46 * and control calls. It implements Phone interface.
47 *
48 * CallManager provides call and connection control as well as
49 * channel capability.
50 *
51 * There are three categories of APIs CallManager provided
52 *
53 *  1. Call control and operation, such as dial() and hangup()
54 *  2. Channel capabilities, such as CanConference()
55 *  3. Register notification
56 *
57 *
58 */
59public final class CallManager {
60
61    private static final String LOG_TAG ="CallManager";
62    private static final boolean DBG = true;
63    private static final boolean VDBG = false;
64
65    private static final int EVENT_DISCONNECT = 100;
66    private static final int EVENT_PRECISE_CALL_STATE_CHANGED = 101;
67    private static final int EVENT_NEW_RINGING_CONNECTION = 102;
68    private static final int EVENT_UNKNOWN_CONNECTION = 103;
69    private static final int EVENT_INCOMING_RING = 104;
70    private static final int EVENT_RINGBACK_TONE = 105;
71    private static final int EVENT_IN_CALL_VOICE_PRIVACY_ON = 106;
72    private static final int EVENT_IN_CALL_VOICE_PRIVACY_OFF = 107;
73    private static final int EVENT_CALL_WAITING = 108;
74    private static final int EVENT_DISPLAY_INFO = 109;
75    private static final int EVENT_SIGNAL_INFO = 110;
76    private static final int EVENT_CDMA_OTA_STATUS_CHANGE = 111;
77    private static final int EVENT_RESEND_INCALL_MUTE = 112;
78    private static final int EVENT_MMI_INITIATE = 113;
79    private static final int EVENT_MMI_COMPLETE = 114;
80    private static final int EVENT_ECM_TIMER_RESET = 115;
81    private static final int EVENT_SUBSCRIPTION_INFO_READY = 116;
82    private static final int EVENT_SUPP_SERVICE_FAILED = 117;
83    private static final int EVENT_SERVICE_STATE_CHANGED = 118;
84    private static final int EVENT_POST_DIAL_CHARACTER = 119;
85    private static final int EVENT_ONHOLD_TONE = 120;
86    // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
87    //private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 121;
88    private static final int EVENT_TTY_MODE_RECEIVED = 122;
89
90    // Singleton instance
91    private static final CallManager INSTANCE = new CallManager();
92
93    // list of registered phones, which are PhoneBase objs
94    private final ArrayList<Phone> mPhones;
95
96    // list of supported ringing calls
97    private final ArrayList<Call> mRingingCalls;
98
99    // list of supported background calls
100    private final ArrayList<Call> mBackgroundCalls;
101
102    // list of supported foreground calls
103    private final ArrayList<Call> mForegroundCalls;
104
105    // empty connection list
106    private final ArrayList<Connection> mEmptyConnections = new ArrayList<Connection>();
107
108    // mapping of phones to registered handler instances used for callbacks from RIL
109    private final HashMap<Phone, CallManagerHandler> mHandlerMap = new HashMap<>();
110
111    // default phone as the first phone registered, which is PhoneBase obj
112    private Phone mDefaultPhone;
113
114    private boolean mSpeedUpAudioForMtCall = false;
115    // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
116    //private boolean mIsEccDialing = false;
117
118    private Object mRegistrantidentifier = new Object();
119
120    // state registrants
121    protected final RegistrantList mPreciseCallStateRegistrants
122    = new RegistrantList();
123
124    protected final RegistrantList mNewRingingConnectionRegistrants
125    = new RegistrantList();
126
127    protected final RegistrantList mIncomingRingRegistrants
128    = new RegistrantList();
129
130    protected final RegistrantList mDisconnectRegistrants
131    = new RegistrantList();
132
133    protected final RegistrantList mMmiRegistrants
134    = new RegistrantList();
135
136    protected final RegistrantList mUnknownConnectionRegistrants
137    = new RegistrantList();
138
139    protected final RegistrantList mRingbackToneRegistrants
140    = new RegistrantList();
141
142    protected final RegistrantList mOnHoldToneRegistrants
143    = new RegistrantList();
144
145    protected final RegistrantList mInCallVoicePrivacyOnRegistrants
146    = new RegistrantList();
147
148    protected final RegistrantList mInCallVoicePrivacyOffRegistrants
149    = new RegistrantList();
150
151    protected final RegistrantList mCallWaitingRegistrants
152    = new RegistrantList();
153
154    protected final RegistrantList mDisplayInfoRegistrants
155    = new RegistrantList();
156
157    protected final RegistrantList mSignalInfoRegistrants
158    = new RegistrantList();
159
160    protected final RegistrantList mCdmaOtaStatusChangeRegistrants
161    = new RegistrantList();
162
163    protected final RegistrantList mResendIncallMuteRegistrants
164    = new RegistrantList();
165
166    protected final RegistrantList mMmiInitiateRegistrants
167    = new RegistrantList();
168
169    protected final RegistrantList mMmiCompleteRegistrants
170    = new RegistrantList();
171
172    protected final RegistrantList mEcmTimerResetRegistrants
173    = new RegistrantList();
174
175    protected final RegistrantList mSubscriptionInfoReadyRegistrants
176    = new RegistrantList();
177
178    protected final RegistrantList mSuppServiceFailedRegistrants
179    = new RegistrantList();
180
181    protected final RegistrantList mServiceStateChangedRegistrants
182    = new RegistrantList();
183
184    protected final RegistrantList mPostDialCharacterRegistrants
185    = new RegistrantList();
186
187    protected final RegistrantList mTtyModeReceivedRegistrants
188    = new RegistrantList();
189
190    private CallManager() {
191        mPhones = new ArrayList<Phone>();
192        mRingingCalls = new ArrayList<Call>();
193        mBackgroundCalls = new ArrayList<Call>();
194        mForegroundCalls = new ArrayList<Call>();
195        mDefaultPhone = null;
196    }
197
198    /**
199     * get singleton instance of CallManager
200     * @return CallManager
201     */
202    public static CallManager getInstance() {
203        return INSTANCE;
204    }
205
206    /**
207     * Get the corresponding PhoneBase obj
208     *
209     * @param phone a Phone object
210     * @return the corresponding PhoneBase obj in Phone if Phone
211     * is a PhoneProxy obj
212     * or the Phone itself if Phone is not a PhoneProxy obj
213     */
214    private static Phone getPhoneBase(Phone phone) {
215        return phone;
216    }
217
218    /**
219     * Check if two phones refer to the same PhoneBase obj
220     *
221     * Note: PhoneBase, not PhoneProxy, is to be used inside of CallManager
222     *
223     * Both PhoneBase and PhoneProxy implement Phone interface, so
224     * they have same phone APIs, such as dial(). The real implementation, for
225     * example in GSM,  is in GSMPhone as extend from PhoneBase, so that
226     * foregroundCall.getPhone() returns GSMPhone obj. On the other hand,
227     * PhoneFactory.getDefaultPhone() returns PhoneProxy obj, which has a class
228     * member of GSMPhone.
229     *
230     * So for phone returned by PhoneFacotry, which is used by PhoneApp,
231     *        phone.getForegroundCall().getPhone() != phone
232     * but
233     *        isSamePhone(phone, phone.getForegroundCall().getPhone()) == true
234     *
235     * @param p1 is the first Phone obj
236     * @param p2 is the second Phone obj
237     * @return true if p1 and p2 refer to the same phone
238     */
239    public static boolean isSamePhone(Phone p1, Phone p2) {
240        return (getPhoneBase(p1) == getPhoneBase(p2));
241    }
242
243    /**
244     * Returns all the registered phone objects.
245     * @return all the registered phone objects.
246     */
247    public List<Phone> getAllPhones() {
248        return Collections.unmodifiableList(mPhones);
249    }
250
251    /**
252     * get Phone object corresponds to subId
253     * @return Phone
254     */
255    private Phone getPhone(int subId) {
256        Phone p = null;
257        for (Phone phone : mPhones) {
258            if (phone.getSubId() == subId && !(phone instanceof ImsPhone)) {
259                p = phone;
260                break;
261            }
262        }
263        return p;
264    }
265
266    /**
267     * Get current coarse-grained voice call state.
268     * If the Call Manager has an active call and call waiting occurs,
269     * then the phone state is RINGING not OFFHOOK
270     *
271     */
272    public PhoneConstants.State getState() {
273        PhoneConstants.State s = PhoneConstants.State.IDLE;
274
275        for (Phone phone : mPhones) {
276            if (phone.getState() == PhoneConstants.State.RINGING) {
277                s = PhoneConstants.State.RINGING;
278            } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
279                if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
280            }
281        }
282        return s;
283    }
284
285    /**
286     * Get current coarse-grained voice call state on a subId.
287     * If the Call Manager has an active call and call waiting occurs,
288     * then the phone state is RINGING not OFFHOOK
289     *
290     */
291    public PhoneConstants.State getState(int subId) {
292        PhoneConstants.State s = PhoneConstants.State.IDLE;
293
294        for (Phone phone : mPhones) {
295            if (phone.getSubId() == subId) {
296                if (phone.getState() == PhoneConstants.State.RINGING) {
297                    s = PhoneConstants.State.RINGING;
298                } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
299                    if (s == PhoneConstants.State.IDLE) s = PhoneConstants.State.OFFHOOK;
300                }
301            }
302        }
303        return s;
304    }
305
306    /**
307     * @return the service state of CallManager, which represents the
308     * highest priority state of all the service states of phones
309     *
310     * The priority is defined as
311     *
312     * STATE_IN_SERIVCE > STATE_OUT_OF_SERIVCE > STATE_EMERGENCY > STATE_POWER_OFF
313     *
314     */
315
316    public int getServiceState() {
317        int resultState = ServiceState.STATE_OUT_OF_SERVICE;
318
319        for (Phone phone : mPhones) {
320            int serviceState = phone.getServiceState().getState();
321            if (serviceState == ServiceState.STATE_IN_SERVICE) {
322                // IN_SERVICE has the highest priority
323                resultState = serviceState;
324                break;
325            } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
326                // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
327                // Note: EMERGENCY_ONLY is not in use at this moment
328                if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
329                        resultState == ServiceState.STATE_POWER_OFF) {
330                    resultState = serviceState;
331                }
332            } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
333                if (resultState == ServiceState.STATE_POWER_OFF) {
334                    resultState = serviceState;
335                }
336            }
337        }
338        return resultState;
339    }
340
341    /**
342     * @return the Phone service state corresponds to subId
343     */
344    public int getServiceState(int subId) {
345        int resultState = ServiceState.STATE_OUT_OF_SERVICE;
346
347        for (Phone phone : mPhones) {
348            if (phone.getSubId() == subId) {
349                int serviceState = phone.getServiceState().getState();
350                if (serviceState == ServiceState.STATE_IN_SERVICE) {
351                    // IN_SERVICE has the highest priority
352                    resultState = serviceState;
353                    break;
354                } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
355                    // OUT_OF_SERVICE replaces EMERGENCY_ONLY and POWER_OFF
356                    // Note: EMERGENCY_ONLY is not in use at this moment
357                    if ( resultState == ServiceState.STATE_EMERGENCY_ONLY ||
358                            resultState == ServiceState.STATE_POWER_OFF) {
359                        resultState = serviceState;
360                    }
361                } else if (serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
362                    if (resultState == ServiceState.STATE_POWER_OFF) {
363                        resultState = serviceState;
364                    }
365                }
366            }
367        }
368        return resultState;
369    }
370
371    /**
372     * @return the phone associated with any call
373     */
374    public Phone getPhoneInCall() {
375        Phone phone = null;
376        if (!getFirstActiveRingingCall().isIdle()) {
377            phone = getFirstActiveRingingCall().getPhone();
378        } else if (!getActiveFgCall().isIdle()) {
379            phone = getActiveFgCall().getPhone();
380        } else {
381            // If BG call is idle, we return default phone
382            phone = getFirstActiveBgCall().getPhone();
383        }
384        return phone;
385    }
386
387    public Phone getPhoneInCall(int subId) {
388        Phone phone = null;
389        if (!getFirstActiveRingingCall(subId).isIdle()) {
390            phone = getFirstActiveRingingCall(subId).getPhone();
391        } else if (!getActiveFgCall(subId).isIdle()) {
392            phone = getActiveFgCall(subId).getPhone();
393        } else {
394            // If BG call is idle, we return default phone
395            phone = getFirstActiveBgCall(subId).getPhone();
396        }
397        return phone;
398    }
399
400    /**
401     * Register phone to CallManager
402     * @param phone to be registered
403     * @return true if register successfully
404     */
405    public boolean registerPhone(Phone phone) {
406        Phone basePhone = getPhoneBase(phone);
407
408        if (basePhone != null && !mPhones.contains(basePhone)) {
409
410            if (DBG) {
411                Rlog.d(LOG_TAG, "registerPhone(" +
412                        phone.getPhoneName() + " " + phone + ")");
413            }
414
415            if (mPhones.isEmpty()) {
416                mDefaultPhone = basePhone;
417            }
418            mPhones.add(basePhone);
419            mRingingCalls.add(basePhone.getRingingCall());
420            mBackgroundCalls.add(basePhone.getBackgroundCall());
421            mForegroundCalls.add(basePhone.getForegroundCall());
422            registerForPhoneStates(basePhone);
423            return true;
424        }
425        return false;
426    }
427
428    /**
429     * unregister phone from CallManager
430     * @param phone to be unregistered
431     */
432    public void unregisterPhone(Phone phone) {
433        Phone basePhone = getPhoneBase(phone);
434
435        if (basePhone != null && mPhones.contains(basePhone)) {
436
437            if (DBG) {
438                Rlog.d(LOG_TAG, "unregisterPhone(" +
439                        phone.getPhoneName() + " " + phone + ")");
440            }
441
442            Phone vPhone = basePhone.getImsPhone();
443            if (vPhone != null) {
444               unregisterPhone(vPhone);
445            }
446
447            mPhones.remove(basePhone);
448            mRingingCalls.remove(basePhone.getRingingCall());
449            mBackgroundCalls.remove(basePhone.getBackgroundCall());
450            mForegroundCalls.remove(basePhone.getForegroundCall());
451            unregisterForPhoneStates(basePhone);
452            if (basePhone == mDefaultPhone) {
453                if (mPhones.isEmpty()) {
454                    mDefaultPhone = null;
455                } else {
456                    mDefaultPhone = mPhones.get(0);
457                }
458            }
459        }
460    }
461
462    /**
463     * return the default phone or null if no phone available
464     */
465    public Phone getDefaultPhone() {
466        return mDefaultPhone;
467    }
468
469    /**
470     * @return the phone associated with the foreground call
471     */
472    public Phone getFgPhone() {
473        return getActiveFgCall().getPhone();
474    }
475
476    /**
477     * @return the phone associated with the foreground call
478     * of a particular subId
479     */
480    public Phone getFgPhone(int subId) {
481        return getActiveFgCall(subId).getPhone();
482    }
483
484    /**
485     * @return the phone associated with the background call
486     */
487    public Phone getBgPhone() {
488        return getFirstActiveBgCall().getPhone();
489    }
490
491    /**
492     * @return the phone associated with the background call
493     * of a particular subId
494     */
495    public Phone getBgPhone(int subId) {
496        return getFirstActiveBgCall(subId).getPhone();
497    }
498
499    /**
500     * @return the phone associated with the ringing call
501     */
502    public Phone getRingingPhone() {
503        return getFirstActiveRingingCall().getPhone();
504    }
505
506    /**
507     * @return the phone associated with the ringing call
508     * of a particular subId
509     */
510    public Phone getRingingPhone(int subId) {
511        return getFirstActiveRingingCall(subId).getPhone();
512    }
513
514    /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
515    public void setAudioMode() {
516        Context context = getContext();
517        if (context == null) return;
518        AudioManager audioManager = (AudioManager)
519                context.getSystemService(Context.AUDIO_SERVICE);
520
521        if (!isServiceStateInService() && !mIsEccDialing) {
522            if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
523                if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
524                // abandon audio focus after the mode has been set back to normal
525                audioManager.abandonAudioFocusForCall();
526                audioManager.setMode(AudioManager.MODE_NORMAL);
527            }
528            return;
529        }
530
531        // change the audio mode and request/abandon audio focus according to phone state,
532        // but only on audio mode transitions
533        switch (getState()) {
534            case RINGING:
535                int curAudioMode = audioManager.getMode();
536                if (curAudioMode != AudioManager.MODE_RINGTONE) {
537                    if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_RING");
538                    audioManager.requestAudioFocusForCall(AudioManager.STREAM_RING,
539                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
540                    if(!mSpeedUpAudioForMtCall) {
541                        audioManager.setMode(AudioManager.MODE_RINGTONE);
542                    }
543                }
544
545                if (mSpeedUpAudioForMtCall && (curAudioMode != AudioManager.MODE_IN_CALL)) {
546                    audioManager.setMode(AudioManager.MODE_IN_CALL);
547                }
548                break;
549            case OFFHOOK:
550                Phone offhookPhone = getFgPhone();
551                if (getActiveFgCallState() == Call.State.IDLE) {
552                    // There is no active Fg calls, the OFFHOOK state
553                    // is set by the Bg call. So set the phone to bgPhone.
554                    offhookPhone = getBgPhone();
555                }
556
557                int newAudioMode = AudioManager.MODE_IN_CALL;
558                if (offhookPhone instanceof SipPhone) {
559                    Rlog.d(LOG_TAG, "setAudioMode Set audio mode for SIP call!");
560                    // enable IN_COMMUNICATION audio mode instead for sipPhone
561                    newAudioMode = AudioManager.MODE_IN_COMMUNICATION;
562                }
563                int currMode = audioManager.getMode();
564                if (currMode != newAudioMode || mSpeedUpAudioForMtCall) {
565                    // request audio focus before setting the new mode
566                    if (VDBG) Rlog.d(LOG_TAG, "requestAudioFocus on STREAM_VOICE_CALL");
567                    audioManager.requestAudioFocusForCall(AudioManager.STREAM_VOICE_CALL,
568                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
569                    Rlog.d(LOG_TAG, "setAudioMode Setting audio mode from "
570                            + currMode + " to " + newAudioMode);
571                    audioManager.setMode(newAudioMode);
572                }
573                mSpeedUpAudioForMtCall = false;
574                break;
575            case IDLE:
576                if (audioManager.getMode() != AudioManager.MODE_NORMAL) {
577                    audioManager.setMode(AudioManager.MODE_NORMAL);
578                    if (VDBG) Rlog.d(LOG_TAG, "abandonAudioFocus");
579                    // abandon audio focus after the mode has been set back to normal
580                    audioManager.abandonAudioFocusForCall();
581                }
582                mSpeedUpAudioForMtCall = false;
583                break;
584        }
585        Rlog.d(LOG_TAG, "setAudioMode state = " + getState());
586    }
587    */
588
589    private Context getContext() {
590        Phone defaultPhone = getDefaultPhone();
591        return ((defaultPhone == null) ? null : defaultPhone.getContext());
592    }
593
594    public Object getRegistrantIdentifier() {
595        return mRegistrantidentifier;
596    }
597
598    private void registerForPhoneStates(Phone phone) {
599        // We need to keep a mapping of handler to Phone for proper unregistration.
600        // TODO: Clean up this solution as it is just a work around for each Phone instance
601        // using the same Handler to register with the RIL. When time permits, we should consider
602        // moving the handler (or the reference ot the handler) into the Phone object.
603        // See b/17414427.
604        CallManagerHandler handler = mHandlerMap.get(phone);
605        if (handler != null) {
606            Rlog.d(LOG_TAG, "This phone has already been registered.");
607            return;
608        }
609
610        // New registration, create a new handler instance and register the phone.
611        handler = new CallManagerHandler();
612        mHandlerMap.put(phone, handler);
613
614        // for common events supported by all phones
615        // The mRegistrantIdentifier passed here, is to identify in the PhoneBase
616        // that the registrants are coming from the CallManager.
617        phone.registerForPreciseCallStateChanged(handler, EVENT_PRECISE_CALL_STATE_CHANGED,
618                mRegistrantidentifier);
619        phone.registerForDisconnect(handler, EVENT_DISCONNECT,
620                mRegistrantidentifier);
621        phone.registerForNewRingingConnection(handler, EVENT_NEW_RINGING_CONNECTION,
622                mRegistrantidentifier);
623        phone.registerForUnknownConnection(handler, EVENT_UNKNOWN_CONNECTION,
624                mRegistrantidentifier);
625        phone.registerForIncomingRing(handler, EVENT_INCOMING_RING,
626                mRegistrantidentifier);
627        phone.registerForRingbackTone(handler, EVENT_RINGBACK_TONE,
628                mRegistrantidentifier);
629        phone.registerForInCallVoicePrivacyOn(handler, EVENT_IN_CALL_VOICE_PRIVACY_ON,
630                mRegistrantidentifier);
631        phone.registerForInCallVoicePrivacyOff(handler, EVENT_IN_CALL_VOICE_PRIVACY_OFF,
632                mRegistrantidentifier);
633        phone.registerForDisplayInfo(handler, EVENT_DISPLAY_INFO,
634                mRegistrantidentifier);
635        phone.registerForSignalInfo(handler, EVENT_SIGNAL_INFO,
636                mRegistrantidentifier);
637        phone.registerForResendIncallMute(handler, EVENT_RESEND_INCALL_MUTE,
638                mRegistrantidentifier);
639        phone.registerForMmiInitiate(handler, EVENT_MMI_INITIATE,
640                mRegistrantidentifier);
641        phone.registerForMmiComplete(handler, EVENT_MMI_COMPLETE,
642                mRegistrantidentifier);
643        phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED,
644                mRegistrantidentifier);
645        phone.registerForServiceStateChanged(handler, EVENT_SERVICE_STATE_CHANGED,
646                mRegistrantidentifier);
647
648        // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
649        //phone.registerForRadioOffOrNotAvailable(handler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
650
651        // for events supported only by GSM, CDMA and IMS phone
652        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
653                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
654                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
655            phone.setOnPostDialCharacter(handler, EVENT_POST_DIAL_CHARACTER, null);
656        }
657
658        // for events supported only by CDMA phone
659        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){
660            phone.registerForCdmaOtaStatusChange(handler, EVENT_CDMA_OTA_STATUS_CHANGE, null);
661            phone.registerForSubscriptionInfoReady(handler, EVENT_SUBSCRIPTION_INFO_READY, null);
662            phone.registerForCallWaiting(handler, EVENT_CALL_WAITING, null);
663            phone.registerForEcmTimerReset(handler, EVENT_ECM_TIMER_RESET, null);
664        }
665
666        // for events supported only by IMS phone
667        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
668            phone.registerForOnHoldTone(handler, EVENT_ONHOLD_TONE, null);
669            phone.registerForSuppServiceFailed(handler, EVENT_SUPP_SERVICE_FAILED, null);
670            phone.registerForTtyModeReceived(handler, EVENT_TTY_MODE_RECEIVED, null);
671        }
672    }
673
674    private void unregisterForPhoneStates(Phone phone) {
675        // Make sure that we clean up our map of handlers to Phones.
676        CallManagerHandler handler = mHandlerMap.get(phone);
677        if (handler != null) {
678            Rlog.e(LOG_TAG, "Could not find Phone handler for unregistration");
679            return;
680        }
681        mHandlerMap.remove(phone);
682
683        //  for common events supported by all phones
684        phone.unregisterForPreciseCallStateChanged(handler);
685        phone.unregisterForDisconnect(handler);
686        phone.unregisterForNewRingingConnection(handler);
687        phone.unregisterForUnknownConnection(handler);
688        phone.unregisterForIncomingRing(handler);
689        phone.unregisterForRingbackTone(handler);
690        phone.unregisterForInCallVoicePrivacyOn(handler);
691        phone.unregisterForInCallVoicePrivacyOff(handler);
692        phone.unregisterForDisplayInfo(handler);
693        phone.unregisterForSignalInfo(handler);
694        phone.unregisterForResendIncallMute(handler);
695        phone.unregisterForMmiInitiate(handler);
696        phone.unregisterForMmiComplete(handler);
697        phone.unregisterForSuppServiceFailed(handler);
698        phone.unregisterForServiceStateChanged(handler);
699        phone.unregisterForTtyModeReceived(handler);
700        // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
701        //phone.unregisterForRadioOffOrNotAvailable(handler);
702
703        // for events supported only by GSM, CDMA and IMS phone
704        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
705                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ||
706                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
707            phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null);
708        }
709
710        // for events supported only by CDMA phone
711        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA ){
712            phone.unregisterForCdmaOtaStatusChange(handler);
713            phone.unregisterForSubscriptionInfoReady(handler);
714            phone.unregisterForCallWaiting(handler);
715            phone.unregisterForEcmTimerReset(handler);
716        }
717
718        // for events supported only by IMS phone
719        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
720            phone.unregisterForOnHoldTone(handler);
721            phone.unregisterForSuppServiceFailed(handler);
722        }
723    }
724
725    /**
726     * Answers a ringing or waiting call.
727     *
728     * Active call, if any, go on hold.
729     * If active call can't be held, i.e., a background call of the same channel exists,
730     * the active call will be hang up.
731     *
732     * Answering occurs asynchronously, and final notification occurs via
733     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
734     * java.lang.Object) registerForPreciseCallStateChanged()}.
735     *
736     * @exception CallStateException when call is not ringing or waiting
737     */
738    public void acceptCall(Call ringingCall) throws CallStateException {
739        Phone ringingPhone = ringingCall.getPhone();
740
741        if (VDBG) {
742            Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")");
743            Rlog.d(LOG_TAG, toString());
744        }
745
746        if ( hasActiveFgCall() ) {
747            Phone activePhone = getActiveFgCall().getPhone();
748            boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
749            boolean sameChannel = (activePhone == ringingPhone);
750
751            if (VDBG) {
752                Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
753            }
754
755            if (sameChannel && hasBgCall) {
756                getActiveFgCall().hangup();
757            } else if (!sameChannel && !hasBgCall) {
758                activePhone.switchHoldingAndActive();
759            } else if (!sameChannel && hasBgCall) {
760                getActiveFgCall().hangup();
761            }
762        }
763
764        // We only support the AUDIO_ONLY video state in this scenario.
765        ringingPhone.acceptCall(VideoProfile.STATE_AUDIO_ONLY);
766
767        if (VDBG) {
768            Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")");
769            Rlog.d(LOG_TAG, toString());
770        }
771    }
772
773    /**
774     * Reject (ignore) a ringing call. In GSM, this means UDUB
775     * (User Determined User Busy). Reject occurs asynchronously,
776     * and final notification occurs via
777     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
778     * java.lang.Object) registerForPreciseCallStateChanged()}.
779     *
780     * @exception CallStateException when no call is ringing or waiting
781     */
782    public void rejectCall(Call ringingCall) throws CallStateException {
783        if (VDBG) {
784            Rlog.d(LOG_TAG, "rejectCall(" +ringingCall + ")");
785            Rlog.d(LOG_TAG, toString());
786        }
787
788        Phone ringingPhone = ringingCall.getPhone();
789
790        ringingPhone.rejectCall();
791
792        if (VDBG) {
793            Rlog.d(LOG_TAG, "End rejectCall(" +ringingCall + ")");
794            Rlog.d(LOG_TAG, toString());
795        }
796    }
797
798    /**
799     * Places active call on hold, and makes held call active.
800     * Switch occurs asynchronously and may fail.
801     *
802     * There are 4 scenarios
803     * 1. only active call but no held call, aka, hold
804     * 2. no active call but only held call, aka, unhold
805     * 3. both active and held calls from same phone, aka, swap
806     * 4. active and held calls from different phones, aka, phone swap
807     *
808     * Final notification occurs via
809     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
810     * java.lang.Object) registerForPreciseCallStateChanged()}.
811     *
812     * @exception CallStateException if active call is ringing, waiting, or
813     * dialing/alerting, or heldCall can't be active.
814     * In these cases, this operation may not be performed.
815     */
816    public void switchHoldingAndActive(Call heldCall) throws CallStateException {
817        Phone activePhone = null;
818        Phone heldPhone = null;
819
820        if (VDBG) {
821            Rlog.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")");
822            Rlog.d(LOG_TAG, toString());
823        }
824
825        if (hasActiveFgCall()) {
826            activePhone = getActiveFgCall().getPhone();
827        }
828
829        if (heldCall != null) {
830            heldPhone = heldCall.getPhone();
831        }
832
833        if (activePhone != null) {
834            activePhone.switchHoldingAndActive();
835        }
836
837        if (heldPhone != null && heldPhone != activePhone) {
838            heldPhone.switchHoldingAndActive();
839        }
840
841        if (VDBG) {
842            Rlog.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")");
843            Rlog.d(LOG_TAG, toString());
844        }
845    }
846
847    /**
848     * Hangup foreground call and resume the specific background call
849     *
850     * Note: this is noop if there is no foreground call or the heldCall is null
851     *
852     * @param heldCall to become foreground
853     * @throws CallStateException
854     */
855    public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
856        Phone foregroundPhone = null;
857        Phone backgroundPhone = null;
858
859        if (VDBG) {
860            Rlog.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")");
861            Rlog.d(LOG_TAG, toString());
862        }
863
864        if (hasActiveFgCall()) {
865            foregroundPhone = getFgPhone();
866            if (heldCall != null) {
867                backgroundPhone = heldCall.getPhone();
868                if (foregroundPhone == backgroundPhone) {
869                    getActiveFgCall().hangup();
870                } else {
871                // the call to be hangup and resumed belongs to different phones
872                    getActiveFgCall().hangup();
873                    switchHoldingAndActive(heldCall);
874                }
875            }
876        }
877
878        if (VDBG) {
879            Rlog.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")");
880            Rlog.d(LOG_TAG, toString());
881        }
882    }
883
884    /**
885     * Whether or not the phone can conference in the current phone
886     * state--that is, one call holding and one call active.
887     * @return true if the phone can conference; false otherwise.
888     */
889    public boolean canConference(Call heldCall) {
890        Phone activePhone = null;
891        Phone heldPhone = null;
892
893        if (hasActiveFgCall()) {
894            activePhone = getActiveFgCall().getPhone();
895        }
896
897        if (heldCall != null) {
898            heldPhone = heldCall.getPhone();
899        }
900
901        return heldPhone.getClass().equals(activePhone.getClass());
902    }
903
904    /**
905     * Whether or not the phone can conference in the current phone
906     * state--that is, one call holding and one call active.
907     * This method consider the phone object which is specific
908     * to the provided subId.
909     * @return true if the phone can conference; false otherwise.
910     */
911    public boolean canConference(Call heldCall, int subId) {
912        Phone activePhone = null;
913        Phone heldPhone = null;
914
915        if (hasActiveFgCall(subId)) {
916            activePhone = getActiveFgCall(subId).getPhone();
917        }
918
919        if (heldCall != null) {
920            heldPhone = heldCall.getPhone();
921        }
922
923        return heldPhone.getClass().equals(activePhone.getClass());
924    }
925
926    /**
927     * Conferences holding and active. Conference occurs asynchronously
928     * and may fail. Final notification occurs via
929     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
930     * java.lang.Object) registerForPreciseCallStateChanged()}.
931     *
932     * @exception CallStateException if canConference() would return false.
933     * In these cases, this operation may not be performed.
934     */
935    public void conference(Call heldCall) throws CallStateException {
936        int subId  = heldCall.getPhone().getSubId();
937
938        if (VDBG) {
939            Rlog.d(LOG_TAG, "conference(" +heldCall + ")");
940            Rlog.d(LOG_TAG, toString());
941        }
942
943        Phone fgPhone = getFgPhone(subId);
944        if (fgPhone != null) {
945            if (fgPhone instanceof SipPhone) {
946                ((SipPhone) fgPhone).conference(heldCall);
947            } else if (canConference(heldCall)) {
948                fgPhone.conference();
949            } else {
950                throw(new CallStateException("Can't conference foreground and selected background call"));
951            }
952        } else {
953            Rlog.d(LOG_TAG, "conference: fgPhone=null");
954        }
955
956        if (VDBG) {
957            Rlog.d(LOG_TAG, "End conference(" +heldCall + ")");
958            Rlog.d(LOG_TAG, toString());
959        }
960
961    }
962
963    /**
964     * Initiate a new voice connection. This happens asynchronously, so you
965     * cannot assume the audio path is connected (or a call index has been
966     * assigned) until PhoneStateChanged notification has occurred.
967     *
968     * @exception CallStateException if a new outgoing call is not currently
969     * possible because no more call slots exist or a call exists that is
970     * dialing, alerting, ringing, or waiting.  Other errors are
971     * handled asynchronously.
972     */
973    public Connection dial(Phone phone, String dialString, int videoState)
974            throws CallStateException {
975        Phone basePhone = getPhoneBase(phone);
976        int subId = phone.getSubId();
977        Connection result;
978
979        if (VDBG) {
980            Rlog.d(LOG_TAG, " dial(" + basePhone + ", "+ dialString + ")" +
981                    " subId = " + subId);
982            Rlog.d(LOG_TAG, toString());
983        }
984
985        if (!canDial(phone)) {
986            /*
987             * canDial function only checks whether the phone can make a new call.
988             * InCall MMI commmands are basically supplementary services
989             * within a call eg: call hold, call deflection, explicit call transfer etc.
990             */
991            String newDialString = PhoneNumberUtils.stripSeparators(dialString);
992            if (basePhone.handleInCallMmiCommands(newDialString)) {
993                return null;
994            } else {
995                throw new CallStateException("cannot dial in current state");
996            }
997        }
998
999        if ( hasActiveFgCall(subId) ) {
1000            Phone activePhone = getActiveFgCall(subId).getPhone();
1001            boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
1002
1003            if (DBG) {
1004                Rlog.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone));
1005            }
1006
1007            // Manipulation between IMS phone and its owner
1008            // will be treated in GSM/CDMA phone.
1009            Phone vPhone = basePhone.getImsPhone();
1010            if (activePhone != basePhone
1011                    && (vPhone == null || vPhone != activePhone)) {
1012                if (hasBgCall) {
1013                    Rlog.d(LOG_TAG, "Hangup");
1014                    getActiveFgCall(subId).hangup();
1015                } else {
1016                    Rlog.d(LOG_TAG, "Switch");
1017                    activePhone.switchHoldingAndActive();
1018                }
1019            }
1020        }
1021
1022        // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
1023        //mIsEccDialing = PhoneNumberUtils.isEmergencyNumber(dialString);
1024
1025        result = basePhone.dial(dialString, videoState);
1026
1027        if (VDBG) {
1028            Rlog.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")");
1029            Rlog.d(LOG_TAG, toString());
1030        }
1031
1032        return result;
1033    }
1034
1035    /**
1036     * Initiate a new voice connection. This happens asynchronously, so you
1037     * cannot assume the audio path is connected (or a call index has been
1038     * assigned) until PhoneStateChanged notification has occurred.
1039     *
1040     * @exception CallStateException if a new outgoing call is not currently
1041     * possible because no more call slots exist or a call exists that is
1042     * dialing, alerting, ringing, or waiting.  Other errors are
1043     * handled asynchronously.
1044     */
1045    public Connection dial(Phone phone, String dialString, UUSInfo uusInfo, int videoState)
1046            throws CallStateException {
1047        return phone.dial(dialString, uusInfo, videoState, null);
1048    }
1049
1050    /**
1051     * clear disconnect connection for each phone
1052     */
1053    public void clearDisconnected() {
1054        for(Phone phone : mPhones) {
1055            phone.clearDisconnected();
1056        }
1057    }
1058
1059    /**
1060     * clear disconnect connection for a phone specific
1061     * to the provided subId
1062     */
1063    public void clearDisconnected(int subId) {
1064        for(Phone phone : mPhones) {
1065            if (phone.getSubId() == subId) {
1066                phone.clearDisconnected();
1067            }
1068        }
1069    }
1070
1071    /**
1072     * Phone can make a call only if ALL of the following are true:
1073     *        - Phone is not powered off
1074     *        - There's no incoming or waiting call
1075     *        - The foreground call is ACTIVE or IDLE or DISCONNECTED.
1076     *          (We mainly need to make sure it *isn't* DIALING or ALERTING.)
1077     * @param phone
1078     * @return true if the phone can make a new call
1079     */
1080    private boolean canDial(Phone phone) {
1081        int serviceState = phone.getServiceState().getState();
1082        int subId = phone.getSubId();
1083        boolean hasRingingCall = hasActiveRingingCall();
1084        Call.State fgCallState = getActiveFgCallState(subId);
1085
1086        boolean result = (serviceState != ServiceState.STATE_POWER_OFF
1087                && !hasRingingCall
1088                && ((fgCallState == Call.State.ACTIVE)
1089                    || (fgCallState == Call.State.IDLE)
1090                    || (fgCallState == Call.State.DISCONNECTED)
1091                    /*As per 3GPP TS 51.010-1 section 31.13.1.4
1092                    call should be alowed when the foreground
1093                    call is in ALERTING state*/
1094                    || (fgCallState == Call.State.ALERTING)));
1095
1096        if (result == false) {
1097            Rlog.d(LOG_TAG, "canDial serviceState=" + serviceState
1098                            + " hasRingingCall=" + hasRingingCall
1099                            + " fgCallState=" + fgCallState);
1100        }
1101        return result;
1102    }
1103
1104    /**
1105     * Whether or not the phone can do explicit call transfer in the current
1106     * phone state--that is, one call holding and one call active.
1107     * @return true if the phone can do explicit call transfer; false otherwise.
1108     */
1109    public boolean canTransfer(Call heldCall) {
1110        Phone activePhone = null;
1111        Phone heldPhone = null;
1112
1113        if (hasActiveFgCall()) {
1114            activePhone = getActiveFgCall().getPhone();
1115        }
1116
1117        if (heldCall != null) {
1118            heldPhone = heldCall.getPhone();
1119        }
1120
1121        return (heldPhone == activePhone && activePhone.canTransfer());
1122    }
1123
1124    /**
1125     * Whether or not the phone specific to subId can do explicit call transfer
1126     * in the current phone state--that is, one call holding and one call active.
1127     * @return true if the phone can do explicit call transfer; false otherwise.
1128     */
1129    public boolean canTransfer(Call heldCall, int subId) {
1130        Phone activePhone = null;
1131        Phone heldPhone = null;
1132
1133        if (hasActiveFgCall(subId)) {
1134            activePhone = getActiveFgCall(subId).getPhone();
1135        }
1136
1137        if (heldCall != null) {
1138            heldPhone = heldCall.getPhone();
1139        }
1140
1141        return (heldPhone == activePhone && activePhone.canTransfer());
1142    }
1143
1144    /**
1145     * Connects the held call and active call
1146     * Disconnects the subscriber from both calls
1147     *
1148     * Explicit Call Transfer occurs asynchronously
1149     * and may fail. Final notification occurs via
1150     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1151     * java.lang.Object) registerForPreciseCallStateChanged()}.
1152     *
1153     * @exception CallStateException if canTransfer() would return false.
1154     * In these cases, this operation may not be performed.
1155     */
1156    public void explicitCallTransfer(Call heldCall) throws CallStateException {
1157        if (VDBG) {
1158            Rlog.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")");
1159            Rlog.d(LOG_TAG, toString());
1160        }
1161
1162        if (canTransfer(heldCall)) {
1163            heldCall.getPhone().explicitCallTransfer();
1164        }
1165
1166        if (VDBG) {
1167            Rlog.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")");
1168            Rlog.d(LOG_TAG, toString());
1169        }
1170
1171    }
1172
1173    /**
1174     * Returns a list of MMI codes that are pending for a phone. (They have initiated
1175     * but have not yet completed).
1176     * Presently there is only ever one.
1177     *
1178     * Use <code>registerForMmiInitiate</code>
1179     * and <code>registerForMmiComplete</code> for change notification.
1180     * @return null if phone doesn't have or support mmi code
1181     */
1182    public List<? extends MmiCode> getPendingMmiCodes(Phone phone) {
1183        Rlog.e(LOG_TAG, "getPendingMmiCodes not implemented");
1184        return null;
1185    }
1186
1187    /**
1188     * Sends user response to a USSD REQUEST message.  An MmiCode instance
1189     * representing this response is sent to handlers registered with
1190     * registerForMmiInitiate.
1191     *
1192     * @param ussdMessge    Message to send in the response.
1193     * @return false if phone doesn't support ussd service
1194     */
1195    public boolean sendUssdResponse(Phone phone, String ussdMessge) {
1196        Rlog.e(LOG_TAG, "sendUssdResponse not implemented");
1197        return false;
1198    }
1199
1200    /**
1201     * Mutes or unmutes the microphone for the active call. The microphone
1202     * is automatically unmuted if a call is answered, dialed, or resumed
1203     * from a holding state.
1204     *
1205     * @param muted true to mute the microphone,
1206     * false to activate the microphone.
1207     */
1208
1209    public void setMute(boolean muted) {
1210        if (VDBG) {
1211            Rlog.d(LOG_TAG, " setMute(" + muted + ")");
1212            Rlog.d(LOG_TAG, toString());
1213        }
1214
1215        if (hasActiveFgCall()) {
1216            getActiveFgCall().getPhone().setMute(muted);
1217        }
1218
1219        if (VDBG) {
1220            Rlog.d(LOG_TAG, "End setMute(" + muted + ")");
1221            Rlog.d(LOG_TAG, toString());
1222        }
1223    }
1224
1225    /**
1226     * Gets current mute status. Use
1227     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
1228     * java.lang.Object) registerForPreciseCallStateChanged()}
1229     * as a change notifcation, although presently phone state changed is not
1230     * fired when setMute() is called.
1231     *
1232     * @return true is muting, false is unmuting
1233     */
1234    public boolean getMute() {
1235        if (hasActiveFgCall()) {
1236            return getActiveFgCall().getPhone().getMute();
1237        } else if (hasActiveBgCall()) {
1238            return getFirstActiveBgCall().getPhone().getMute();
1239        }
1240        return false;
1241    }
1242
1243    /**
1244     * Enables or disables echo suppression.
1245     */
1246    public void setEchoSuppressionEnabled() {
1247        if (VDBG) {
1248            Rlog.d(LOG_TAG, " setEchoSuppression()");
1249            Rlog.d(LOG_TAG, toString());
1250        }
1251
1252        if (hasActiveFgCall()) {
1253            getActiveFgCall().getPhone().setEchoSuppressionEnabled();
1254        }
1255
1256        if (VDBG) {
1257            Rlog.d(LOG_TAG, "End setEchoSuppression()");
1258            Rlog.d(LOG_TAG, toString());
1259        }
1260    }
1261
1262    /**
1263     * Play a DTMF tone on the active call.
1264     *
1265     * @param c should be one of 0-9, '*' or '#'. Other values will be
1266     * silently ignored.
1267     * @return false if no active call or the active call doesn't support
1268     *         dtmf tone
1269     */
1270    public boolean sendDtmf(char c) {
1271        boolean result = false;
1272
1273        if (VDBG) {
1274            Rlog.d(LOG_TAG, " sendDtmf(" + c + ")");
1275            Rlog.d(LOG_TAG, toString());
1276        }
1277
1278        if (hasActiveFgCall()) {
1279            getActiveFgCall().getPhone().sendDtmf(c);
1280            result = true;
1281        }
1282
1283        if (VDBG) {
1284            Rlog.d(LOG_TAG, "End sendDtmf(" + c + ")");
1285            Rlog.d(LOG_TAG, toString());
1286        }
1287        return result;
1288    }
1289
1290    /**
1291     * Start to paly a DTMF tone on the active call.
1292     * or there is a playing DTMF tone.
1293     * @param c should be one of 0-9, '*' or '#'. Other values will be
1294     * silently ignored.
1295     *
1296     * @return false if no active call or the active call doesn't support
1297     *         dtmf tone
1298     */
1299    public boolean startDtmf(char c) {
1300        boolean result = false;
1301
1302        if (VDBG) {
1303            Rlog.d(LOG_TAG, " startDtmf(" + c + ")");
1304            Rlog.d(LOG_TAG, toString());
1305        }
1306
1307        if (hasActiveFgCall()) {
1308            getActiveFgCall().getPhone().startDtmf(c);
1309            result = true;
1310        }
1311
1312        if (VDBG) {
1313            Rlog.d(LOG_TAG, "End startDtmf(" + c + ")");
1314            Rlog.d(LOG_TAG, toString());
1315        }
1316
1317        return result;
1318    }
1319
1320    /**
1321     * Stop the playing DTMF tone. Ignored if there is no playing DTMF
1322     * tone or no active call.
1323     */
1324    public void stopDtmf() {
1325        if (VDBG) {
1326            Rlog.d(LOG_TAG, " stopDtmf()" );
1327            Rlog.d(LOG_TAG, toString());
1328        }
1329
1330        if (hasActiveFgCall()) getFgPhone().stopDtmf();
1331
1332        if (VDBG) {
1333            Rlog.d(LOG_TAG, "End stopDtmf()");
1334            Rlog.d(LOG_TAG, toString());
1335        }
1336    }
1337
1338    /**
1339     * send burst DTMF tone, it can send the string as single character or multiple character
1340     * ignore if there is no active call or not valid digits string.
1341     * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
1342     * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
1343     * this api can send single character and multiple character, also, this api has response
1344     * back to caller.
1345     *
1346     * @param dtmfString is string representing the dialing digit(s) in the active call
1347     * @param on the DTMF ON length in milliseconds, or 0 for default
1348     * @param off the DTMF OFF length in milliseconds, or 0 for default
1349     * @param onComplete is the callback message when the action is processed by BP
1350     *
1351     */
1352    public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1353        if (hasActiveFgCall()) {
1354            getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
1355            return true;
1356        }
1357        return false;
1358    }
1359
1360    /**
1361     * Notifies when a voice connection has disconnected, either due to local
1362     * or remote hangup or error.
1363     *
1364     *  Messages received from this will have the following members:<p>
1365     *  <ul><li>Message.obj will be an AsyncResult</li>
1366     *  <li>AsyncResult.userObj = obj</li>
1367     *  <li>AsyncResult.result = a Connection object that is
1368     *  no longer connected.</li></ul>
1369     */
1370    public void registerForDisconnect(Handler h, int what, Object obj) {
1371        mDisconnectRegistrants.addUnique(h, what, obj);
1372    }
1373
1374    /**
1375     * Unregisters for voice disconnection notification.
1376     * Extraneous calls are tolerated silently
1377     */
1378    public void unregisterForDisconnect(Handler h){
1379        mDisconnectRegistrants.remove(h);
1380    }
1381
1382    /**
1383     * Register for getting notifications for change in the Call State {@link Call.State}
1384     * This is called PreciseCallState because the call state is more precise than what
1385     * can be obtained using the {@link PhoneStateListener}
1386     *
1387     * Resulting events will have an AsyncResult in <code>Message.obj</code>.
1388     * AsyncResult.userData will be set to the obj argument here.
1389     * The <em>h</em> parameter is held only by a weak reference.
1390     */
1391    public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1392        mPreciseCallStateRegistrants.addUnique(h, what, obj);
1393    }
1394
1395    /**
1396     * Unregisters for voice call state change notifications.
1397     * Extraneous calls are tolerated silently.
1398     */
1399    public void unregisterForPreciseCallStateChanged(Handler h){
1400        mPreciseCallStateRegistrants.remove(h);
1401    }
1402
1403    /**
1404     * Notifies when a previously untracked non-ringing/waiting connection has appeared.
1405     * This is likely due to some other entity (eg, SIM card application) initiating a call.
1406     */
1407    public void registerForUnknownConnection(Handler h, int what, Object obj){
1408        mUnknownConnectionRegistrants.addUnique(h, what, obj);
1409    }
1410
1411    /**
1412     * Unregisters for unknown connection notifications.
1413     */
1414    public void unregisterForUnknownConnection(Handler h){
1415        mUnknownConnectionRegistrants.remove(h);
1416    }
1417
1418
1419    /**
1420     * Notifies when a new ringing or waiting connection has appeared.<p>
1421     *
1422     *  Messages received from this:
1423     *  Message.obj will be an AsyncResult
1424     *  AsyncResult.userObj = obj
1425     *  AsyncResult.result = a Connection. <p>
1426     *  Please check Connection.isRinging() to make sure the Connection
1427     *  has not dropped since this message was posted.
1428     *  If Connection.isRinging() is true, then
1429     *   Connection.getCall() == Phone.getRingingCall()
1430     */
1431    public void registerForNewRingingConnection(Handler h, int what, Object obj){
1432        mNewRingingConnectionRegistrants.addUnique(h, what, obj);
1433    }
1434
1435    /**
1436     * Unregisters for new ringing connection notification.
1437     * Extraneous calls are tolerated silently
1438     */
1439
1440    public void unregisterForNewRingingConnection(Handler h){
1441        mNewRingingConnectionRegistrants.remove(h);
1442    }
1443
1444    /**
1445     * Notifies when an incoming call rings.<p>
1446     *
1447     *  Messages received from this:
1448     *  Message.obj will be an AsyncResult
1449     *  AsyncResult.userObj = obj
1450     *  AsyncResult.result = a Connection. <p>
1451     */
1452    public void registerForIncomingRing(Handler h, int what, Object obj){
1453        mIncomingRingRegistrants.addUnique(h, what, obj);
1454    }
1455
1456    /**
1457     * Unregisters for ring notification.
1458     * Extraneous calls are tolerated silently
1459     */
1460
1461    public void unregisterForIncomingRing(Handler h){
1462        mIncomingRingRegistrants.remove(h);
1463    }
1464
1465    /**
1466     * Notifies when out-band ringback tone is needed.<p>
1467     *
1468     *  Messages received from this:
1469     *  Message.obj will be an AsyncResult
1470     *  AsyncResult.userObj = obj
1471     *  AsyncResult.result = boolean, true to start play ringback tone
1472     *                       and false to stop. <p>
1473     */
1474    public void registerForRingbackTone(Handler h, int what, Object obj){
1475        mRingbackToneRegistrants.addUnique(h, what, obj);
1476    }
1477
1478    /**
1479     * Unregisters for ringback tone notification.
1480     */
1481
1482    public void unregisterForRingbackTone(Handler h){
1483        mRingbackToneRegistrants.remove(h);
1484    }
1485
1486    /**
1487     * Notifies when out-band on-hold tone is needed.<p>
1488     *
1489     *  Messages received from this:
1490     *  Message.obj will be an AsyncResult
1491     *  AsyncResult.userObj = obj
1492     *  AsyncResult.result = boolean, true to start play on-hold tone
1493     *                       and false to stop. <p>
1494     */
1495    public void registerForOnHoldTone(Handler h, int what, Object obj){
1496        mOnHoldToneRegistrants.addUnique(h, what, obj);
1497    }
1498
1499    /**
1500     * Unregisters for on-hold tone notification.
1501     */
1502
1503    public void unregisterForOnHoldTone(Handler h){
1504        mOnHoldToneRegistrants.remove(h);
1505    }
1506
1507    /**
1508     * Registers the handler to reset the uplink mute state to get
1509     * uplink audio.
1510     */
1511    public void registerForResendIncallMute(Handler h, int what, Object obj){
1512        mResendIncallMuteRegistrants.addUnique(h, what, obj);
1513    }
1514
1515    /**
1516     * Unregisters for resend incall mute notifications.
1517     */
1518    public void unregisterForResendIncallMute(Handler h){
1519        mResendIncallMuteRegistrants.remove(h);
1520    }
1521
1522    /**
1523     * Register for notifications of initiation of a new MMI code request.
1524     * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
1525     *
1526     * Example: If Phone.dial is called with "*#31#", then the app will
1527     * be notified here.<p>
1528     *
1529     * The returned <code>Message.obj</code> will contain an AsyncResult.
1530     *
1531     * <code>obj.result</code> will be an "MmiCode" object.
1532     */
1533    public void registerForMmiInitiate(Handler h, int what, Object obj){
1534        mMmiInitiateRegistrants.addUnique(h, what, obj);
1535    }
1536
1537    /**
1538     * Unregisters for new MMI initiate notification.
1539     * Extraneous calls are tolerated silently
1540     */
1541    public void unregisterForMmiInitiate(Handler h){
1542        mMmiInitiateRegistrants.remove(h);
1543    }
1544
1545    /**
1546     * Register for notifications that an MMI request has completed
1547     * its network activity and is in its final state. This may mean a state
1548     * of COMPLETE, FAILED, or CANCELLED.
1549     *
1550     * <code>Message.obj</code> will contain an AsyncResult.
1551     * <code>obj.result</code> will be an "MmiCode" object
1552     */
1553    public void registerForMmiComplete(Handler h, int what, Object obj){
1554        mMmiCompleteRegistrants.addUnique(h, what, obj);
1555    }
1556
1557    /**
1558     * Unregisters for MMI complete notification.
1559     * Extraneous calls are tolerated silently
1560     */
1561    public void unregisterForMmiComplete(Handler h){
1562        mMmiCompleteRegistrants.remove(h);
1563    }
1564
1565    /**
1566     * Registration point for Ecm timer reset
1567     * @param h handler to notify
1568     * @param what user-defined message code
1569     * @param obj placed in Message.obj
1570     */
1571    public void registerForEcmTimerReset(Handler h, int what, Object obj){
1572        mEcmTimerResetRegistrants.addUnique(h, what, obj);
1573    }
1574
1575    /**
1576     * Unregister for notification for Ecm timer reset
1577     * @param h Handler to be removed from the registrant list.
1578     */
1579    public void unregisterForEcmTimerReset(Handler h){
1580        mEcmTimerResetRegistrants.remove(h);
1581    }
1582
1583    /**
1584     * Register for ServiceState changed.
1585     * Message.obj will contain an AsyncResult.
1586     * AsyncResult.result will be a ServiceState instance
1587     */
1588    public void registerForServiceStateChanged(Handler h, int what, Object obj){
1589        mServiceStateChangedRegistrants.addUnique(h, what, obj);
1590    }
1591
1592    /**
1593     * Unregisters for ServiceStateChange notification.
1594     * Extraneous calls are tolerated silently
1595     */
1596    public void unregisterForServiceStateChanged(Handler h){
1597        mServiceStateChangedRegistrants.remove(h);
1598    }
1599
1600    /**
1601     * Register for notifications when a supplementary service attempt fails.
1602     * Message.obj will contain an AsyncResult.
1603     *
1604     * @param h Handler that receives the notification message.
1605     * @param what User-defined message code.
1606     * @param obj User object.
1607     */
1608    public void registerForSuppServiceFailed(Handler h, int what, Object obj){
1609        mSuppServiceFailedRegistrants.addUnique(h, what, obj);
1610    }
1611
1612    /**
1613     * Unregister for notifications when a supplementary service attempt fails.
1614     * Extraneous calls are tolerated silently
1615     *
1616     * @param h Handler to be removed from the registrant list.
1617     */
1618    public void unregisterForSuppServiceFailed(Handler h){
1619        mSuppServiceFailedRegistrants.remove(h);
1620    }
1621
1622    /**
1623     * Register for notifications when a sInCall VoicePrivacy is enabled
1624     *
1625     * @param h Handler that receives the notification message.
1626     * @param what User-defined message code.
1627     * @param obj User object.
1628     */
1629    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
1630        mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj);
1631    }
1632
1633    /**
1634     * Unregister for notifications when a sInCall VoicePrivacy is enabled
1635     *
1636     * @param h Handler to be removed from the registrant list.
1637     */
1638    public void unregisterForInCallVoicePrivacyOn(Handler h){
1639        mInCallVoicePrivacyOnRegistrants.remove(h);
1640    }
1641
1642    /**
1643     * Register for notifications when a sInCall VoicePrivacy is disabled
1644     *
1645     * @param h Handler that receives the notification message.
1646     * @param what User-defined message code.
1647     * @param obj User object.
1648     */
1649    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
1650        mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj);
1651    }
1652
1653    /**
1654     * Unregister for notifications when a sInCall VoicePrivacy is disabled
1655     *
1656     * @param h Handler to be removed from the registrant list.
1657     */
1658    public void unregisterForInCallVoicePrivacyOff(Handler h){
1659        mInCallVoicePrivacyOffRegistrants.remove(h);
1660    }
1661
1662    /**
1663     * Register for notifications when CDMA call waiting comes
1664     *
1665     * @param h Handler that receives the notification message.
1666     * @param what User-defined message code.
1667     * @param obj User object.
1668     */
1669    public void registerForCallWaiting(Handler h, int what, Object obj){
1670        mCallWaitingRegistrants.addUnique(h, what, obj);
1671    }
1672
1673    /**
1674     * Unregister for notifications when CDMA Call waiting comes
1675     * @param h Handler to be removed from the registrant list.
1676     */
1677    public void unregisterForCallWaiting(Handler h){
1678        mCallWaitingRegistrants.remove(h);
1679    }
1680
1681
1682    /**
1683     * Register for signal information notifications from the network.
1684     * Message.obj will contain an AsyncResult.
1685     * AsyncResult.result will be a SuppServiceNotification instance.
1686     *
1687     * @param h Handler that receives the notification message.
1688     * @param what User-defined message code.
1689     * @param obj User object.
1690     */
1691
1692    public void registerForSignalInfo(Handler h, int what, Object obj){
1693        mSignalInfoRegistrants.addUnique(h, what, obj);
1694    }
1695
1696    /**
1697     * Unregisters for signal information notifications.
1698     * Extraneous calls are tolerated silently
1699     *
1700     * @param h Handler to be removed from the registrant list.
1701     */
1702    public void unregisterForSignalInfo(Handler h){
1703        mSignalInfoRegistrants.remove(h);
1704    }
1705
1706    /**
1707     * Register for display information notifications from the network.
1708     * Message.obj will contain an AsyncResult.
1709     * AsyncResult.result will be a SuppServiceNotification instance.
1710     *
1711     * @param h Handler that receives the notification message.
1712     * @param what User-defined message code.
1713     * @param obj User object.
1714     */
1715    public void registerForDisplayInfo(Handler h, int what, Object obj){
1716        mDisplayInfoRegistrants.addUnique(h, what, obj);
1717    }
1718
1719    /**
1720     * Unregisters for display information notifications.
1721     * Extraneous calls are tolerated silently
1722     *
1723     * @param h Handler to be removed from the registrant list.
1724     */
1725    public void unregisterForDisplayInfo(Handler h) {
1726        mDisplayInfoRegistrants.remove(h);
1727    }
1728
1729    /**
1730     * Register for notifications when CDMA OTA Provision status change
1731     *
1732     * @param h Handler that receives the notification message.
1733     * @param what User-defined message code.
1734     * @param obj User object.
1735     */
1736    public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){
1737        mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj);
1738    }
1739
1740    /**
1741     * Unregister for notifications when CDMA OTA Provision status change
1742     * @param h Handler to be removed from the registrant list.
1743     */
1744    public void unregisterForCdmaOtaStatusChange(Handler h){
1745        mCdmaOtaStatusChangeRegistrants.remove(h);
1746    }
1747
1748    /**
1749     * Registration point for subscription info ready
1750     * @param h handler to notify
1751     * @param what what code of message when delivered
1752     * @param obj placed in Message.obj
1753     */
1754    public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){
1755        mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj);
1756    }
1757
1758    /**
1759     * Unregister for notifications for subscription info
1760     * @param h Handler to be removed from the registrant list.
1761     */
1762    public void unregisterForSubscriptionInfoReady(Handler h){
1763        mSubscriptionInfoReadyRegistrants.remove(h);
1764    }
1765
1766    /**
1767     * Sets an event to be fired when the telephony system processes
1768     * a post-dial character on an outgoing call.<p>
1769     *
1770     * Messages of type <code>what</code> will be sent to <code>h</code>.
1771     * The <code>obj</code> field of these Message's will be instances of
1772     * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
1773     * a Connection object.<p>
1774     *
1775     * Message.arg1 will be the post dial character being processed,
1776     * or 0 ('\0') if end of string.<p>
1777     *
1778     * If Connection.getPostDialState() == WAIT,
1779     * the application must call
1780     * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
1781     * Connection.proceedAfterWaitChar()} or
1782     * {@link com.android.internal.telephony.Connection#cancelPostDial()
1783     * Connection.cancelPostDial()}
1784     * for the telephony system to continue playing the post-dial
1785     * DTMF sequence.<p>
1786     *
1787     * If Connection.getPostDialState() == WILD,
1788     * the application must call
1789     * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
1790     * Connection.proceedAfterWildChar()}
1791     * or
1792     * {@link com.android.internal.telephony.Connection#cancelPostDial()
1793     * Connection.cancelPostDial()}
1794     * for the telephony system to continue playing the
1795     * post-dial DTMF sequence.<p>
1796     *
1797     */
1798    public void registerForPostDialCharacter(Handler h, int what, Object obj){
1799        mPostDialCharacterRegistrants.addUnique(h, what, obj);
1800    }
1801
1802    public void unregisterForPostDialCharacter(Handler h){
1803        mPostDialCharacterRegistrants.remove(h);
1804    }
1805
1806    /**
1807     * Register for TTY mode change notifications from the network.
1808     * Message.obj will contain an AsyncResult.
1809     * AsyncResult.result will be an Integer containing new mode.
1810     *
1811     * @param h Handler that receives the notification message.
1812     * @param what User-defined message code.
1813     * @param obj User object.
1814     */
1815    public void registerForTtyModeReceived(Handler h, int what, Object obj){
1816        mTtyModeReceivedRegistrants.addUnique(h, what, obj);
1817    }
1818
1819    /**
1820     * Unregisters for TTY mode change notifications.
1821     * Extraneous calls are tolerated silently
1822     *
1823     * @param h Handler to be removed from the registrant list.
1824     */
1825    public void unregisterForTtyModeReceived(Handler h) {
1826        mTtyModeReceivedRegistrants.remove(h);
1827    }
1828
1829    /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls
1830     * 1. APIs to access list of calls
1831     * 2. APIs to check if any active call, which has connection other than
1832     * disconnected ones, pleaser refer to Call.isIdle()
1833     * 3. APIs to return first active call
1834     * 4. APIs to return the connections of first active call
1835     * 5. APIs to return other property of first active call
1836     */
1837
1838    /**
1839     * @return list of all ringing calls
1840     */
1841    public List<Call> getRingingCalls() {
1842        return Collections.unmodifiableList(mRingingCalls);
1843    }
1844
1845    /**
1846     * @return list of all foreground calls
1847     */
1848    public List<Call> getForegroundCalls() {
1849        return Collections.unmodifiableList(mForegroundCalls);
1850    }
1851
1852    /**
1853     * @return list of all background calls
1854     */
1855    public List<Call> getBackgroundCalls() {
1856        return Collections.unmodifiableList(mBackgroundCalls);
1857    }
1858
1859    /**
1860     * Return true if there is at least one active foreground call
1861     */
1862    public boolean hasActiveFgCall() {
1863        return (getFirstActiveCall(mForegroundCalls) != null);
1864    }
1865
1866    /**
1867     * Return true if there is at least one active foreground call
1868     * on a particular subId or an active sip call
1869     */
1870    public boolean hasActiveFgCall(int subId) {
1871        return (getFirstActiveCall(mForegroundCalls, subId) != null);
1872    }
1873
1874    /**
1875     * Return true if there is at least one active background call
1876     */
1877    public boolean hasActiveBgCall() {
1878        // TODO since hasActiveBgCall may get called often
1879        // better to cache it to improve performance
1880        return (getFirstActiveCall(mBackgroundCalls) != null);
1881    }
1882
1883    /**
1884     * Return true if there is at least one active background call
1885     * on a particular subId or an active sip call
1886     */
1887    public boolean hasActiveBgCall(int subId) {
1888        // TODO since hasActiveBgCall may get called often
1889        // better to cache it to improve performance
1890        return (getFirstActiveCall(mBackgroundCalls, subId) != null);
1891    }
1892
1893    /**
1894     * Return true if there is at least one active ringing call
1895     *
1896     */
1897    public boolean hasActiveRingingCall() {
1898        return (getFirstActiveCall(mRingingCalls) != null);
1899    }
1900
1901    /**
1902     * Return true if there is at least one active ringing call
1903     */
1904    public boolean hasActiveRingingCall(int subId) {
1905        return (getFirstActiveCall(mRingingCalls, subId) != null);
1906    }
1907
1908    /**
1909     * return the active foreground call from foreground calls
1910     *
1911     * Active call means the call is NOT in Call.State.IDLE
1912     *
1913     * 1. If there is active foreground call, return it
1914     * 2. If there is no active foreground call, return the
1915     *    foreground call associated with default phone, which state is IDLE.
1916     * 3. If there is no phone registered at all, return null.
1917     *
1918     */
1919    public Call getActiveFgCall() {
1920        Call call = getFirstNonIdleCall(mForegroundCalls);
1921        if (call == null) {
1922            call = (mDefaultPhone == null)
1923                    ? null
1924                    : mDefaultPhone.getForegroundCall();
1925        }
1926        return call;
1927    }
1928
1929    public Call getActiveFgCall(int subId) {
1930        Call call = getFirstNonIdleCall(mForegroundCalls, subId);
1931        if (call == null) {
1932            Phone phone = getPhone(subId);
1933            call = (phone == null)
1934                    ? null
1935                    : phone.getForegroundCall();
1936        }
1937        return call;
1938    }
1939
1940    // Returns the first call that is not in IDLE state. If both active calls
1941    // and disconnecting/disconnected calls exist, return the first active call.
1942    private Call getFirstNonIdleCall(List<Call> calls) {
1943        Call result = null;
1944        for (Call call : calls) {
1945            if (!call.isIdle()) {
1946                return call;
1947            } else if (call.getState() != Call.State.IDLE) {
1948                if (result == null) result = call;
1949            }
1950        }
1951        return result;
1952    }
1953
1954    // Returns the first call that is not in IDLE state. If both active calls
1955    // and disconnecting/disconnected calls exist, return the first active call.
1956    private Call getFirstNonIdleCall(List<Call> calls, int subId) {
1957        Call result = null;
1958        for (Call call : calls) {
1959            if ((call.getPhone().getSubId() == subId) ||
1960                    (call.getPhone() instanceof SipPhone)) {
1961                if (!call.isIdle()) {
1962                    return call;
1963                } else if (call.getState() != Call.State.IDLE) {
1964                    if (result == null) result = call;
1965                }
1966            }
1967        }
1968        return result;
1969    }
1970
1971    /**
1972     * return one active background call from background calls
1973     *
1974     * Active call means the call is NOT idle defined by Call.isIdle()
1975     *
1976     * 1. If there is only one active background call, return it
1977     * 2. If there is more than one active background call, return the first one
1978     * 3. If there is no active background call, return the background call
1979     *    associated with default phone, which state is IDLE.
1980     * 4. If there is no background call at all, return null.
1981     *
1982     * Complete background calls list can be get by getBackgroundCalls()
1983     */
1984    public Call getFirstActiveBgCall() {
1985        Call call = getFirstNonIdleCall(mBackgroundCalls);
1986        if (call == null) {
1987            call = (mDefaultPhone == null)
1988                    ? null
1989                    : mDefaultPhone.getBackgroundCall();
1990        }
1991        return call;
1992    }
1993
1994    /**
1995     * return one active background call from background calls of the
1996     * requested subId.
1997     *
1998     * Active call means the call is NOT idle defined by Call.isIdle()
1999     *
2000     * 1. If there is only one active background call on given sub or
2001     *    on SIP Phone, return it
2002     * 2. If there is more than one active background call, return the background call
2003     *    associated with the active sub.
2004     * 3. If there is no background call at all, return null.
2005     *
2006     * Complete background calls list can be get by getBackgroundCalls()
2007     */
2008    public Call getFirstActiveBgCall(int subId) {
2009        Phone phone = getPhone(subId);
2010        if (hasMoreThanOneHoldingCall(subId)) {
2011            return phone.getBackgroundCall();
2012        } else {
2013            Call call = getFirstNonIdleCall(mBackgroundCalls, subId);
2014            if (call == null) {
2015                call = (phone == null)
2016                        ? null
2017                        : phone.getBackgroundCall();
2018            }
2019            return call;
2020        }
2021    }
2022
2023    /**
2024     * return one active ringing call from ringing calls
2025     *
2026     * Active call means the call is NOT idle defined by Call.isIdle()
2027     *
2028     * 1. If there is only one active ringing call, return it
2029     * 2. If there is more than one active ringing call, return the first one
2030     * 3. If there is no active ringing call, return the ringing call
2031     *    associated with default phone, which state is IDLE.
2032     * 4. If there is no ringing call at all, return null.
2033     *
2034     * Complete ringing calls list can be get by getRingingCalls()
2035     */
2036    public Call getFirstActiveRingingCall() {
2037        Call call = getFirstNonIdleCall(mRingingCalls);
2038        if (call == null) {
2039            call = (mDefaultPhone == null)
2040                    ? null
2041                    : mDefaultPhone.getRingingCall();
2042        }
2043        return call;
2044    }
2045
2046    public Call getFirstActiveRingingCall(int subId) {
2047        Phone phone = getPhone(subId);
2048        Call call = getFirstNonIdleCall(mRingingCalls, subId);
2049        if (call == null) {
2050            call = (phone == null)
2051                    ? null
2052                    : phone.getRingingCall();
2053        }
2054        return call;
2055    }
2056
2057    /**
2058     * @return the state of active foreground call
2059     * return IDLE if there is no active foreground call
2060     */
2061    public Call.State getActiveFgCallState() {
2062        Call fgCall = getActiveFgCall();
2063
2064        if (fgCall != null) {
2065            return fgCall.getState();
2066        }
2067
2068        return Call.State.IDLE;
2069    }
2070
2071    public Call.State getActiveFgCallState(int subId) {
2072        Call fgCall = getActiveFgCall(subId);
2073
2074        if (fgCall != null) {
2075            return fgCall.getState();
2076        }
2077
2078        return Call.State.IDLE;
2079    }
2080
2081    /**
2082     * @return the connections of active foreground call
2083     * return empty list if there is no active foreground call
2084     */
2085    public List<Connection> getFgCallConnections() {
2086        Call fgCall = getActiveFgCall();
2087        if ( fgCall != null) {
2088            return fgCall.getConnections();
2089        }
2090        return mEmptyConnections;
2091    }
2092
2093    /**
2094     * @return the connections of active foreground call
2095     * return empty list if there is no active foreground call
2096     */
2097    public List<Connection> getFgCallConnections(int subId) {
2098        Call fgCall = getActiveFgCall(subId);
2099        if ( fgCall != null) {
2100            return fgCall.getConnections();
2101        }
2102        return mEmptyConnections;
2103    }
2104
2105    /**
2106     * @return the connections of active background call
2107     * return empty list if there is no active background call
2108     */
2109    public List<Connection> getBgCallConnections() {
2110        Call bgCall = getFirstActiveBgCall();
2111        if ( bgCall != null) {
2112            return bgCall.getConnections();
2113        }
2114        return mEmptyConnections;
2115    }
2116
2117    /**
2118     * @return the connections of active background call
2119     * return empty list if there is no active background call
2120     */
2121    public List<Connection> getBgCallConnections(int subId) {
2122        Call bgCall = getFirstActiveBgCall(subId);
2123        if ( bgCall != null) {
2124            return bgCall.getConnections();
2125        }
2126        return mEmptyConnections;
2127    }
2128
2129    /**
2130     * @return the latest connection of active foreground call
2131     * return null if there is no active foreground call
2132     */
2133    public Connection getFgCallLatestConnection() {
2134        Call fgCall = getActiveFgCall();
2135        if ( fgCall != null) {
2136            return fgCall.getLatestConnection();
2137        }
2138        return null;
2139    }
2140
2141    /**
2142     * @return the latest connection of active foreground call
2143     * return null if there is no active foreground call
2144     */
2145    public Connection getFgCallLatestConnection(int subId) {
2146        Call fgCall = getActiveFgCall(subId);
2147        if ( fgCall != null) {
2148            return fgCall.getLatestConnection();
2149        }
2150        return null;
2151    }
2152
2153    /**
2154     * @return true if there is at least one Foreground call in disconnected state
2155     */
2156    public boolean hasDisconnectedFgCall() {
2157        return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null);
2158    }
2159
2160    /**
2161     * @return true if there is at least one Foreground call in disconnected state
2162     */
2163    public boolean hasDisconnectedFgCall(int subId) {
2164        return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED,
2165                subId) != null);
2166    }
2167
2168    /**
2169     * @return true if there is at least one background call in disconnected state
2170     */
2171    public boolean hasDisconnectedBgCall() {
2172        return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null);
2173    }
2174
2175    /**
2176     * @return true if there is at least one background call in disconnected state
2177     */
2178    public boolean hasDisconnectedBgCall(int subId) {
2179        return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED,
2180                subId) != null);
2181    }
2182
2183
2184    /**
2185     * @return the first active call from a call list
2186     */
2187    private  Call getFirstActiveCall(ArrayList<Call> calls) {
2188        for (Call call : calls) {
2189            if (!call.isIdle()) {
2190                return call;
2191            }
2192        }
2193        return null;
2194    }
2195
2196    /**
2197     * @return the first active call from a call list
2198     */
2199    private  Call getFirstActiveCall(ArrayList<Call> calls, int subId) {
2200        for (Call call : calls) {
2201            if ((!call.isIdle()) && ((call.getPhone().getSubId() == subId) ||
2202                    (call.getPhone() instanceof SipPhone))) {
2203                return call;
2204            }
2205        }
2206        return null;
2207    }
2208
2209    /**
2210     * @return the first call in a the Call.state from a call list
2211     */
2212    private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) {
2213        for (Call call : calls) {
2214            if (call.getState() == state) {
2215                return call;
2216            }
2217        }
2218        return null;
2219    }
2220
2221    /**
2222     * @return the first call in a the Call.state from a call list
2223     */
2224    private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state,
2225            int subId) {
2226        for (Call call : calls) {
2227            if ((call.getState() == state) ||
2228                ((call.getPhone().getSubId() == subId) ||
2229                (call.getPhone() instanceof SipPhone))) {
2230                return call;
2231            }
2232        }
2233        return null;
2234    }
2235
2236    private boolean hasMoreThanOneRingingCall() {
2237        int count = 0;
2238        for (Call call : mRingingCalls) {
2239            if (call.getState().isRinging()) {
2240                if (++count > 1) return true;
2241            }
2242        }
2243        return false;
2244    }
2245
2246    /**
2247     * @return true if more than one active ringing call exists on
2248     * the active subId.
2249     * This checks for the active calls on provided
2250     * subId and also active calls on SIP Phone.
2251     *
2252     */
2253    private boolean hasMoreThanOneRingingCall(int subId) {
2254        int count = 0;
2255        for (Call call : mRingingCalls) {
2256            if ((call.getState().isRinging()) &&
2257                ((call.getPhone().getSubId() == subId) ||
2258                (call.getPhone() instanceof SipPhone))) {
2259                if (++count > 1) return true;
2260            }
2261        }
2262        return false;
2263    }
2264
2265    /**
2266     * @return true if more than one active background call exists on
2267     * the provided subId.
2268     * This checks for the background calls on provided
2269     * subId and also background calls on SIP Phone.
2270     *
2271     */
2272    private boolean hasMoreThanOneHoldingCall(int subId) {
2273        int count = 0;
2274        for (Call call : mBackgroundCalls) {
2275            if ((call.getState() == Call.State.HOLDING) &&
2276                ((call.getPhone().getSubId() == subId) ||
2277                (call.getPhone() instanceof SipPhone))) {
2278                if (++count > 1) return true;
2279            }
2280        }
2281        return false;
2282    }
2283
2284    /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2285    private boolean isServiceStateInService() {
2286        boolean bInService = false;
2287
2288        for (Phone phone : mPhones) {
2289            bInService = (phone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
2290            if (bInService) {
2291                break;
2292            }
2293        }
2294
2295        if (VDBG) Rlog.d(LOG_TAG, "[isServiceStateInService] bInService = " + bInService);
2296        return bInService;
2297    }
2298    */
2299
2300    private class CallManagerHandler extends Handler {
2301        @Override
2302        public void handleMessage(Message msg) {
2303
2304            switch (msg.what) {
2305                case EVENT_DISCONNECT:
2306                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");
2307                    mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2308                    // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2309                    //mIsEccDialing = false;
2310                    break;
2311                case EVENT_PRECISE_CALL_STATE_CHANGED:
2312                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");
2313                    mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2314                    break;
2315                case EVENT_NEW_RINGING_CONNECTION:
2316                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
2317                    Connection c = (Connection) ((AsyncResult) msg.obj).result;
2318                    int subId = c.getCall().getPhone().getSubId();
2319                    if (getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall()) {
2320                        try {
2321                            Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
2322                            c.getCall().hangup();
2323                        } catch (CallStateException e) {
2324                            Rlog.w(LOG_TAG, "new ringing connection", e);
2325                        }
2326                    } else {
2327                        mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2328                    }
2329                    break;
2330                case EVENT_UNKNOWN_CONNECTION:
2331                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
2332                    mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2333                    break;
2334                case EVENT_INCOMING_RING:
2335                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");
2336                    // The event may come from RIL who's not aware of an ongoing fg call
2337                    if (!hasActiveFgCall()) {
2338                        mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2339                    }
2340                    break;
2341                case EVENT_RINGBACK_TONE:
2342                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");
2343                    mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2344                    break;
2345                case EVENT_IN_CALL_VOICE_PRIVACY_ON:
2346                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");
2347                    mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2348                    break;
2349                case EVENT_IN_CALL_VOICE_PRIVACY_OFF:
2350                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");
2351                    mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2352                    break;
2353                case EVENT_CALL_WAITING:
2354                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");
2355                    mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2356                    break;
2357                case EVENT_DISPLAY_INFO:
2358                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");
2359                    mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2360                    break;
2361                case EVENT_SIGNAL_INFO:
2362                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");
2363                    mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2364                    break;
2365                case EVENT_CDMA_OTA_STATUS_CHANGE:
2366                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");
2367                    mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2368                    break;
2369                case EVENT_RESEND_INCALL_MUTE:
2370                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");
2371                    mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2372                    break;
2373                case EVENT_MMI_INITIATE:
2374                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");
2375                    mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2376                    break;
2377                case EVENT_MMI_COMPLETE:
2378                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)");
2379                    mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2380                    break;
2381                case EVENT_ECM_TIMER_RESET:
2382                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");
2383                    mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2384                    break;
2385                case EVENT_SUBSCRIPTION_INFO_READY:
2386                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
2387                    mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2388                    break;
2389                case EVENT_SUPP_SERVICE_FAILED:
2390                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
2391                    mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2392                    break;
2393                case EVENT_SERVICE_STATE_CHANGED:
2394                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");
2395                    mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2396                    // FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2397                    //setAudioMode();
2398                    break;
2399                case EVENT_POST_DIAL_CHARACTER:
2400                    // we need send the character that is being processed in msg.arg1
2401                    // so can't use notifyRegistrants()
2402                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");
2403                    for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {
2404                        Message notifyMsg;
2405                        notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();
2406                        notifyMsg.obj = msg.obj;
2407                        notifyMsg.arg1 = msg.arg1;
2408                        notifyMsg.sendToTarget();
2409                    }
2410                    break;
2411                case EVENT_ONHOLD_TONE:
2412                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_ONHOLD_TONE)");
2413                    mOnHoldToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2414                    break;
2415                case EVENT_TTY_MODE_RECEIVED:
2416                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_TTY_MODE_RECEIVED)");
2417                    mTtyModeReceivedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
2418                    break;
2419                /* FIXME Taken from klp-sprout-dev but setAudioMode was removed in L.
2420                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
2421                    if (VDBG) Rlog.d(LOG_TAG, " handleMessage (EVENT_RADIO_OFF_OR_NOT_AVAILABLE)");
2422                    setAudioMode();
2423                    break;
2424                */
2425            }
2426        }
2427    };
2428
2429    @Override
2430    public String toString() {
2431        Call call;
2432        StringBuilder b = new StringBuilder();
2433        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2434            b.append("CallManager {");
2435            b.append("\nstate = " + getState(i));
2436            call = getActiveFgCall(i);
2437            if (call != null) {
2438                b.append("\n- Foreground: " + getActiveFgCallState(i));
2439                b.append(" from " + call.getPhone());
2440                b.append("\n  Conn: ").append(getFgCallConnections(i));
2441            }
2442            call = getFirstActiveBgCall(i);
2443            if (call != null) {
2444                b.append("\n- Background: " + call.getState());
2445                b.append(" from " + call.getPhone());
2446                b.append("\n  Conn: ").append(getBgCallConnections(i));
2447            }
2448            call = getFirstActiveRingingCall(i);
2449            if (call != null) {
2450                b.append("\n- Ringing: " +call.getState());
2451                b.append(" from " + call.getPhone());
2452            }
2453        }
2454
2455        for (Phone phone : getAllPhones()) {
2456            if (phone != null) {
2457                b.append("\nPhone: " + phone + ", name = " + phone.getPhoneName()
2458                        + ", state = " + phone.getState());
2459                call = phone.getForegroundCall();
2460                if (call != null) {
2461                    b.append("\n- Foreground: ").append(call);
2462                }
2463                call = phone.getBackgroundCall();
2464                if (call != null) {
2465                    b.append(" Background: ").append(call);
2466                }
2467                call = phone.getRingingCall();
2468                if (call != null) {
2469                    b.append(" Ringing: ").append(call);
2470                }
2471            }
2472        }
2473        b.append("\n}");
2474        return b.toString();
2475    }
2476}
2477