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 fgPhone = getFgPhone();
    383                 // Enable IN_CALL mode while foreground call is in DIALING,
    384                 // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone
    385                 if (getActiveFgCallState() != Call.State.IDLE
    386                         && getActiveFgCallState() != Call.State.DISCONNECTED
    387                         && !(fgPhone instanceof SipPhone)) {
    388                     mode = AudioManager.MODE_IN_CALL;
    389                 }
    390                 break;
    391         }
    392         // calling audioManager.setMode() multiple times in a short period of
    393         // time seems to break the audio recorder in in-call mode
    394         if (audioManager.getMode() != mode) audioManager.setMode(mode);
    395     }
    396 
    397     private Context getContext() {
    398         Phone defaultPhone = getDefaultPhone();
    399         return ((defaultPhone == null) ? null : defaultPhone.getContext());
    400     }
    401 
    402     private void registerForPhoneStates(Phone phone) {
    403         // for common events supported by all phones
    404         phone.registerForPreciseCallStateChanged(mHandler, EVENT_PRECISE_CALL_STATE_CHANGED, null);
    405         phone.registerForDisconnect(mHandler, EVENT_DISCONNECT, null);
    406         phone.registerForNewRingingConnection(mHandler, EVENT_NEW_RINGING_CONNECTION, null);
    407         phone.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null);
    408         phone.registerForIncomingRing(mHandler, EVENT_INCOMING_RING, null);
    409         phone.registerForRingbackTone(mHandler, EVENT_RINGBACK_TONE, null);
    410         phone.registerForInCallVoicePrivacyOn(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_ON, null);
    411         phone.registerForInCallVoicePrivacyOff(mHandler, EVENT_IN_CALL_VOICE_PRIVACY_OFF, null);
    412         phone.registerForDisplayInfo(mHandler, EVENT_DISPLAY_INFO, null);
    413         phone.registerForSignalInfo(mHandler, EVENT_SIGNAL_INFO, null);
    414         phone.registerForResendIncallMute(mHandler, EVENT_RESEND_INCALL_MUTE, null);
    415         phone.registerForMmiInitiate(mHandler, EVENT_MMI_INITIATE, null);
    416         phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
    417         phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null);
    418         phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null);
    419 
    420         // for events supported only by GSM and CDMA phone
    421         if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM ||
    422                 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
    423             phone.setOnPostDialCharacter(mHandler, EVENT_POST_DIAL_CHARACTER, null);
    424         }
    425 
    426         // for events supported only by CDMA phone
    427         if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){
    428             phone.registerForCdmaOtaStatusChange(mHandler, EVENT_CDMA_OTA_STATUS_CHANGE, null);
    429             phone.registerForSubscriptionInfoReady(mHandler, EVENT_SUBSCRIPTION_INFO_READY, null);
    430             phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null);
    431             phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null);
    432         }
    433     }
    434 
    435     private void unregisterForPhoneStates(Phone phone) {
    436         //  for common events supported by all phones
    437         phone.unregisterForPreciseCallStateChanged(mHandler);
    438         phone.unregisterForDisconnect(mHandler);
    439         phone.unregisterForNewRingingConnection(mHandler);
    440         phone.unregisterForUnknownConnection(mHandler);
    441         phone.unregisterForIncomingRing(mHandler);
    442         phone.unregisterForRingbackTone(mHandler);
    443         phone.unregisterForInCallVoicePrivacyOn(mHandler);
    444         phone.unregisterForInCallVoicePrivacyOff(mHandler);
    445         phone.unregisterForDisplayInfo(mHandler);
    446         phone.unregisterForSignalInfo(mHandler);
    447         phone.unregisterForResendIncallMute(mHandler);
    448         phone.unregisterForMmiInitiate(mHandler);
    449         phone.unregisterForMmiComplete(mHandler);
    450         phone.unregisterForSuppServiceFailed(mHandler);
    451         phone.unregisterForServiceStateChanged(mHandler);
    452 
    453         // for events supported only by GSM and CDMA phone
    454         if (phone.getPhoneType() == Phone.PHONE_TYPE_GSM ||
    455                 phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
    456             phone.setOnPostDialCharacter(null, EVENT_POST_DIAL_CHARACTER, null);
    457         }
    458 
    459         // for events supported only by CDMA phone
    460         if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA ){
    461             phone.unregisterForCdmaOtaStatusChange(mHandler);
    462             phone.unregisterForSubscriptionInfoReady(mHandler);
    463             phone.unregisterForCallWaiting(mHandler);
    464             phone.unregisterForEcmTimerReset(mHandler);
    465         }
    466     }
    467 
    468     /**
    469      * Answers a ringing or waiting call.
    470      *
    471      * Active call, if any, go on hold.
    472      * If active call can't be held, i.e., a background call of the same channel exists,
    473      * the active call will be hang up.
    474      *
    475      * Answering occurs asynchronously, and final notification occurs via
    476      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    477      * java.lang.Object) registerForPreciseCallStateChanged()}.
    478      *
    479      * @exception CallStateException when call is not ringing or waiting
    480      */
    481     public void acceptCall(Call ringingCall) throws CallStateException {
    482         Phone ringingPhone = ringingCall.getPhone();
    483 
    484         if (VDBG) {
    485             Log.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")");
    486             Log.d(LOG_TAG, this.toString());
    487         }
    488 
    489         if ( hasActiveFgCall() ) {
    490             Phone activePhone = getActiveFgCall().getPhone();
    491             boolean hasBgCall = ! (activePhone.getBackgroundCall().isIdle());
    492             boolean sameChannel = (activePhone == ringingPhone);
    493 
    494             if (VDBG) {
    495                 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + "sameChannel:" + sameChannel);
    496             }
    497 
    498             if (sameChannel && hasBgCall) {
    499                 getActiveFgCall().hangup();
    500             } else if (!sameChannel && !hasBgCall) {
    501                 activePhone.switchHoldingAndActive();
    502             } else if (!sameChannel && hasBgCall) {
    503                 getActiveFgCall().hangup();
    504             }
    505         }
    506 
    507         ringingPhone.acceptCall();
    508 
    509         if (VDBG) {
    510             Log.d(LOG_TAG, "End acceptCall(" +ringingCall + ")");
    511             Log.d(LOG_TAG, this.toString());
    512         }
    513     }
    514 
    515     /**
    516      * Reject (ignore) a ringing call. In GSM, this means UDUB
    517      * (User Determined User Busy). Reject occurs asynchronously,
    518      * and final notification occurs via
    519      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    520      * java.lang.Object) registerForPreciseCallStateChanged()}.
    521      *
    522      * @exception CallStateException when no call is ringing or waiting
    523      */
    524     public void rejectCall(Call ringingCall) throws CallStateException {
    525         if (VDBG) {
    526             Log.d(LOG_TAG, "rejectCall(" +ringingCall + ")");
    527             Log.d(LOG_TAG, this.toString());
    528         }
    529 
    530         Phone ringingPhone = ringingCall.getPhone();
    531 
    532         ringingPhone.rejectCall();
    533 
    534         if (VDBG) {
    535             Log.d(LOG_TAG, "End rejectCall(" +ringingCall + ")");
    536             Log.d(LOG_TAG, this.toString());
    537         }
    538     }
    539 
    540     /**
    541      * Places active call on hold, and makes held call active.
    542      * Switch occurs asynchronously and may fail.
    543      *
    544      * There are 4 scenarios
    545      * 1. only active call but no held call, aka, hold
    546      * 2. no active call but only held call, aka, unhold
    547      * 3. both active and held calls from same phone, aka, swap
    548      * 4. active and held calls from different phones, aka, phone swap
    549      *
    550      * Final notification occurs via
    551      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    552      * java.lang.Object) registerForPreciseCallStateChanged()}.
    553      *
    554      * @exception CallStateException if active call is ringing, waiting, or
    555      * dialing/alerting, or heldCall can't be active.
    556      * In these cases, this operation may not be performed.
    557      */
    558     public void switchHoldingAndActive(Call heldCall) throws CallStateException {
    559         Phone activePhone = null;
    560         Phone heldPhone = null;
    561 
    562         if (VDBG) {
    563             Log.d(LOG_TAG, "switchHoldingAndActive(" +heldCall + ")");
    564             Log.d(LOG_TAG, this.toString());
    565         }
    566 
    567         if (hasActiveFgCall()) {
    568             activePhone = getActiveFgCall().getPhone();
    569         }
    570 
    571         if (heldCall != null) {
    572             heldPhone = heldCall.getPhone();
    573         }
    574 
    575         if (activePhone != null) {
    576             activePhone.switchHoldingAndActive();
    577         }
    578 
    579         if (heldPhone != null && heldPhone != activePhone) {
    580             heldPhone.switchHoldingAndActive();
    581         }
    582 
    583         if (VDBG) {
    584             Log.d(LOG_TAG, "End switchHoldingAndActive(" +heldCall + ")");
    585             Log.d(LOG_TAG, this.toString());
    586         }
    587     }
    588 
    589     /**
    590      * Hangup foreground call and resume the specific background call
    591      *
    592      * Note: this is noop if there is no foreground call or the heldCall is null
    593      *
    594      * @param heldCall to become foreground
    595      * @throws CallStateException
    596      */
    597     public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
    598         Phone foregroundPhone = null;
    599         Phone backgroundPhone = null;
    600 
    601         if (VDBG) {
    602             Log.d(LOG_TAG, "hangupForegroundResumeBackground(" +heldCall + ")");
    603             Log.d(LOG_TAG, this.toString());
    604         }
    605 
    606         if (hasActiveFgCall()) {
    607             foregroundPhone = getFgPhone();
    608             if (heldCall != null) {
    609                 backgroundPhone = heldCall.getPhone();
    610                 if (foregroundPhone == backgroundPhone) {
    611                     getActiveFgCall().hangup();
    612                 } else {
    613                 // the call to be hangup and resumed belongs to different phones
    614                     getActiveFgCall().hangup();
    615                     switchHoldingAndActive(heldCall);
    616                 }
    617             }
    618         }
    619 
    620         if (VDBG) {
    621             Log.d(LOG_TAG, "End hangupForegroundResumeBackground(" +heldCall + ")");
    622             Log.d(LOG_TAG, this.toString());
    623         }
    624     }
    625 
    626     /**
    627      * Whether or not the phone can conference in the current phone
    628      * state--that is, one call holding and one call active.
    629      * @return true if the phone can conference; false otherwise.
    630      */
    631     public boolean canConference(Call heldCall) {
    632         Phone activePhone = null;
    633         Phone heldPhone = null;
    634 
    635         if (hasActiveFgCall()) {
    636             activePhone = getActiveFgCall().getPhone();
    637         }
    638 
    639         if (heldCall != null) {
    640             heldPhone = heldCall.getPhone();
    641         }
    642 
    643         return heldPhone.getClass().equals(activePhone.getClass());
    644     }
    645 
    646     /**
    647      * Conferences holding and active. Conference occurs asynchronously
    648      * and may fail. Final notification occurs via
    649      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    650      * java.lang.Object) registerForPreciseCallStateChanged()}.
    651      *
    652      * @exception CallStateException if canConference() would return false.
    653      * In these cases, this operation may not be performed.
    654      */
    655     public void conference(Call heldCall) throws CallStateException {
    656 
    657         if (VDBG) {
    658             Log.d(LOG_TAG, "conference(" +heldCall + ")");
    659             Log.d(LOG_TAG, this.toString());
    660         }
    661 
    662 
    663         Phone fgPhone = getFgPhone();
    664         if (fgPhone instanceof SipPhone) {
    665             ((SipPhone) fgPhone).conference(heldCall);
    666         } else if (canConference(heldCall)) {
    667             fgPhone.conference();
    668         } else {
    669             throw(new CallStateException("Can't conference foreground and selected background call"));
    670         }
    671 
    672         if (VDBG) {
    673             Log.d(LOG_TAG, "End conference(" +heldCall + ")");
    674             Log.d(LOG_TAG, this.toString());
    675         }
    676 
    677     }
    678 
    679     /**
    680      * Initiate a new voice connection. This happens asynchronously, so you
    681      * cannot assume the audio path is connected (or a call index has been
    682      * assigned) until PhoneStateChanged notification has occurred.
    683      *
    684      * @exception CallStateException if a new outgoing call is not currently
    685      * possible because no more call slots exist or a call exists that is
    686      * dialing, alerting, ringing, or waiting.  Other errors are
    687      * handled asynchronously.
    688      */
    689     public Connection dial(Phone phone, String dialString) throws CallStateException {
    690         Phone basePhone = getPhoneBase(phone);
    691         Connection result;
    692 
    693         if (VDBG) {
    694             Log.d(LOG_TAG, " dial(" + basePhone + ", "+ dialString + ")");
    695             Log.d(LOG_TAG, this.toString());
    696         }
    697 
    698         if ( hasActiveFgCall() ) {
    699             Phone activePhone = getActiveFgCall().getPhone();
    700             boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
    701 
    702             if (DBG) {
    703                 Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone));
    704             }
    705 
    706             if (activePhone != basePhone) {
    707                 if (hasBgCall) {
    708                     Log.d(LOG_TAG, "Hangup");
    709                     getActiveFgCall().hangup();
    710                 } else {
    711                     Log.d(LOG_TAG, "Switch");
    712                     activePhone.switchHoldingAndActive();
    713                 }
    714             }
    715         }
    716 
    717         result = basePhone.dial(dialString);
    718 
    719         if (VDBG) {
    720             Log.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")");
    721             Log.d(LOG_TAG, this.toString());
    722         }
    723 
    724         return result;
    725     }
    726 
    727     /**
    728      * Initiate a new voice connection. This happens asynchronously, so you
    729      * cannot assume the audio path is connected (or a call index has been
    730      * assigned) until PhoneStateChanged notification has occurred.
    731      *
    732      * @exception CallStateException if a new outgoing call is not currently
    733      * possible because no more call slots exist or a call exists that is
    734      * dialing, alerting, ringing, or waiting.  Other errors are
    735      * handled asynchronously.
    736      */
    737     public Connection dial(Phone phone, String dialString, UUSInfo uusInfo) throws CallStateException {
    738         return phone.dial(dialString, uusInfo);
    739     }
    740 
    741     /**
    742      * clear disconnect connection for each phone
    743      */
    744     public void clearDisconnected() {
    745         for(Phone phone : mPhones) {
    746             phone.clearDisconnected();
    747         }
    748     }
    749 
    750     /**
    751      * Whether or not the phone can do explicit call transfer in the current
    752      * phone state--that is, one call holding and one call active.
    753      * @return true if the phone can do explicit call transfer; false otherwise.
    754      */
    755     public boolean canTransfer(Call heldCall) {
    756         Phone activePhone = null;
    757         Phone heldPhone = null;
    758 
    759         if (hasActiveFgCall()) {
    760             activePhone = getActiveFgCall().getPhone();
    761         }
    762 
    763         if (heldCall != null) {
    764             heldPhone = heldCall.getPhone();
    765         }
    766 
    767         return (heldPhone == activePhone && activePhone.canTransfer());
    768     }
    769 
    770     /**
    771      * Connects the held call and active call
    772      * Disconnects the subscriber from both calls
    773      *
    774      * Explicit Call Transfer occurs asynchronously
    775      * and may fail. Final notification occurs via
    776      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    777      * java.lang.Object) registerForPreciseCallStateChanged()}.
    778      *
    779      * @exception CallStateException if canTransfer() would return false.
    780      * In these cases, this operation may not be performed.
    781      */
    782     public void explicitCallTransfer(Call heldCall) throws CallStateException {
    783         if (VDBG) {
    784             Log.d(LOG_TAG, " explicitCallTransfer(" + heldCall + ")");
    785             Log.d(LOG_TAG, this.toString());
    786         }
    787 
    788         if (canTransfer(heldCall)) {
    789             heldCall.getPhone().explicitCallTransfer();
    790         }
    791 
    792         if (VDBG) {
    793             Log.d(LOG_TAG, "End explicitCallTransfer(" + heldCall + ")");
    794             Log.d(LOG_TAG, this.toString());
    795         }
    796 
    797     }
    798 
    799     /**
    800      * Returns a list of MMI codes that are pending for a phone. (They have initiated
    801      * but have not yet completed).
    802      * Presently there is only ever one.
    803      *
    804      * Use <code>registerForMmiInitiate</code>
    805      * and <code>registerForMmiComplete</code> for change notification.
    806      * @return null if phone doesn't have or support mmi code
    807      */
    808     public List<? extends MmiCode> getPendingMmiCodes(Phone phone) {
    809         Log.e(LOG_TAG, "getPendingMmiCodes not implemented");
    810         return null;
    811     }
    812 
    813     /**
    814      * Sends user response to a USSD REQUEST message.  An MmiCode instance
    815      * representing this response is sent to handlers registered with
    816      * registerForMmiInitiate.
    817      *
    818      * @param ussdMessge    Message to send in the response.
    819      * @return false if phone doesn't support ussd service
    820      */
    821     public boolean sendUssdResponse(Phone phone, String ussdMessge) {
    822         Log.e(LOG_TAG, "sendUssdResponse not implemented");
    823         return false;
    824     }
    825 
    826     /**
    827      * Mutes or unmutes the microphone for the active call. The microphone
    828      * is automatically unmuted if a call is answered, dialed, or resumed
    829      * from a holding state.
    830      *
    831      * @param muted true to mute the microphone,
    832      * false to activate the microphone.
    833      */
    834 
    835     public void setMute(boolean muted) {
    836         if (VDBG) {
    837             Log.d(LOG_TAG, " setMute(" + muted + ")");
    838             Log.d(LOG_TAG, this.toString());
    839         }
    840 
    841         if (hasActiveFgCall()) {
    842             getActiveFgCall().getPhone().setMute(muted);
    843         }
    844 
    845         if (VDBG) {
    846             Log.d(LOG_TAG, "End setMute(" + muted + ")");
    847             Log.d(LOG_TAG, this.toString());
    848         }
    849     }
    850 
    851     /**
    852      * Gets current mute status. Use
    853      * {@link #registerForPreciseCallStateChanged(android.os.Handler, int,
    854      * java.lang.Object) registerForPreciseCallStateChanged()}
    855      * as a change notifcation, although presently phone state changed is not
    856      * fired when setMute() is called.
    857      *
    858      * @return true is muting, false is unmuting
    859      */
    860     public boolean getMute() {
    861         if (hasActiveFgCall()) {
    862             return getActiveFgCall().getPhone().getMute();
    863         }
    864         return false;
    865     }
    866 
    867     /**
    868      * Enables or disables echo suppression.
    869      */
    870     public void setEchoSuppressionEnabled(boolean enabled) {
    871         if (VDBG) {
    872             Log.d(LOG_TAG, " setEchoSuppression(" + enabled + ")");
    873             Log.d(LOG_TAG, this.toString());
    874         }
    875 
    876         if (hasActiveFgCall()) {
    877             getActiveFgCall().getPhone().setEchoSuppressionEnabled(enabled);
    878         }
    879 
    880         if (VDBG) {
    881             Log.d(LOG_TAG, "End setEchoSuppression(" + enabled + ")");
    882             Log.d(LOG_TAG, this.toString());
    883         }
    884     }
    885 
    886     /**
    887      * Play a DTMF tone on the active call.
    888      *
    889      * @param c should be one of 0-9, '*' or '#'. Other values will be
    890      * silently ignored.
    891      * @return false if no active call or the active call doesn't support
    892      *         dtmf tone
    893      */
    894     public boolean sendDtmf(char c) {
    895         boolean result = false;
    896 
    897         if (VDBG) {
    898             Log.d(LOG_TAG, " sendDtmf(" + c + ")");
    899             Log.d(LOG_TAG, this.toString());
    900         }
    901 
    902         if (hasActiveFgCall()) {
    903             getActiveFgCall().getPhone().sendDtmf(c);
    904             result = true;
    905         }
    906 
    907         if (VDBG) {
    908             Log.d(LOG_TAG, "End sendDtmf(" + c + ")");
    909             Log.d(LOG_TAG, this.toString());
    910         }
    911         return result;
    912     }
    913 
    914     /**
    915      * Start to paly a DTMF tone on the active call.
    916      * or there is a playing DTMF tone.
    917      * @param c should be one of 0-9, '*' or '#'. Other values will be
    918      * silently ignored.
    919      *
    920      * @return false if no active call or the active call doesn't support
    921      *         dtmf tone
    922      */
    923     public boolean startDtmf(char c) {
    924         boolean result = false;
    925 
    926         if (VDBG) {
    927             Log.d(LOG_TAG, " startDtmf(" + c + ")");
    928             Log.d(LOG_TAG, this.toString());
    929         }
    930 
    931         if (hasActiveFgCall()) {
    932             getActiveFgCall().getPhone().startDtmf(c);
    933             result = true;
    934         }
    935 
    936         if (VDBG) {
    937             Log.d(LOG_TAG, "End startDtmf(" + c + ")");
    938             Log.d(LOG_TAG, this.toString());
    939         }
    940 
    941         return result;
    942     }
    943 
    944     /**
    945      * Stop the playing DTMF tone. Ignored if there is no playing DTMF
    946      * tone or no active call.
    947      */
    948     public void stopDtmf() {
    949         if (VDBG) {
    950             Log.d(LOG_TAG, " stopDtmf()" );
    951             Log.d(LOG_TAG, this.toString());
    952         }
    953 
    954         if (hasActiveFgCall()) getFgPhone().stopDtmf();
    955 
    956         if (VDBG) {
    957             Log.d(LOG_TAG, "End stopDtmf()");
    958             Log.d(LOG_TAG, this.toString());
    959         }
    960     }
    961 
    962     /**
    963      * send burst DTMF tone, it can send the string as single character or multiple character
    964      * ignore if there is no active call or not valid digits string.
    965      * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
    966      * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
    967      * this api can send single character and multiple character, also, this api has response
    968      * back to caller.
    969      *
    970      * @param dtmfString is string representing the dialing digit(s) in the active call
    971      * @param on the DTMF ON length in milliseconds, or 0 for default
    972      * @param off the DTMF OFF length in milliseconds, or 0 for default
    973      * @param onComplete is the callback message when the action is processed by BP
    974      *
    975      */
    976     public boolean sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
    977         if (hasActiveFgCall()) {
    978             getActiveFgCall().getPhone().sendBurstDtmf(dtmfString, on, off, onComplete);
    979             return true;
    980         }
    981         return false;
    982     }
    983 
    984     /**
    985      * Notifies when a voice connection has disconnected, either due to local
    986      * or remote hangup or error.
    987      *
    988      *  Messages received from this will have the following members:<p>
    989      *  <ul><li>Message.obj will be an AsyncResult</li>
    990      *  <li>AsyncResult.userObj = obj</li>
    991      *  <li>AsyncResult.result = a Connection object that is
    992      *  no longer connected.</li></ul>
    993      */
    994     public void registerForDisconnect(Handler h, int what, Object obj) {
    995         mDisconnectRegistrants.addUnique(h, what, obj);
    996     }
    997 
    998     /**
    999      * Unregisters for voice disconnection notification.
   1000      * Extraneous calls are tolerated silently
   1001      */
   1002     public void unregisterForDisconnect(Handler h){
   1003         mDisconnectRegistrants.remove(h);
   1004     }
   1005 
   1006     /**
   1007      * Register for getting notifications for change in the Call State {@link Call.State}
   1008      * This is called PreciseCallState because the call state is more precise than the
   1009      * {@link Phone.State} which can be obtained using the {@link PhoneStateListener}
   1010      *
   1011      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
   1012      * AsyncResult.userData will be set to the obj argument here.
   1013      * The <em>h</em> parameter is held only by a weak reference.
   1014      */
   1015     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
   1016         mPreciseCallStateRegistrants.addUnique(h, what, obj);
   1017     }
   1018 
   1019     /**
   1020      * Unregisters for voice call state change notifications.
   1021      * Extraneous calls are tolerated silently.
   1022      */
   1023     public void unregisterForPreciseCallStateChanged(Handler h){
   1024         mPreciseCallStateRegistrants.remove(h);
   1025     }
   1026 
   1027     /**
   1028      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
   1029      * This is likely due to some other entity (eg, SIM card application) initiating a call.
   1030      */
   1031     public void registerForUnknownConnection(Handler h, int what, Object obj){
   1032         mUnknownConnectionRegistrants.addUnique(h, what, obj);
   1033     }
   1034 
   1035     /**
   1036      * Unregisters for unknown connection notifications.
   1037      */
   1038     public void unregisterForUnknownConnection(Handler h){
   1039         mUnknownConnectionRegistrants.remove(h);
   1040     }
   1041 
   1042 
   1043     /**
   1044      * Notifies when a new ringing or waiting connection has appeared.<p>
   1045      *
   1046      *  Messages received from this:
   1047      *  Message.obj will be an AsyncResult
   1048      *  AsyncResult.userObj = obj
   1049      *  AsyncResult.result = a Connection. <p>
   1050      *  Please check Connection.isRinging() to make sure the Connection
   1051      *  has not dropped since this message was posted.
   1052      *  If Connection.isRinging() is true, then
   1053      *   Connection.getCall() == Phone.getRingingCall()
   1054      */
   1055     public void registerForNewRingingConnection(Handler h, int what, Object obj){
   1056         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
   1057     }
   1058 
   1059     /**
   1060      * Unregisters for new ringing connection notification.
   1061      * Extraneous calls are tolerated silently
   1062      */
   1063 
   1064     public void unregisterForNewRingingConnection(Handler h){
   1065         mNewRingingConnectionRegistrants.remove(h);
   1066     }
   1067 
   1068     /**
   1069      * Notifies when an incoming call rings.<p>
   1070      *
   1071      *  Messages received from this:
   1072      *  Message.obj will be an AsyncResult
   1073      *  AsyncResult.userObj = obj
   1074      *  AsyncResult.result = a Connection. <p>
   1075      */
   1076     public void registerForIncomingRing(Handler h, int what, Object obj){
   1077         mIncomingRingRegistrants.addUnique(h, what, obj);
   1078     }
   1079 
   1080     /**
   1081      * Unregisters for ring notification.
   1082      * Extraneous calls are tolerated silently
   1083      */
   1084 
   1085     public void unregisterForIncomingRing(Handler h){
   1086         mIncomingRingRegistrants.remove(h);
   1087     }
   1088 
   1089     /**
   1090      * Notifies when out-band ringback tone is needed.<p>
   1091      *
   1092      *  Messages received from this:
   1093      *  Message.obj will be an AsyncResult
   1094      *  AsyncResult.userObj = obj
   1095      *  AsyncResult.result = boolean, true to start play ringback tone
   1096      *                       and false to stop. <p>
   1097      */
   1098     public void registerForRingbackTone(Handler h, int what, Object obj){
   1099         mRingbackToneRegistrants.addUnique(h, what, obj);
   1100     }
   1101 
   1102     /**
   1103      * Unregisters for ringback tone notification.
   1104      */
   1105 
   1106     public void unregisterForRingbackTone(Handler h){
   1107         mRingbackToneRegistrants.remove(h);
   1108     }
   1109 
   1110     /**
   1111      * Registers the handler to reset the uplink mute state to get
   1112      * uplink audio.
   1113      */
   1114     public void registerForResendIncallMute(Handler h, int what, Object obj){
   1115         mResendIncallMuteRegistrants.addUnique(h, what, obj);
   1116     }
   1117 
   1118     /**
   1119      * Unregisters for resend incall mute notifications.
   1120      */
   1121     public void unregisterForResendIncallMute(Handler h){
   1122         mResendIncallMuteRegistrants.remove(h);
   1123     }
   1124 
   1125     /**
   1126      * Register for notifications of initiation of a new MMI code request.
   1127      * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
   1128      *
   1129      * Example: If Phone.dial is called with "*#31#", then the app will
   1130      * be notified here.<p>
   1131      *
   1132      * The returned <code>Message.obj</code> will contain an AsyncResult.
   1133      *
   1134      * <code>obj.result</code> will be an "MmiCode" object.
   1135      */
   1136     public void registerForMmiInitiate(Handler h, int what, Object obj){
   1137         mMmiInitiateRegistrants.addUnique(h, what, obj);
   1138     }
   1139 
   1140     /**
   1141      * Unregisters for new MMI initiate notification.
   1142      * Extraneous calls are tolerated silently
   1143      */
   1144     public void unregisterForMmiInitiate(Handler h){
   1145         mMmiInitiateRegistrants.remove(h);
   1146     }
   1147 
   1148     /**
   1149      * Register for notifications that an MMI request has completed
   1150      * its network activity and is in its final state. This may mean a state
   1151      * of COMPLETE, FAILED, or CANCELLED.
   1152      *
   1153      * <code>Message.obj</code> will contain an AsyncResult.
   1154      * <code>obj.result</code> will be an "MmiCode" object
   1155      */
   1156     public void registerForMmiComplete(Handler h, int what, Object obj){
   1157         mMmiCompleteRegistrants.addUnique(h, what, obj);
   1158     }
   1159 
   1160     /**
   1161      * Unregisters for MMI complete notification.
   1162      * Extraneous calls are tolerated silently
   1163      */
   1164     public void unregisterForMmiComplete(Handler h){
   1165         mMmiCompleteRegistrants.remove(h);
   1166     }
   1167 
   1168     /**
   1169      * Registration point for Ecm timer reset
   1170      * @param h handler to notify
   1171      * @param what user-defined message code
   1172      * @param obj placed in Message.obj
   1173      */
   1174     public void registerForEcmTimerReset(Handler h, int what, Object obj){
   1175         mEcmTimerResetRegistrants.addUnique(h, what, obj);
   1176     }
   1177 
   1178     /**
   1179      * Unregister for notification for Ecm timer reset
   1180      * @param h Handler to be removed from the registrant list.
   1181      */
   1182     public void unregisterForEcmTimerReset(Handler h){
   1183         mEcmTimerResetRegistrants.remove(h);
   1184     }
   1185 
   1186     /**
   1187      * Register for ServiceState changed.
   1188      * Message.obj will contain an AsyncResult.
   1189      * AsyncResult.result will be a ServiceState instance
   1190      */
   1191     public void registerForServiceStateChanged(Handler h, int what, Object obj){
   1192         mServiceStateChangedRegistrants.addUnique(h, what, obj);
   1193     }
   1194 
   1195     /**
   1196      * Unregisters for ServiceStateChange notification.
   1197      * Extraneous calls are tolerated silently
   1198      */
   1199     public void unregisterForServiceStateChanged(Handler h){
   1200         mServiceStateChangedRegistrants.remove(h);
   1201     }
   1202 
   1203     /**
   1204      * Register for notifications when a supplementary service attempt fails.
   1205      * Message.obj will contain an AsyncResult.
   1206      *
   1207      * @param h Handler that receives the notification message.
   1208      * @param what User-defined message code.
   1209      * @param obj User object.
   1210      */
   1211     public void registerForSuppServiceFailed(Handler h, int what, Object obj){
   1212         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
   1213     }
   1214 
   1215     /**
   1216      * Unregister for notifications when a supplementary service attempt fails.
   1217      * Extraneous calls are tolerated silently
   1218      *
   1219      * @param h Handler to be removed from the registrant list.
   1220      */
   1221     public void unregisterForSuppServiceFailed(Handler h){
   1222         mSuppServiceFailedRegistrants.remove(h);
   1223     }
   1224 
   1225     /**
   1226      * Register for notifications when a sInCall VoicePrivacy is enabled
   1227      *
   1228      * @param h Handler that receives the notification message.
   1229      * @param what User-defined message code.
   1230      * @param obj User object.
   1231      */
   1232     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
   1233         mInCallVoicePrivacyOnRegistrants.addUnique(h, what, obj);
   1234     }
   1235 
   1236     /**
   1237      * Unregister for notifications when a sInCall VoicePrivacy is enabled
   1238      *
   1239      * @param h Handler to be removed from the registrant list.
   1240      */
   1241     public void unregisterForInCallVoicePrivacyOn(Handler h){
   1242         mInCallVoicePrivacyOnRegistrants.remove(h);
   1243     }
   1244 
   1245     /**
   1246      * Register for notifications when a sInCall VoicePrivacy is disabled
   1247      *
   1248      * @param h Handler that receives the notification message.
   1249      * @param what User-defined message code.
   1250      * @param obj User object.
   1251      */
   1252     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
   1253         mInCallVoicePrivacyOffRegistrants.addUnique(h, what, obj);
   1254     }
   1255 
   1256     /**
   1257      * Unregister for notifications when a sInCall VoicePrivacy is disabled
   1258      *
   1259      * @param h Handler to be removed from the registrant list.
   1260      */
   1261     public void unregisterForInCallVoicePrivacyOff(Handler h){
   1262         mInCallVoicePrivacyOffRegistrants.remove(h);
   1263     }
   1264 
   1265     /**
   1266      * Register for notifications when CDMA call waiting comes
   1267      *
   1268      * @param h Handler that receives the notification message.
   1269      * @param what User-defined message code.
   1270      * @param obj User object.
   1271      */
   1272     public void registerForCallWaiting(Handler h, int what, Object obj){
   1273         mCallWaitingRegistrants.addUnique(h, what, obj);
   1274     }
   1275 
   1276     /**
   1277      * Unregister for notifications when CDMA Call waiting comes
   1278      * @param h Handler to be removed from the registrant list.
   1279      */
   1280     public void unregisterForCallWaiting(Handler h){
   1281         mCallWaitingRegistrants.remove(h);
   1282     }
   1283 
   1284 
   1285     /**
   1286      * Register for signal information notifications from the network.
   1287      * Message.obj will contain an AsyncResult.
   1288      * AsyncResult.result will be a SuppServiceNotification instance.
   1289      *
   1290      * @param h Handler that receives the notification message.
   1291      * @param what User-defined message code.
   1292      * @param obj User object.
   1293      */
   1294 
   1295     public void registerForSignalInfo(Handler h, int what, Object obj){
   1296         mSignalInfoRegistrants.addUnique(h, what, obj);
   1297     }
   1298 
   1299     /**
   1300      * Unregisters for signal information notifications.
   1301      * Extraneous calls are tolerated silently
   1302      *
   1303      * @param h Handler to be removed from the registrant list.
   1304      */
   1305     public void unregisterForSignalInfo(Handler h){
   1306         mSignalInfoRegistrants.remove(h);
   1307     }
   1308 
   1309     /**
   1310      * Register for display information notifications from the network.
   1311      * Message.obj will contain an AsyncResult.
   1312      * AsyncResult.result will be a SuppServiceNotification instance.
   1313      *
   1314      * @param h Handler that receives the notification message.
   1315      * @param what User-defined message code.
   1316      * @param obj User object.
   1317      */
   1318     public void registerForDisplayInfo(Handler h, int what, Object obj){
   1319         mDisplayInfoRegistrants.addUnique(h, what, obj);
   1320     }
   1321 
   1322     /**
   1323      * Unregisters for display information notifications.
   1324      * Extraneous calls are tolerated silently
   1325      *
   1326      * @param h Handler to be removed from the registrant list.
   1327      */
   1328     public void unregisterForDisplayInfo(Handler h) {
   1329         mDisplayInfoRegistrants.remove(h);
   1330     }
   1331 
   1332     /**
   1333      * Register for notifications when CDMA OTA Provision status change
   1334      *
   1335      * @param h Handler that receives the notification message.
   1336      * @param what User-defined message code.
   1337      * @param obj User object.
   1338      */
   1339     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj){
   1340         mCdmaOtaStatusChangeRegistrants.addUnique(h, what, obj);
   1341     }
   1342 
   1343     /**
   1344      * Unregister for notifications when CDMA OTA Provision status change
   1345      * @param h Handler to be removed from the registrant list.
   1346      */
   1347     public void unregisterForCdmaOtaStatusChange(Handler h){
   1348         mCdmaOtaStatusChangeRegistrants.remove(h);
   1349     }
   1350 
   1351     /**
   1352      * Registration point for subscription info ready
   1353      * @param h handler to notify
   1354      * @param what what code of message when delivered
   1355      * @param obj placed in Message.obj
   1356      */
   1357     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj){
   1358         mSubscriptionInfoReadyRegistrants.addUnique(h, what, obj);
   1359     }
   1360 
   1361     /**
   1362      * Unregister for notifications for subscription info
   1363      * @param h Handler to be removed from the registrant list.
   1364      */
   1365     public void unregisterForSubscriptionInfoReady(Handler h){
   1366         mSubscriptionInfoReadyRegistrants.remove(h);
   1367     }
   1368 
   1369     /**
   1370      * Sets an event to be fired when the telephony system processes
   1371      * a post-dial character on an outgoing call.<p>
   1372      *
   1373      * Messages of type <code>what</code> will be sent to <code>h</code>.
   1374      * The <code>obj</code> field of these Message's will be instances of
   1375      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
   1376      * a Connection object.<p>
   1377      *
   1378      * Message.arg1 will be the post dial character being processed,
   1379      * or 0 ('\0') if end of string.<p>
   1380      *
   1381      * If Connection.getPostDialState() == WAIT,
   1382      * the application must call
   1383      * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
   1384      * Connection.proceedAfterWaitChar()} or
   1385      * {@link com.android.internal.telephony.Connection#cancelPostDial()
   1386      * Connection.cancelPostDial()}
   1387      * for the telephony system to continue playing the post-dial
   1388      * DTMF sequence.<p>
   1389      *
   1390      * If Connection.getPostDialState() == WILD,
   1391      * the application must call
   1392      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
   1393      * Connection.proceedAfterWildChar()}
   1394      * or
   1395      * {@link com.android.internal.telephony.Connection#cancelPostDial()
   1396      * Connection.cancelPostDial()}
   1397      * for the telephony system to continue playing the
   1398      * post-dial DTMF sequence.<p>
   1399      *
   1400      */
   1401     public void registerForPostDialCharacter(Handler h, int what, Object obj){
   1402         mPostDialCharacterRegistrants.addUnique(h, what, obj);
   1403     }
   1404 
   1405     public void unregisterForPostDialCharacter(Handler h){
   1406         mPostDialCharacterRegistrants.remove(h);
   1407     }
   1408 
   1409     /* APIs to access foregroudCalls, backgroudCalls, and ringingCalls
   1410      * 1. APIs to access list of calls
   1411      * 2. APIs to check if any active call, which has connection other than
   1412      * disconnected ones, pleaser refer to Call.isIdle()
   1413      * 3. APIs to return first active call
   1414      * 4. APIs to return the connections of first active call
   1415      * 5. APIs to return other property of first active call
   1416      */
   1417 
   1418     /**
   1419      * @return list of all ringing calls
   1420      */
   1421     public List<Call> getRingingCalls() {
   1422         return Collections.unmodifiableList(mRingingCalls);
   1423     }
   1424 
   1425     /**
   1426      * @return list of all foreground calls
   1427      */
   1428     public List<Call> getForegroundCalls() {
   1429         return Collections.unmodifiableList(mForegroundCalls);
   1430     }
   1431 
   1432     /**
   1433      * @return list of all background calls
   1434      */
   1435     public List<Call> getBackgroundCalls() {
   1436         return Collections.unmodifiableList(mBackgroundCalls);
   1437     }
   1438 
   1439     /**
   1440      * Return true if there is at least one active foreground call
   1441      */
   1442     public boolean hasActiveFgCall() {
   1443         return (getFirstActiveCall(mForegroundCalls) != null);
   1444     }
   1445 
   1446     /**
   1447      * Return true if there is at least one active background call
   1448      */
   1449     public boolean hasActiveBgCall() {
   1450         // TODO since hasActiveBgCall may get called often
   1451         // better to cache it to improve performance
   1452         return (getFirstActiveCall(mBackgroundCalls) != null);
   1453     }
   1454 
   1455     /**
   1456      * Return true if there is at least one active ringing call
   1457      *
   1458      */
   1459     public boolean hasActiveRingingCall() {
   1460         return (getFirstActiveCall(mRingingCalls) != null);
   1461     }
   1462 
   1463     /**
   1464      * return the active foreground call from foreground calls
   1465      *
   1466      * Active call means the call is NOT in Call.State.IDLE
   1467      *
   1468      * 1. If there is active foreground call, return it
   1469      * 2. If there is no active foreground call, return the
   1470      *    foreground call associated with default phone, which state is IDLE.
   1471      * 3. If there is no phone registered at all, return null.
   1472      *
   1473      */
   1474     public Call getActiveFgCall() {
   1475         Call call = getFirstNonIdleCall(mForegroundCalls);
   1476         if (call == null) {
   1477             call = (mDefaultPhone == null)
   1478                     ? null
   1479                     : mDefaultPhone.getForegroundCall();
   1480         }
   1481         return call;
   1482     }
   1483 
   1484     // Returns the first call that is not in IDLE state. If both active calls
   1485     // and disconnecting/disconnected calls exist, return the first active call.
   1486     private Call getFirstNonIdleCall(List<Call> calls) {
   1487         Call result = null;
   1488         for (Call call : calls) {
   1489             if (!call.isIdle()) {
   1490                 return call;
   1491             } else if (call.getState() != Call.State.IDLE) {
   1492                 if (result == null) result = call;
   1493             }
   1494         }
   1495         return result;
   1496     }
   1497 
   1498     /**
   1499      * return one active background call from background calls
   1500      *
   1501      * Active call means the call is NOT idle defined by Call.isIdle()
   1502      *
   1503      * 1. If there is only one active background call, return it
   1504      * 2. If there is more than one active background call, return the first one
   1505      * 3. If there is no active background call, return the background call
   1506      *    associated with default phone, which state is IDLE.
   1507      * 4. If there is no background call at all, return null.
   1508      *
   1509      * Complete background calls list can be get by getBackgroundCalls()
   1510      */
   1511     public Call getFirstActiveBgCall() {
   1512         Call call = getFirstNonIdleCall(mBackgroundCalls);
   1513         if (call == null) {
   1514             call = (mDefaultPhone == null)
   1515                     ? null
   1516                     : mDefaultPhone.getBackgroundCall();
   1517         }
   1518         return call;
   1519     }
   1520 
   1521     /**
   1522      * return one active ringing call from ringing calls
   1523      *
   1524      * Active call means the call is NOT idle defined by Call.isIdle()
   1525      *
   1526      * 1. If there is only one active ringing call, return it
   1527      * 2. If there is more than one active ringing call, return the first one
   1528      * 3. If there is no active ringing call, return the ringing call
   1529      *    associated with default phone, which state is IDLE.
   1530      * 4. If there is no ringing call at all, return null.
   1531      *
   1532      * Complete ringing calls list can be get by getRingingCalls()
   1533      */
   1534     public Call getFirstActiveRingingCall() {
   1535         Call call = getFirstNonIdleCall(mRingingCalls);
   1536         if (call == null) {
   1537             call = (mDefaultPhone == null)
   1538                     ? null
   1539                     : mDefaultPhone.getRingingCall();
   1540         }
   1541         return call;
   1542     }
   1543 
   1544     /**
   1545      * @return the state of active foreground call
   1546      * return IDLE if there is no active foreground call
   1547      */
   1548     public Call.State getActiveFgCallState() {
   1549         Call fgCall = getActiveFgCall();
   1550 
   1551         if (fgCall != null) {
   1552             return fgCall.getState();
   1553         }
   1554 
   1555         return Call.State.IDLE;
   1556     }
   1557 
   1558     /**
   1559      * @return the connections of active foreground call
   1560      * return empty list if there is no active foreground call
   1561      */
   1562     public List<Connection> getFgCallConnections() {
   1563         Call fgCall = getActiveFgCall();
   1564         if ( fgCall != null) {
   1565             return fgCall.getConnections();
   1566         }
   1567         return emptyConnections;
   1568     }
   1569 
   1570     /**
   1571      * @return the connections of active background call
   1572      * return empty list if there is no active background call
   1573      */
   1574     public List<Connection> getBgCallConnections() {
   1575         Call bgCall = getFirstActiveBgCall();
   1576         if ( bgCall != null) {
   1577             return bgCall.getConnections();
   1578         }
   1579         return emptyConnections;
   1580     }
   1581 
   1582     /**
   1583      * @return the latest connection of active foreground call
   1584      * return null if there is no active foreground call
   1585      */
   1586     public Connection getFgCallLatestConnection() {
   1587         Call fgCall = getActiveFgCall();
   1588         if ( fgCall != null) {
   1589             return fgCall.getLatestConnection();
   1590         }
   1591         return null;
   1592     }
   1593 
   1594     /**
   1595      * @return true if there is at least one Foreground call in disconnected state
   1596      */
   1597     public boolean hasDisconnectedFgCall() {
   1598         return (getFirstCallOfState(mForegroundCalls, Call.State.DISCONNECTED) != null);
   1599     }
   1600 
   1601     /**
   1602      * @return true if there is at least one background call in disconnected state
   1603      */
   1604     public boolean hasDisconnectedBgCall() {
   1605         return (getFirstCallOfState(mBackgroundCalls, Call.State.DISCONNECTED) != null);
   1606     }
   1607 
   1608     /**
   1609      * @return the first active call from a call list
   1610      */
   1611     private  Call getFirstActiveCall(ArrayList<Call> calls) {
   1612         for (Call call : calls) {
   1613             if (!call.isIdle()) {
   1614                 return call;
   1615             }
   1616         }
   1617         return null;
   1618     }
   1619 
   1620     /**
   1621      * @return the first call in a the Call.state from a call list
   1622      */
   1623     private Call getFirstCallOfState(ArrayList<Call> calls, Call.State state) {
   1624         for (Call call : calls) {
   1625             if (call.getState() == state) {
   1626                 return call;
   1627             }
   1628         }
   1629         return null;
   1630     }
   1631 
   1632 
   1633     private boolean hasMoreThanOneRingingCall() {
   1634         int count = 0;
   1635         for (Call call : mRingingCalls) {
   1636             if (call.getState().isRinging()) {
   1637                 if (++count > 1) return true;
   1638             }
   1639         }
   1640         return false;
   1641     }
   1642 
   1643     private Handler mHandler = new Handler() {
   1644 
   1645         @Override
   1646         public void handleMessage(Message msg) {
   1647 
   1648             switch (msg.what) {
   1649                 case EVENT_DISCONNECT:
   1650                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISCONNECT)");
   1651                     mDisconnectRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1652                     break;
   1653                 case EVENT_PRECISE_CALL_STATE_CHANGED:
   1654                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_PRECISE_CALL_STATE_CHANGED)");
   1655                     mPreciseCallStateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1656                     break;
   1657                 case EVENT_NEW_RINGING_CONNECTION:
   1658                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_NEW_RINGING_CONNECTION)");
   1659                     if (getActiveFgCallState().isDialing() || hasMoreThanOneRingingCall()) {
   1660                         Connection c = (Connection) ((AsyncResult) msg.obj).result;
   1661                         try {
   1662                             Log.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
   1663                             c.getCall().hangup();
   1664                         } catch (CallStateException e) {
   1665                             Log.w(LOG_TAG, "new ringing connection", e);
   1666                         }
   1667                     } else {
   1668                         mNewRingingConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1669                     }
   1670                     break;
   1671                 case EVENT_UNKNOWN_CONNECTION:
   1672                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_UNKNOWN_CONNECTION)");
   1673                     mUnknownConnectionRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1674                     break;
   1675                 case EVENT_INCOMING_RING:
   1676                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_INCOMING_RING)");
   1677                     // The event may come from RIL who's not aware of an ongoing fg call
   1678                     if (!hasActiveFgCall()) {
   1679                         mIncomingRingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1680                     }
   1681                     break;
   1682                 case EVENT_RINGBACK_TONE:
   1683                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RINGBACK_TONE)");
   1684                     mRingbackToneRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1685                     break;
   1686                 case EVENT_IN_CALL_VOICE_PRIVACY_ON:
   1687                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_ON)");
   1688                     mInCallVoicePrivacyOnRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1689                     break;
   1690                 case EVENT_IN_CALL_VOICE_PRIVACY_OFF:
   1691                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_IN_CALL_VOICE_PRIVACY_OFF)");
   1692                     mInCallVoicePrivacyOffRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1693                     break;
   1694                 case EVENT_CALL_WAITING:
   1695                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CALL_WAITING)");
   1696                     mCallWaitingRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1697                     break;
   1698                 case EVENT_DISPLAY_INFO:
   1699                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_DISPLAY_INFO)");
   1700                     mDisplayInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1701                     break;
   1702                 case EVENT_SIGNAL_INFO:
   1703                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SIGNAL_INFO)");
   1704                     mSignalInfoRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1705                     break;
   1706                 case EVENT_CDMA_OTA_STATUS_CHANGE:
   1707                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_CDMA_OTA_STATUS_CHANGE)");
   1708                     mCdmaOtaStatusChangeRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1709                     break;
   1710                 case EVENT_RESEND_INCALL_MUTE:
   1711                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_RESEND_INCALL_MUTE)");
   1712                     mResendIncallMuteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1713                     break;
   1714                 case EVENT_MMI_INITIATE:
   1715                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_INITIATE)");
   1716                     mMmiInitiateRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1717                     break;
   1718                 case EVENT_MMI_COMPLETE:
   1719                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_MMI_COMPLETE)");
   1720                     mMmiCompleteRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1721                     break;
   1722                 case EVENT_ECM_TIMER_RESET:
   1723                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_ECM_TIMER_RESET)");
   1724                     mEcmTimerResetRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1725                     break;
   1726                 case EVENT_SUBSCRIPTION_INFO_READY:
   1727                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUBSCRIPTION_INFO_READY)");
   1728                     mSubscriptionInfoReadyRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1729                     break;
   1730                 case EVENT_SUPP_SERVICE_FAILED:
   1731                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SUPP_SERVICE_FAILED)");
   1732                     mSuppServiceFailedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1733                     break;
   1734                 case EVENT_SERVICE_STATE_CHANGED:
   1735                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_SERVICE_STATE_CHANGED)");
   1736                     mServiceStateChangedRegistrants.notifyRegistrants((AsyncResult) msg.obj);
   1737                     break;
   1738                 case EVENT_POST_DIAL_CHARACTER:
   1739                     // we need send the character that is being processed in msg.arg1
   1740                     // so can't use notifyRegistrants()
   1741                     if (VDBG) Log.d(LOG_TAG, " handleMessage (EVENT_POST_DIAL_CHARACTER)");
   1742                     for(int i=0; i < mPostDialCharacterRegistrants.size(); i++) {
   1743                         Message notifyMsg;
   1744                         notifyMsg = ((Registrant)mPostDialCharacterRegistrants.get(i)).messageForRegistrant();
   1745                         notifyMsg.obj = msg.obj;
   1746                         notifyMsg.arg1 = msg.arg1;
   1747                         notifyMsg.sendToTarget();
   1748                     }
   1749                     break;
   1750             }
   1751         }
   1752     };
   1753 
   1754     @Override
   1755     public String toString() {
   1756         Call call;
   1757         StringBuilder b = new StringBuilder();
   1758 
   1759         b.append("########### Dump CallManager ############");
   1760         b.append("\nCallManager state = " + getState());
   1761         call = getActiveFgCall();
   1762         b.append("\n   - Foreground: " + getActiveFgCallState());
   1763         b.append(" from " + call.getPhone());
   1764         b.append("\n     Conn: ").append(getFgCallConnections());
   1765         call = getFirstActiveBgCall();
   1766         b.append("\n   - Background: " + call.getState());
   1767         b.append(" from " + call.getPhone());
   1768         b.append("\n     Conn: ").append(getBgCallConnections());
   1769         call = getFirstActiveRingingCall();
   1770         b.append("\n   - Ringing: " +call.getState());
   1771         b.append(" from " + call.getPhone());
   1772 
   1773         for (Phone phone : getAllPhones()) {
   1774             if (phone != null) {
   1775                 b.append("\n Phone: " + phone + ", name = " + phone.getPhoneName()
   1776                         + ", state = " + phone.getState());
   1777                 call = phone.getForegroundCall();
   1778                 b.append("\n   - Foreground: ").append(call);
   1779                 call = phone.getBackgroundCall();
   1780                 b.append(" Background: ").append(call);
   1781                 call = phone.getRingingCall();
   1782                 b.append(" Ringing: ").append(call);
   1783             }
   1784         }
   1785         b.append("\n########## End Dump CallManager ##########");
   1786         return b.toString();
   1787     }
   1788 }
   1789