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