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