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