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