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