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