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