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