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