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