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