Home | History | Annotate | Download | only in gsm
      1 /*
      2  * Copyright (C) 2006 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.gsm;
     18 
     19 import android.content.ContentValues;
     20 import android.content.Context;
     21 import android.content.SharedPreferences;
     22 import android.database.SQLException;
     23 import android.net.Uri;
     24 import android.os.AsyncResult;
     25 import android.os.Bundle;
     26 import android.os.Handler;
     27 import android.os.Message;
     28 import android.os.Registrant;
     29 import android.os.RegistrantList;
     30 import android.preference.PreferenceManager;
     31 import android.provider.Telephony;
     32 import android.telecom.VideoProfile;
     33 import android.telephony.CellLocation;
     34 import android.telephony.PhoneNumberUtils;
     35 import android.telephony.ServiceState;
     36 import android.telephony.SubscriptionManager;
     37 import android.telephony.TelephonyManager;
     38 
     39 import com.android.internal.telephony.CallTracker;
     40 
     41 import android.text.TextUtils;
     42 import android.telephony.Rlog;
     43 import android.util.Log;
     44 
     45 import com.android.ims.ImsManager;
     46 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
     47 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
     48 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
     49 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
     50 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
     51 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
     52 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
     53 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
     54 import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
     55 import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
     56 import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
     57 
     58 import com.android.internal.telephony.dataconnection.DcTracker;
     59 import com.android.internal.telephony.Call;
     60 import com.android.internal.telephony.CallForwardInfo;
     61 import com.android.internal.telephony.CallStateException;
     62 import com.android.internal.telephony.CommandsInterface;
     63 import com.android.internal.telephony.Connection;
     64 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
     65 import com.android.internal.telephony.MmiCode;
     66 import com.android.internal.telephony.Phone;
     67 import com.android.internal.telephony.PhoneBase;
     68 import com.android.internal.telephony.PhoneConstants;
     69 import com.android.internal.telephony.PhoneNotifier;
     70 import com.android.internal.telephony.PhoneProxy;
     71 import com.android.internal.telephony.PhoneSubInfo;
     72 import com.android.internal.telephony.UUSInfo;
     73 import com.android.internal.telephony.imsphone.ImsPhone;
     74 import com.android.internal.telephony.test.SimulatedRadioControl;
     75 import com.android.internal.telephony.uicc.IccRecords;
     76 import com.android.internal.telephony.uicc.IccVmNotSupportedException;
     77 import com.android.internal.telephony.uicc.UiccCard;
     78 import com.android.internal.telephony.uicc.UiccCardApplication;
     79 import com.android.internal.telephony.uicc.UiccController;
     80 import com.android.internal.telephony.ServiceStateTracker;
     81 import com.android.internal.telephony.uicc.IsimRecords;
     82 import com.android.internal.telephony.uicc.IsimUiccRecords;
     83 
     84 import java.io.FileDescriptor;
     85 import java.io.PrintWriter;
     86 import java.util.ArrayList;
     87 import java.util.List;
     88 
     89 
     90 /**
     91  * {@hide}
     92  */
     93 public class GSMPhone extends PhoneBase {
     94     // NOTE that LOG_TAG here is "GSM", which means that log messages
     95     // from this file will go into the radio log rather than the main
     96     // log.  (Use "adb logcat -b radio" to see them.)
     97     static final String LOG_TAG = "GSMPhone";
     98     private static final boolean LOCAL_DEBUG = true;
     99     private static final boolean VDBG = false; /* STOPSHIP if true */
    100 
    101     // Key used to read/write current ciphering state
    102     public static final String CIPHERING_KEY = "ciphering_key";
    103     // Key used to read/write voice mail number
    104     public static final String VM_NUMBER = "vm_number_key";
    105     // Key used to read/write the SIM IMSI used for storing the voice mail
    106     public static final String VM_SIM_IMSI = "vm_sim_imsi_key";
    107 
    108     // Instance Variables
    109     GsmCallTracker mCT;
    110     GsmServiceStateTracker mSST;
    111     ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
    112     SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
    113     PhoneSubInfo mSubInfo;
    114 
    115 
    116     Registrant mPostDialHandler;
    117 
    118     /** List of Registrants to receive Supplementary Service Notifications. */
    119     RegistrantList mSsnRegistrants = new RegistrantList();
    120 
    121     // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
    122     private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList();
    123 
    124     private String mImei;
    125     private String mImeiSv;
    126     private String mVmNumber;
    127 
    128     private IsimUiccRecords mIsimUiccRecords;
    129 
    130     // Create Cfu (Call forward unconditional) so that dialing number &
    131     // mOnComplete (Message object passed by client) can be packed &
    132     // given as a single Cfu object as user data to RIL.
    133     private static class Cfu {
    134         final String mSetCfNumber;
    135         final Message mOnComplete;
    136 
    137         Cfu(String cfNumber, Message onComplete) {
    138             mSetCfNumber = cfNumber;
    139             mOnComplete = onComplete;
    140         }
    141     }
    142 
    143     // Constructors
    144 
    145     public
    146     GSMPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
    147         super("GSM", notifier, context, ci, unitTestMode);
    148 
    149         if (ci instanceof SimulatedRadioControl) {
    150             mSimulatedRadioControl = (SimulatedRadioControl) ci;
    151         }
    152 
    153         mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);
    154         mCT = new GsmCallTracker(this);
    155 
    156         mSST = new GsmServiceStateTracker(this);
    157         mDcTracker = new DcTracker(this);
    158 
    159         if (!unitTestMode) {
    160             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
    161             mSubInfo = new PhoneSubInfo(this);
    162         }
    163 
    164         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
    165         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
    166         mCi.registerForOn(this, EVENT_RADIO_ON, null);
    167         mCi.setOnUSSD(this, EVENT_USSD, null);
    168         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
    169         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
    170         mCi.setOnSs(this, EVENT_SS, null);
    171         setProperties();
    172     }
    173 
    174     public
    175     GSMPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId) {
    176         this(context, ci, notifier, false, phoneId);
    177     }
    178 
    179     public
    180     GSMPhone(Context context, CommandsInterface ci,
    181             PhoneNotifier notifier, boolean unitTestMode, int phoneId) {
    182         super("GSM", notifier, context, ci, unitTestMode, phoneId);
    183 
    184         if (ci instanceof SimulatedRadioControl) {
    185             mSimulatedRadioControl = (SimulatedRadioControl) ci;
    186         }
    187 
    188         mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);
    189         mCT = new GsmCallTracker(this);
    190 
    191         mSST = new GsmServiceStateTracker(this);
    192         mDcTracker = new DcTracker(this);
    193 
    194         if (!unitTestMode) {
    195             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
    196             mSubInfo = new PhoneSubInfo(this);
    197         }
    198 
    199         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
    200         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
    201         mCi.registerForOn(this, EVENT_RADIO_ON, null);
    202         mCi.setOnUSSD(this, EVENT_USSD, null);
    203         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
    204         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
    205         mCi.setOnSs(this, EVENT_SS, null);
    206         setProperties();
    207 
    208         log("GSMPhone: constructor: sub = " + mPhoneId);
    209 
    210         setProperties();
    211     }
    212 
    213     protected void setProperties() {
    214         TelephonyManager.from(mContext).setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_GSM);
    215     }
    216 
    217     @Override
    218     public void dispose() {
    219         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    220             super.dispose();
    221 
    222             //Unregister from all former registered events
    223             mCi.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
    224             unregisterForSimRecordEvents();
    225             mCi.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
    226             mCi.unregisterForOn(this); //EVENT_RADIO_ON
    227             mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
    228             mCi.unSetOnUSSD(this);
    229             mCi.unSetOnSuppServiceNotification(this);
    230             mCi.unSetOnSs(this);
    231 
    232             mPendingMMIs.clear();
    233 
    234             //Force all referenced classes to unregister their former registered events
    235             mCT.dispose();
    236             mDcTracker.dispose();
    237             mSST.dispose();
    238             mSimPhoneBookIntManager.dispose();
    239             mSubInfo.dispose();
    240         }
    241     }
    242 
    243     @Override
    244     public void removeReferences() {
    245         Rlog.d(LOG_TAG, "removeReferences");
    246         mSimulatedRadioControl = null;
    247         mSimPhoneBookIntManager = null;
    248         mSubInfo = null;
    249         mCT = null;
    250         mSST = null;
    251 
    252         super.removeReferences();
    253     }
    254 
    255     @Override
    256     protected void finalize() {
    257         if(LOCAL_DEBUG) Rlog.d(LOG_TAG, "GSMPhone finalized");
    258     }
    259 
    260     @Override
    261     public ServiceState
    262     getServiceState() {
    263         if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
    264             if (mImsPhone != null) {
    265                 return ServiceState.mergeServiceStates(
    266                         (mSST == null) ? new ServiceState() : mSST.mSS,
    267                         mImsPhone.getServiceState());
    268             }
    269         }
    270 
    271         if (mSST != null) {
    272             return mSST.mSS;
    273         } else {
    274             // avoid potential NPE in EmergencyCallHelper during Phone switch
    275             return new ServiceState();
    276         }
    277     }
    278 
    279     @Override
    280     public CellLocation getCellLocation() {
    281         return mSST.getCellLocation();
    282     }
    283 
    284     @Override
    285     public PhoneConstants.State getState() {
    286         if (mImsPhone != null) {
    287             PhoneConstants.State imsState = mImsPhone.getState();
    288             if (imsState != PhoneConstants.State.IDLE) {
    289                 return imsState;
    290             }
    291         }
    292 
    293         return mCT.mState;
    294     }
    295 
    296     @Override
    297     public int getPhoneType() {
    298         return PhoneConstants.PHONE_TYPE_GSM;
    299     }
    300 
    301     @Override
    302     public ServiceStateTracker getServiceStateTracker() {
    303         return mSST;
    304     }
    305 
    306     @Override
    307     public CallTracker getCallTracker() {
    308         return mCT;
    309     }
    310 
    311     // pending voice mail count updated after phone creation
    312     private void updateVoiceMail() {
    313         int countVoiceMessages = 0;
    314         IccRecords r = mIccRecords.get();
    315         if (r != null) {
    316             // get voice mail count from SIM
    317             countVoiceMessages = r.getVoiceMessageCount();
    318         }
    319         int countVoiceMessagesStored = getStoredVoiceMessageCount();
    320         if (countVoiceMessages == -1 && countVoiceMessagesStored != 0) {
    321             countVoiceMessages = countVoiceMessagesStored;
    322         }
    323         Rlog.d(LOG_TAG, "updateVoiceMail countVoiceMessages = " + countVoiceMessages
    324                 +" subId "+getSubId());
    325         setVoiceMessageCount(countVoiceMessages);
    326     }
    327 
    328     @Override
    329     public List<? extends MmiCode>
    330     getPendingMmiCodes() {
    331         return mPendingMMIs;
    332     }
    333 
    334     @Override
    335     public PhoneConstants.DataState getDataConnectionState(String apnType) {
    336         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
    337 
    338         if (mSST == null) {
    339             // Radio Technology Change is ongoning, dispose() and removeReferences() have
    340             // already been called
    341 
    342             ret = PhoneConstants.DataState.DISCONNECTED;
    343         } else if (!apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY) &&
    344                 mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
    345             // If we're out of service, open TCP sockets may still work
    346             // but no data will flow
    347 
    348             // Emergency APN is available even in Out Of Service
    349             // Pass the actual State of EPDN
    350 
    351             ret = PhoneConstants.DataState.DISCONNECTED;
    352         } else if (mDcTracker.isApnTypeEnabled(apnType) == false ||
    353                 mDcTracker.isApnTypeActive(apnType) == false) {
    354             //TODO: isApnTypeActive() is just checking whether ApnContext holds
    355             //      Dataconnection or not. Checking each ApnState below should
    356             //      provide the same state. Calling isApnTypeActive() can be removed.
    357             ret = PhoneConstants.DataState.DISCONNECTED;
    358         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
    359             switch (mDcTracker.getState(apnType)) {
    360                 case RETRYING:
    361                 case FAILED:
    362                 case IDLE:
    363                     ret = PhoneConstants.DataState.DISCONNECTED;
    364                 break;
    365 
    366                 case CONNECTED:
    367                 case DISCONNECTING:
    368                     if ( mCT.mState != PhoneConstants.State.IDLE
    369                             && !mSST.isConcurrentVoiceAndDataAllowed()) {
    370                         ret = PhoneConstants.DataState.SUSPENDED;
    371                     } else {
    372                         ret = PhoneConstants.DataState.CONNECTED;
    373                     }
    374                 break;
    375 
    376                 case CONNECTING:
    377                 case SCANNING:
    378                     ret = PhoneConstants.DataState.CONNECTING;
    379                 break;
    380             }
    381         }
    382 
    383         return ret;
    384     }
    385 
    386     @Override
    387     public DataActivityState getDataActivityState() {
    388         DataActivityState ret = DataActivityState.NONE;
    389 
    390         if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
    391             switch (mDcTracker.getActivity()) {
    392                 case DATAIN:
    393                     ret = DataActivityState.DATAIN;
    394                 break;
    395 
    396                 case DATAOUT:
    397                     ret = DataActivityState.DATAOUT;
    398                 break;
    399 
    400                 case DATAINANDOUT:
    401                     ret = DataActivityState.DATAINANDOUT;
    402                 break;
    403 
    404                 case DORMANT:
    405                     ret = DataActivityState.DORMANT;
    406                 break;
    407 
    408                 default:
    409                     ret = DataActivityState.NONE;
    410                 break;
    411             }
    412         }
    413 
    414         return ret;
    415     }
    416 
    417     /**
    418      * Notify any interested party of a Phone state change
    419      * {@link com.android.internal.telephony.PhoneConstants.State}
    420      */
    421     /*package*/ void notifyPhoneStateChanged() {
    422         mNotifier.notifyPhoneState(this);
    423     }
    424 
    425     /**
    426      * Notify registrants of a change in the call state. This notifies changes in
    427      * {@link com.android.internal.telephony.Call.State}. Use this when changes
    428      * in the precise call state are needed, else use notifyPhoneStateChanged.
    429      */
    430     /*package*/ void notifyPreciseCallStateChanged() {
    431         /* we'd love it if this was package-scoped*/
    432         super.notifyPreciseCallStateChangedP();
    433     }
    434 
    435     public void notifyNewRingingConnection(Connection c) {
    436         super.notifyNewRingingConnectionP(c);
    437     }
    438 
    439     /*package*/ void
    440     notifyDisconnect(Connection cn) {
    441         mDisconnectRegistrants.notifyResult(cn);
    442 
    443         mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
    444     }
    445 
    446     void notifyUnknownConnection(Connection cn) {
    447         mUnknownConnectionRegistrants.notifyResult(cn);
    448     }
    449 
    450     void notifySuppServiceFailed(SuppService code) {
    451         mSuppServiceFailedRegistrants.notifyResult(code);
    452     }
    453 
    454     /*package*/ void
    455     notifyServiceStateChanged(ServiceState ss) {
    456         super.notifyServiceStateChangedP(ss);
    457     }
    458 
    459     /*package*/
    460     void notifyLocationChanged() {
    461         mNotifier.notifyCellLocation(this);
    462     }
    463 
    464     @Override
    465     public void
    466     notifyCallForwardingIndicator() {
    467         mNotifier.notifyCallForwardingChanged(this);
    468     }
    469 
    470     // override for allowing access from other classes of this package
    471     /**
    472      * {@inheritDoc}
    473      */
    474     @Override
    475     public void
    476     setSystemProperty(String property, String value) {
    477         TelephonyManager.setTelephonyProperty(mPhoneId, property, value);
    478     }
    479 
    480     @Override
    481     public void registerForSuppServiceNotification(
    482             Handler h, int what, Object obj) {
    483         mSsnRegistrants.addUnique(h, what, obj);
    484         if (mSsnRegistrants.size() == 1) mCi.setSuppServiceNotifications(true, null);
    485     }
    486 
    487     @Override
    488     public void unregisterForSuppServiceNotification(Handler h) {
    489         mSsnRegistrants.remove(h);
    490         if (mSsnRegistrants.size() == 0) mCi.setSuppServiceNotifications(false, null);
    491     }
    492 
    493     @Override
    494     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
    495         mSimRecordsLoadedRegistrants.addUnique(h, what, obj);
    496     }
    497 
    498     @Override
    499     public void unregisterForSimRecordsLoaded(Handler h) {
    500         mSimRecordsLoadedRegistrants.remove(h);
    501     }
    502 
    503     @Override
    504     public void
    505     acceptCall(int videoState) throws CallStateException {
    506         ImsPhone imsPhone = mImsPhone;
    507         if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) {
    508             imsPhone.acceptCall(videoState);
    509         } else {
    510             mCT.acceptCall();
    511         }
    512     }
    513 
    514     @Override
    515     public void
    516     rejectCall() throws CallStateException {
    517         mCT.rejectCall();
    518     }
    519 
    520     @Override
    521     public void
    522     switchHoldingAndActive() throws CallStateException {
    523         mCT.switchWaitingOrHoldingAndActive();
    524     }
    525 
    526     @Override
    527     public boolean canConference() {
    528         boolean canImsConference = false;
    529         if (mImsPhone != null) {
    530             canImsConference = mImsPhone.canConference();
    531         }
    532         return mCT.canConference() || canImsConference;
    533     }
    534 
    535     public boolean canDial() {
    536         return mCT.canDial();
    537     }
    538 
    539     @Override
    540     public void conference() {
    541         if (mImsPhone != null && mImsPhone.canConference()) {
    542             log("conference() - delegated to IMS phone");
    543             mImsPhone.conference();
    544             return;
    545         }
    546         mCT.conference();
    547     }
    548 
    549     @Override
    550     public void clearDisconnected() {
    551         mCT.clearDisconnected();
    552     }
    553 
    554     @Override
    555     public boolean canTransfer() {
    556         return mCT.canTransfer();
    557     }
    558 
    559     @Override
    560     public void explicitCallTransfer() {
    561         mCT.explicitCallTransfer();
    562     }
    563 
    564     @Override
    565     public GsmCall
    566     getForegroundCall() {
    567         return mCT.mForegroundCall;
    568     }
    569 
    570     @Override
    571     public GsmCall
    572     getBackgroundCall() {
    573         return mCT.mBackgroundCall;
    574     }
    575 
    576     @Override
    577     public Call getRingingCall() {
    578         ImsPhone imsPhone = mImsPhone;
    579         if ( mCT.mRingingCall != null && mCT.mRingingCall.isRinging() ) {
    580             return mCT.mRingingCall;
    581         } else if ( imsPhone != null ) {
    582             return imsPhone.getRingingCall();
    583         }
    584         return mCT.mRingingCall;
    585     }
    586 
    587     private boolean handleCallDeflectionIncallSupplementaryService(
    588             String dialString) {
    589         if (dialString.length() > 1) {
    590             return false;
    591         }
    592 
    593         if (getRingingCall().getState() != GsmCall.State.IDLE) {
    594             if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "MmiCode 0: rejectCall");
    595             try {
    596                 mCT.rejectCall();
    597             } catch (CallStateException e) {
    598                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    599                     "reject failed", e);
    600                 notifySuppServiceFailed(Phone.SuppService.REJECT);
    601             }
    602         } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) {
    603             if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    604                     "MmiCode 0: hangupWaitingOrBackground");
    605             mCT.hangupWaitingOrBackground();
    606         }
    607 
    608         return true;
    609     }
    610 
    611     private boolean handleCallWaitingIncallSupplementaryService(
    612             String dialString) {
    613         int len = dialString.length();
    614 
    615         if (len > 2) {
    616             return false;
    617         }
    618 
    619         GsmCall call = getForegroundCall();
    620 
    621         try {
    622             if (len > 1) {
    623                 char ch = dialString.charAt(1);
    624                 int callIndex = ch - '0';
    625 
    626                 if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
    627                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    628                             "MmiCode 1: hangupConnectionByIndex " +
    629                             callIndex);
    630                     mCT.hangupConnectionByIndex(call, callIndex);
    631                 }
    632             } else {
    633                 if (call.getState() != GsmCall.State.IDLE) {
    634                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    635                             "MmiCode 1: hangup foreground");
    636                     //mCT.hangupForegroundResumeBackground();
    637                     mCT.hangup(call);
    638                 } else {
    639                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    640                             "MmiCode 1: switchWaitingOrHoldingAndActive");
    641                     mCT.switchWaitingOrHoldingAndActive();
    642                 }
    643             }
    644         } catch (CallStateException e) {
    645             if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    646                 "hangup failed", e);
    647             notifySuppServiceFailed(Phone.SuppService.HANGUP);
    648         }
    649 
    650         return true;
    651     }
    652 
    653     private boolean handleCallHoldIncallSupplementaryService(String dialString) {
    654         int len = dialString.length();
    655 
    656         if (len > 2) {
    657             return false;
    658         }
    659 
    660         GsmCall call = getForegroundCall();
    661 
    662         if (len > 1) {
    663             try {
    664                 char ch = dialString.charAt(1);
    665                 int callIndex = ch - '0';
    666                 GsmConnection conn = mCT.getConnectionByIndex(call, callIndex);
    667 
    668                 // gsm index starts at 1, up to 5 connections in a call,
    669                 if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
    670                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "MmiCode 2: separate call "+
    671                             callIndex);
    672                     mCT.separate(conn);
    673                 } else {
    674                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "separate: invalid call index "+
    675                             callIndex);
    676                     notifySuppServiceFailed(Phone.SuppService.SEPARATE);
    677                 }
    678             } catch (CallStateException e) {
    679                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    680                     "separate failed", e);
    681                 notifySuppServiceFailed(Phone.SuppService.SEPARATE);
    682             }
    683         } else {
    684             try {
    685                 if (getRingingCall().getState() != GsmCall.State.IDLE) {
    686                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    687                     "MmiCode 2: accept ringing call");
    688                     mCT.acceptCall();
    689                 } else {
    690                     if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    691                     "MmiCode 2: switchWaitingOrHoldingAndActive");
    692                     mCT.switchWaitingOrHoldingAndActive();
    693                 }
    694             } catch (CallStateException e) {
    695                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    696                     "switch failed", e);
    697                 notifySuppServiceFailed(Phone.SuppService.SWITCH);
    698             }
    699         }
    700 
    701         return true;
    702     }
    703 
    704     private boolean handleMultipartyIncallSupplementaryService(
    705             String dialString) {
    706         if (dialString.length() > 1) {
    707             return false;
    708         }
    709 
    710         if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "MmiCode 3: merge calls");
    711         conference();
    712         return true;
    713     }
    714 
    715     private boolean handleEctIncallSupplementaryService(String dialString) {
    716 
    717         int len = dialString.length();
    718 
    719         if (len != 1) {
    720             return false;
    721         }
    722 
    723         if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "MmiCode 4: explicit call transfer");
    724         explicitCallTransfer();
    725         return true;
    726     }
    727 
    728     private boolean handleCcbsIncallSupplementaryService(String dialString) {
    729         if (dialString.length() > 1) {
    730             return false;
    731         }
    732 
    733         Rlog.i(LOG_TAG, "MmiCode 5: CCBS not supported!");
    734         // Treat it as an "unknown" service.
    735         notifySuppServiceFailed(Phone.SuppService.UNKNOWN);
    736         return true;
    737     }
    738 
    739     @Override
    740     public boolean handleInCallMmiCommands(String dialString) throws CallStateException {
    741         ImsPhone imsPhone = mImsPhone;
    742         if (imsPhone != null
    743                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
    744             return imsPhone.handleInCallMmiCommands(dialString);
    745         }
    746 
    747         if (!isInCall()) {
    748             return false;
    749         }
    750 
    751         if (TextUtils.isEmpty(dialString)) {
    752             return false;
    753         }
    754 
    755         boolean result = false;
    756         char ch = dialString.charAt(0);
    757         switch (ch) {
    758             case '0':
    759                 result = handleCallDeflectionIncallSupplementaryService(
    760                         dialString);
    761                 break;
    762             case '1':
    763                 result = handleCallWaitingIncallSupplementaryService(
    764                         dialString);
    765                 break;
    766             case '2':
    767                 result = handleCallHoldIncallSupplementaryService(dialString);
    768                 break;
    769             case '3':
    770                 result = handleMultipartyIncallSupplementaryService(dialString);
    771                 break;
    772             case '4':
    773                 result = handleEctIncallSupplementaryService(dialString);
    774                 break;
    775             case '5':
    776                 result = handleCcbsIncallSupplementaryService(dialString);
    777                 break;
    778             default:
    779                 break;
    780         }
    781 
    782         return result;
    783     }
    784 
    785     boolean isInCall() {
    786         GsmCall.State foregroundCallState = getForegroundCall().getState();
    787         GsmCall.State backgroundCallState = getBackgroundCall().getState();
    788         GsmCall.State ringingCallState = getRingingCall().getState();
    789 
    790        return (foregroundCallState.isAlive() ||
    791                 backgroundCallState.isAlive() ||
    792                 ringingCallState.isAlive());
    793     }
    794 
    795     @Override
    796     public Connection
    797     dial(String dialString, int videoState) throws CallStateException {
    798         return dial(dialString, null, videoState, null);
    799     }
    800 
    801     @Override
    802     public Connection
    803     dial (String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
    804             throws CallStateException {
    805         boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(dialString);
    806         ImsPhone imsPhone = mImsPhone;
    807 
    808         boolean imsUseEnabled = isImsUseEnabled()
    809                  && imsPhone != null
    810                  && (imsPhone.isVolteEnabled() || imsPhone.isVowifiEnabled())
    811                  && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
    812 
    813         boolean useImsForEmergency = ImsManager.isVolteEnabledByPlatform(mContext)
    814                 && imsPhone != null
    815                 && isEmergency
    816                 &&  mContext.getResources().getBoolean(
    817                         com.android.internal.R.bool.useImsAlwaysForEmergencyCall)
    818                 && ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext)
    819                 && (imsPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF);
    820 
    821         if (LOCAL_DEBUG) {
    822             Rlog.d(LOG_TAG, "imsUseEnabled=" + imsUseEnabled
    823                     + ", useImsForEmergency=" + useImsForEmergency
    824                     + ", imsPhone=" + imsPhone
    825                     + ", imsPhone.isVolteEnabled()="
    826                     + ((imsPhone != null) ? imsPhone.isVolteEnabled() : "N/A")
    827                     + ", imsPhone.isVowifiEnabled()="
    828                     + ((imsPhone != null) ? imsPhone.isVowifiEnabled() : "N/A")
    829                     + ", imsPhone.getServiceState().getState()="
    830                     + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A"));
    831         }
    832 
    833         ImsPhone.checkWfcWifiOnlyModeBeforeDial(mImsPhone, mContext);
    834 
    835         if (imsUseEnabled || useImsForEmergency) {
    836             try {
    837                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "Trying IMS PS call");
    838                 return imsPhone.dial(dialString, uusInfo, videoState, intentExtras);
    839             } catch (CallStateException e) {
    840                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "IMS PS call exception " + e +
    841                         "imsUseEnabled =" + imsUseEnabled + ", imsPhone =" + imsPhone);
    842                 if (!ImsPhone.CS_FALLBACK.equals(e.getMessage())) {
    843                     CallStateException ce = new CallStateException(e.getMessage());
    844                     ce.setStackTrace(e.getStackTrace());
    845                     throw ce;
    846                 }
    847             }
    848         }
    849 
    850         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE
    851                 && mSST.mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE && !isEmergency) {
    852             throw new CallStateException("cannot dial in current state");
    853         }
    854         if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "Trying (non-IMS) CS call");
    855         return dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, intentExtras);
    856     }
    857 
    858     @Override
    859     protected Connection
    860     dialInternal (String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
    861             throws CallStateException {
    862 
    863         // Need to make sure dialString gets parsed properly
    864         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
    865 
    866         // handle in-call MMI first if applicable
    867         if (handleInCallMmiCommands(newDialString)) {
    868             return null;
    869         }
    870 
    871         // Only look at the Network portion for mmi
    872         String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
    873         GsmMmiCode mmi =
    874                 GsmMmiCode.newFromDialString(networkPortion, this, mUiccApplication.get());
    875         if (LOCAL_DEBUG) Rlog.d(LOG_TAG,
    876                                "dialing w/ mmi '" + mmi + "'...");
    877 
    878         if (mmi == null) {
    879             return mCT.dial(newDialString, uusInfo, intentExtras);
    880         } else if (mmi.isTemporaryModeCLIR()) {
    881             return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras);
    882         } else {
    883             mPendingMMIs.add(mmi);
    884             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    885             mmi.processCode();
    886 
    887             // FIXME should this return null or something else?
    888             return null;
    889         }
    890     }
    891 
    892     @Override
    893     public boolean handlePinMmi(String dialString) {
    894         GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
    895 
    896         if (mmi != null && mmi.isPinPukCommand()) {
    897             mPendingMMIs.add(mmi);
    898             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    899             mmi.processCode();
    900             return true;
    901         }
    902 
    903         return false;
    904     }
    905 
    906     @Override
    907     public void sendUssdResponse(String ussdMessge) {
    908         GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this, mUiccApplication.get());
    909         mPendingMMIs.add(mmi);
    910         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    911         mmi.sendUssd(ussdMessge);
    912     }
    913 
    914     @Override
    915     public void
    916     sendDtmf(char c) {
    917         if (!PhoneNumberUtils.is12Key(c)) {
    918             Rlog.e(LOG_TAG,
    919                     "sendDtmf called with invalid character '" + c + "'");
    920         } else {
    921             if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
    922                 mCi.sendDtmf(c, null);
    923             }
    924         }
    925     }
    926 
    927     @Override
    928     public void
    929     startDtmf(char c) {
    930         if (!PhoneNumberUtils.is12Key(c)) {
    931             Rlog.e(LOG_TAG,
    932                 "startDtmf called with invalid character '" + c + "'");
    933         } else {
    934             mCi.startDtmf(c, null);
    935         }
    936     }
    937 
    938     @Override
    939     public void
    940     stopDtmf() {
    941         mCi.stopDtmf(null);
    942     }
    943 
    944     public void
    945     sendBurstDtmf(String dtmfString) {
    946         Rlog.e(LOG_TAG, "[GSMPhone] sendBurstDtmf() is a CDMA method");
    947     }
    948 
    949     @Override
    950     public void
    951     setRadioPower(boolean power) {
    952         mSST.setRadioPower(power);
    953     }
    954 
    955     private void storeVoiceMailNumber(String number) {
    956         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    957         SharedPreferences.Editor editor = sp.edit();
    958         editor.putString(VM_NUMBER + getPhoneId(), number);
    959         editor.apply();
    960         setVmSimImsi(getSubscriberId());
    961     }
    962 
    963     @Override
    964     public String getVoiceMailNumber() {
    965         // Read from the SIM. If its null, try reading from the shared preference area.
    966         IccRecords r = mIccRecords.get();
    967         String number = (r != null) ? r.getVoiceMailNumber() : "";
    968         if (TextUtils.isEmpty(number)) {
    969             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    970             number = sp.getString(VM_NUMBER + getPhoneId(), null);
    971         }
    972 
    973         if (TextUtils.isEmpty(number)) {
    974             String[] listArray = getContext().getResources()
    975                 .getStringArray(com.android.internal.R.array.config_default_vm_number);
    976             if (listArray != null && listArray.length > 0) {
    977                 for (int i=0; i<listArray.length; i++) {
    978                     if (!TextUtils.isEmpty(listArray[i])) {
    979                         String[] defaultVMNumberArray = listArray[i].split(";");
    980                         if (defaultVMNumberArray != null && defaultVMNumberArray.length > 0) {
    981                             if (defaultVMNumberArray.length == 1) {
    982                                 number = defaultVMNumberArray[0];
    983                             } else if (defaultVMNumberArray.length == 2 &&
    984                                     !TextUtils.isEmpty(defaultVMNumberArray[1]) &&
    985                                     defaultVMNumberArray[1].equalsIgnoreCase(getGroupIdLevel1())) {
    986                                 number = defaultVMNumberArray[0];
    987                                 break;
    988                             }
    989                         }
    990                     }
    991                 }
    992             }
    993         }
    994         return number;
    995     }
    996 
    997     private String getVmSimImsi() {
    998         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    999         return sp.getString(VM_SIM_IMSI + getPhoneId(), null);
   1000     }
   1001 
   1002     private void setVmSimImsi(String imsi) {
   1003         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1004         SharedPreferences.Editor editor = sp.edit();
   1005         editor.putString(VM_SIM_IMSI + getPhoneId(), imsi);
   1006         editor.apply();
   1007     }
   1008 
   1009     @Override
   1010     public String getVoiceMailAlphaTag() {
   1011         String ret;
   1012         IccRecords r = mIccRecords.get();
   1013 
   1014         ret = (r != null) ? r.getVoiceMailAlphaTag() : "";
   1015 
   1016         if (ret == null || ret.length() == 0) {
   1017             return mContext.getText(
   1018                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
   1019         }
   1020 
   1021         return ret;
   1022     }
   1023 
   1024     @Override
   1025     public String getDeviceId() {
   1026         return mImei;
   1027     }
   1028 
   1029     @Override
   1030     public String getDeviceSvn() {
   1031         return mImeiSv;
   1032     }
   1033 
   1034     @Override
   1035     public IsimRecords getIsimRecords() {
   1036         return mIsimUiccRecords;
   1037     }
   1038 
   1039     @Override
   1040     public String getImei() {
   1041         return mImei;
   1042     }
   1043 
   1044     @Override
   1045     public String getEsn() {
   1046         Rlog.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method");
   1047         return "0";
   1048     }
   1049 
   1050     @Override
   1051     public String getMeid() {
   1052         Rlog.e(LOG_TAG, "[GSMPhone] getMeid() is a CDMA method");
   1053         return "0";
   1054     }
   1055 
   1056     @Override
   1057     public String getNai() {
   1058         IccRecords r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP2);
   1059         if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
   1060             Rlog.v(LOG_TAG, "IccRecords is " + r);
   1061         }
   1062         return (r != null) ? r.getNAI() : null;
   1063     }
   1064 
   1065     @Override
   1066     public String getSubscriberId() {
   1067         IccRecords r = mIccRecords.get();
   1068         return (r != null) ? r.getIMSI() : null;
   1069     }
   1070 
   1071     @Override
   1072     public String getGroupIdLevel1() {
   1073         IccRecords r = mIccRecords.get();
   1074         return (r != null) ? r.getGid1() : null;
   1075     }
   1076 
   1077     @Override
   1078     public String getGroupIdLevel2() {
   1079         IccRecords r = mIccRecords.get();
   1080         return (r != null) ? r.getGid2() : null;
   1081     }
   1082 
   1083     @Override
   1084     public String getLine1Number() {
   1085         IccRecords r = mIccRecords.get();
   1086         return (r != null) ? r.getMsisdnNumber() : null;
   1087     }
   1088 
   1089     @Override
   1090     public String getMsisdn() {
   1091         IccRecords r = mIccRecords.get();
   1092         return (r != null) ? r.getMsisdnNumber() : null;
   1093     }
   1094 
   1095     @Override
   1096     public String getLine1AlphaTag() {
   1097         IccRecords r = mIccRecords.get();
   1098         return (r != null) ? r.getMsisdnAlphaTag() : null;
   1099     }
   1100 
   1101     @Override
   1102     public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
   1103         IccRecords r = mIccRecords.get();
   1104         if (r != null) {
   1105             r.setMsisdnNumber(alphaTag, number, onComplete);
   1106             return true;
   1107         } else {
   1108             return false;
   1109         }
   1110     }
   1111 
   1112     @Override
   1113     public void setVoiceMailNumber(String alphaTag,
   1114                             String voiceMailNumber,
   1115                             Message onComplete) {
   1116 
   1117         Message resp;
   1118         mVmNumber = voiceMailNumber;
   1119         resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
   1120         IccRecords r = mIccRecords.get();
   1121         if (r != null) {
   1122             r.setVoiceMailNumber(alphaTag, mVmNumber, resp);
   1123         }
   1124     }
   1125 
   1126     private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
   1127         switch (commandInterfaceCFReason) {
   1128         case CF_REASON_UNCONDITIONAL:
   1129         case CF_REASON_BUSY:
   1130         case CF_REASON_NO_REPLY:
   1131         case CF_REASON_NOT_REACHABLE:
   1132         case CF_REASON_ALL:
   1133         case CF_REASON_ALL_CONDITIONAL:
   1134             return true;
   1135         default:
   1136             return false;
   1137         }
   1138     }
   1139 
   1140     @Override
   1141     public String getSystemProperty(String property, String defValue) {
   1142         if(getUnitTestMode()) {
   1143             return null;
   1144         }
   1145         return TelephonyManager.getTelephonyProperty(mPhoneId, property, defValue);
   1146     }
   1147 
   1148     private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
   1149         switch (commandInterfaceCFAction) {
   1150         case CF_ACTION_DISABLE:
   1151         case CF_ACTION_ENABLE:
   1152         case CF_ACTION_REGISTRATION:
   1153         case CF_ACTION_ERASURE:
   1154             return true;
   1155         default:
   1156             return false;
   1157         }
   1158     }
   1159 
   1160     public void updateDataConnectionTracker() {
   1161         ((DcTracker)mDcTracker).update();
   1162     }
   1163 
   1164     protected  boolean isCfEnable(int action) {
   1165         return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
   1166     }
   1167 
   1168     @Override
   1169     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
   1170         ImsPhone imsPhone = mImsPhone;
   1171         if ((imsPhone != null)
   1172                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
   1173             imsPhone.getCallForwardingOption(commandInterfaceCFReason, onComplete);
   1174             return;
   1175         }
   1176 
   1177         if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
   1178             if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "requesting call forwarding query.");
   1179             Message resp;
   1180             if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
   1181                 resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
   1182             } else {
   1183                 resp = onComplete;
   1184             }
   1185             mCi.queryCallForwardStatus(commandInterfaceCFReason,0,null,resp);
   1186         }
   1187     }
   1188 
   1189     @Override
   1190     public void setCallForwardingOption(int commandInterfaceCFAction,
   1191             int commandInterfaceCFReason,
   1192             String dialingNumber,
   1193             int timerSeconds,
   1194             Message onComplete) {
   1195         ImsPhone imsPhone = mImsPhone;
   1196         if ((imsPhone != null)
   1197                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
   1198             imsPhone.setCallForwardingOption(commandInterfaceCFAction,
   1199                     commandInterfaceCFReason, dialingNumber, timerSeconds, onComplete);
   1200             return;
   1201         }
   1202 
   1203         if (    (isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
   1204                 (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
   1205 
   1206             Message resp;
   1207             if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
   1208                 Cfu cfu = new Cfu(dialingNumber, onComplete);
   1209                 resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
   1210                         isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, cfu);
   1211             } else {
   1212                 resp = onComplete;
   1213             }
   1214             mCi.setCallForward(commandInterfaceCFAction,
   1215                     commandInterfaceCFReason,
   1216                     CommandsInterface.SERVICE_CLASS_VOICE,
   1217                     dialingNumber,
   1218                     timerSeconds,
   1219                     resp);
   1220         }
   1221     }
   1222 
   1223     @Override
   1224     public void getOutgoingCallerIdDisplay(Message onComplete) {
   1225         mCi.getCLIR(onComplete);
   1226     }
   1227 
   1228     @Override
   1229     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
   1230                                            Message onComplete) {
   1231         mCi.setCLIR(commandInterfaceCLIRMode,
   1232                 obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
   1233     }
   1234 
   1235     @Override
   1236     public void getCallWaiting(Message onComplete) {
   1237         ImsPhone imsPhone = mImsPhone;
   1238         if ((imsPhone != null)
   1239                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
   1240             imsPhone.getCallWaiting(onComplete);
   1241             return;
   1242         }
   1243 
   1244         //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
   1245         //class parameter in call waiting interrogation  to network
   1246         mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete);
   1247     }
   1248 
   1249     @Override
   1250     public void setCallWaiting(boolean enable, Message onComplete) {
   1251         ImsPhone imsPhone = mImsPhone;
   1252         if ((imsPhone != null)
   1253                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
   1254             imsPhone.setCallWaiting(enable, onComplete);
   1255             return;
   1256         }
   1257 
   1258         mCi.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
   1259     }
   1260 
   1261     @Override
   1262     public void
   1263     getAvailableNetworks(Message response) {
   1264         mCi.getAvailableNetworks(response);
   1265     }
   1266 
   1267     @Override
   1268     public void
   1269     getNeighboringCids(Message response) {
   1270         mCi.getNeighboringCids(response);
   1271     }
   1272 
   1273     @Override
   1274     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
   1275         mPostDialHandler = new Registrant(h, what, obj);
   1276     }
   1277 
   1278     @Override
   1279     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
   1280        if (mImsPhone != null) {
   1281            mImsPhone.setUiTTYMode(uiTtyMode, onComplete);
   1282        }
   1283     }
   1284 
   1285     @Override
   1286     public void setMute(boolean muted) {
   1287         mCT.setMute(muted);
   1288     }
   1289 
   1290     @Override
   1291     public boolean getMute() {
   1292         return mCT.getMute();
   1293     }
   1294 
   1295     @Override
   1296     public void getDataCallList(Message response) {
   1297         mCi.getDataCallList(response);
   1298     }
   1299 
   1300     @Override
   1301     public void updateServiceLocation() {
   1302         mSST.enableSingleLocationUpdate();
   1303     }
   1304 
   1305     @Override
   1306     public void enableLocationUpdates() {
   1307         mSST.enableLocationUpdates();
   1308     }
   1309 
   1310     @Override
   1311     public void disableLocationUpdates() {
   1312         mSST.disableLocationUpdates();
   1313     }
   1314 
   1315     @Override
   1316     public boolean getDataRoamingEnabled() {
   1317         return mDcTracker.getDataOnRoamingEnabled();
   1318     }
   1319 
   1320     @Override
   1321     public void setDataRoamingEnabled(boolean enable) {
   1322         mDcTracker.setDataOnRoamingEnabled(enable);
   1323     }
   1324 
   1325     @Override
   1326     public boolean getDataEnabled() {
   1327         return mDcTracker.getDataEnabled();
   1328     }
   1329 
   1330     @Override
   1331     public void setDataEnabled(boolean enable) {
   1332         mDcTracker.setDataEnabled(enable);
   1333     }
   1334 
   1335     /**
   1336      * Removes the given MMI from the pending list and notifies
   1337      * registrants that it is complete.
   1338      * @param mmi MMI that is done
   1339      */
   1340     /*package*/ void
   1341     onMMIDone(GsmMmiCode mmi) {
   1342         /* Only notify complete if it's on the pending list.
   1343          * Otherwise, it's already been handled (eg, previously canceled).
   1344          * The exception is cancellation of an incoming USSD-REQUEST, which is
   1345          * not on the list.
   1346          */
   1347         if (mPendingMMIs.remove(mmi) || mmi.isUssdRequest() || mmi.isSsInfo()) {
   1348             mMmiCompleteRegistrants.notifyRegistrants(
   1349                 new AsyncResult(null, mmi, null));
   1350         }
   1351     }
   1352 
   1353 
   1354     private void
   1355     onNetworkInitiatedUssd(GsmMmiCode mmi) {
   1356         mMmiCompleteRegistrants.notifyRegistrants(
   1357             new AsyncResult(null, mmi, null));
   1358     }
   1359 
   1360 
   1361     /** ussdMode is one of CommandsInterface.USSD_MODE_* */
   1362     private void
   1363     onIncomingUSSD (int ussdMode, String ussdMessage) {
   1364         boolean isUssdError;
   1365         boolean isUssdRequest;
   1366         boolean isUssdRelease;
   1367 
   1368         isUssdRequest
   1369             = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
   1370 
   1371         isUssdError
   1372             = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
   1373                 && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
   1374 
   1375         isUssdRelease = (ussdMode == CommandsInterface.USSD_MODE_NW_RELEASE);
   1376 
   1377         // See comments in GsmMmiCode.java
   1378         // USSD requests aren't finished until one
   1379         // of these two events happen
   1380         GsmMmiCode found = null;
   1381         for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
   1382             if(mPendingMMIs.get(i).isPendingUSSD()) {
   1383                 found = mPendingMMIs.get(i);
   1384                 break;
   1385             }
   1386         }
   1387 
   1388         if (found != null) {
   1389             // Complete pending USSD
   1390 
   1391             if (isUssdRelease) {
   1392                 found.onUssdRelease();
   1393             } else if (isUssdError) {
   1394                 found.onUssdFinishedError();
   1395             } else {
   1396                 found.onUssdFinished(ussdMessage, isUssdRequest);
   1397             }
   1398         } else { // pending USSD not found
   1399             // The network may initiate its own USSD request
   1400 
   1401             // ignore everything that isnt a Notify or a Request
   1402             // also, discard if there is no message to present
   1403             if (!isUssdError && ussdMessage != null) {
   1404                 GsmMmiCode mmi;
   1405                 mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
   1406                                                    isUssdRequest,
   1407                                                    GSMPhone.this,
   1408                                                    mUiccApplication.get());
   1409                 onNetworkInitiatedUssd(mmi);
   1410             }
   1411         }
   1412     }
   1413 
   1414     /**
   1415      * Make sure the network knows our preferred setting.
   1416      */
   1417     protected  void syncClirSetting() {
   1418         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1419         int clirSetting = sp.getInt(CLIR_KEY + getPhoneId(), -1);
   1420         if (clirSetting >= 0) {
   1421             mCi.setCLIR(clirSetting, null);
   1422         }
   1423     }
   1424 
   1425     @Override
   1426     public void handleMessage (Message msg) {
   1427         AsyncResult ar;
   1428         Message onComplete;
   1429 
   1430         // messages to be handled whether or not the phone is being destroyed
   1431         // should only include messages which are being re-directed and do not use
   1432         // resources of the phone being destroyed
   1433         switch (msg.what) {
   1434             // handle the select network completion callbacks.
   1435             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
   1436             case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
   1437                 super.handleMessage(msg);
   1438                 return;
   1439         }
   1440 
   1441         if (!mIsTheCurrentActivePhone) {
   1442             Rlog.e(LOG_TAG, "Received message " + msg +
   1443                     "[" + msg.what + "] while being destroyed. Ignoring.");
   1444             return;
   1445         }
   1446         switch (msg.what) {
   1447             case EVENT_RADIO_AVAILABLE: {
   1448                 mCi.getBasebandVersion(
   1449                         obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
   1450 
   1451                 mCi.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
   1452                 mCi.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE));
   1453                 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
   1454                 startLceAfterRadioIsAvailable();
   1455             }
   1456             break;
   1457 
   1458             case EVENT_RADIO_ON:
   1459                 // If this is on APM off, SIM may already be loaded. Send setPreferredNetworkType
   1460                 // request to RIL to preserve user setting across APM toggling
   1461                 setPreferredNetworkTypeIfSimLoaded();
   1462                 break;
   1463 
   1464             case EVENT_REGISTERED_TO_NETWORK:
   1465                 syncClirSetting();
   1466                 break;
   1467 
   1468             case EVENT_SIM_RECORDS_LOADED:
   1469                 updateCurrentCarrierInProvider();
   1470 
   1471                 // Check if this is a different SIM than the previous one. If so unset the
   1472                 // voice mail number.
   1473                 String imsi = getVmSimImsi();
   1474                 String imsiFromSIM = getSubscriberId();
   1475                 if (imsi != null && imsiFromSIM != null && !imsiFromSIM.equals(imsi)) {
   1476                     storeVoiceMailNumber(null);
   1477                     setVmSimImsi(null);
   1478                 }
   1479 
   1480                 mSimRecordsLoadedRegistrants.notifyRegistrants();
   1481                 updateVoiceMail();
   1482             break;
   1483 
   1484             case EVENT_GET_BASEBAND_VERSION_DONE:
   1485                 ar = (AsyncResult)msg.obj;
   1486 
   1487                 if (ar.exception != null) {
   1488                     break;
   1489                 }
   1490 
   1491                 if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "Baseband version: " + ar.result);
   1492                 TelephonyManager.from(mContext).setBasebandVersionForPhone(getPhoneId(),
   1493                         (String)ar.result);
   1494             break;
   1495 
   1496             case EVENT_GET_IMEI_DONE:
   1497                 ar = (AsyncResult)msg.obj;
   1498 
   1499                 if (ar.exception != null) {
   1500                     break;
   1501                 }
   1502 
   1503                 mImei = (String)ar.result;
   1504             break;
   1505 
   1506             case EVENT_GET_IMEISV_DONE:
   1507                 ar = (AsyncResult)msg.obj;
   1508 
   1509                 if (ar.exception != null) {
   1510                     break;
   1511                 }
   1512 
   1513                 mImeiSv = (String)ar.result;
   1514             break;
   1515 
   1516             case EVENT_USSD:
   1517                 ar = (AsyncResult)msg.obj;
   1518 
   1519                 String[] ussdResult = (String[]) ar.result;
   1520 
   1521                 if (ussdResult.length > 1) {
   1522                     try {
   1523                         onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]);
   1524                     } catch (NumberFormatException e) {
   1525                         Rlog.w(LOG_TAG, "error parsing USSD");
   1526                     }
   1527                 }
   1528             break;
   1529 
   1530             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: {
   1531                 // Some MMI requests (eg USSD) are not completed
   1532                 // within the course of a CommandsInterface request
   1533                 // If the radio shuts off or resets while one of these
   1534                 // is pending, we need to clean up.
   1535 
   1536                 for (int i = mPendingMMIs.size() - 1; i >= 0; i--) {
   1537                     if (mPendingMMIs.get(i).isPendingUSSD()) {
   1538                         mPendingMMIs.get(i).onUssdFinishedError();
   1539                     }
   1540                 }
   1541                 ImsPhone imsPhone = mImsPhone;
   1542                 if (imsPhone != null) {
   1543                     imsPhone.getServiceState().setStateOff();
   1544                 }
   1545                 mRadioOffOrNotAvailableRegistrants.notifyRegistrants();
   1546                 break;
   1547             }
   1548 
   1549             case EVENT_SSN:
   1550                 ar = (AsyncResult)msg.obj;
   1551                 SuppServiceNotification not = (SuppServiceNotification) ar.result;
   1552                 mSsnRegistrants.notifyRegistrants(ar);
   1553             break;
   1554 
   1555             case EVENT_SET_CALL_FORWARD_DONE:
   1556                 ar = (AsyncResult)msg.obj;
   1557                 IccRecords r = mIccRecords.get();
   1558                 Cfu cfu = (Cfu) ar.userObj;
   1559                 if (ar.exception == null && r != null) {
   1560                     r.setVoiceCallForwardingFlag(1, msg.arg1 == 1, cfu.mSetCfNumber);
   1561                 }
   1562                 if (cfu.mOnComplete != null) {
   1563                     AsyncResult.forMessage(cfu.mOnComplete, ar.result, ar.exception);
   1564                     cfu.mOnComplete.sendToTarget();
   1565                 }
   1566                 break;
   1567 
   1568             case EVENT_SET_VM_NUMBER_DONE:
   1569                 ar = (AsyncResult)msg.obj;
   1570                 if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
   1571                     storeVoiceMailNumber(mVmNumber);
   1572                     ar.exception = null;
   1573                 }
   1574                 onComplete = (Message) ar.userObj;
   1575                 if (onComplete != null) {
   1576                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
   1577                     onComplete.sendToTarget();
   1578                 }
   1579                 break;
   1580 
   1581 
   1582             case EVENT_GET_CALL_FORWARD_DONE:
   1583                 ar = (AsyncResult)msg.obj;
   1584                 if (ar.exception == null) {
   1585                     handleCfuQueryResult((CallForwardInfo[])ar.result);
   1586                 }
   1587                 onComplete = (Message) ar.userObj;
   1588                 if (onComplete != null) {
   1589                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
   1590                     onComplete.sendToTarget();
   1591                 }
   1592                 break;
   1593 
   1594             case EVENT_SET_NETWORK_AUTOMATIC:
   1595                 // Automatic network selection from EF_CSP SIM record
   1596                 ar = (AsyncResult) msg.obj;
   1597                 if (mSST.mSS.getIsManualSelection()) {
   1598                     setNetworkSelectionModeAutomatic((Message) ar.result);
   1599                     Rlog.d(LOG_TAG, "SET_NETWORK_SELECTION_AUTOMATIC: set to automatic");
   1600                 } else {
   1601                     // prevent duplicate request which will push current PLMN to low priority
   1602                     Rlog.d(LOG_TAG, "SET_NETWORK_SELECTION_AUTOMATIC: already automatic, ignore");
   1603                 }
   1604                 break;
   1605 
   1606             case EVENT_ICC_RECORD_EVENTS:
   1607                 ar = (AsyncResult)msg.obj;
   1608                 processIccRecordEvents((Integer)ar.result);
   1609                 break;
   1610 
   1611             case EVENT_SET_CLIR_COMPLETE:
   1612                 ar = (AsyncResult)msg.obj;
   1613                 if (ar.exception == null) {
   1614                     saveClirSetting(msg.arg1);
   1615                 }
   1616                 onComplete = (Message) ar.userObj;
   1617                 if (onComplete != null) {
   1618                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
   1619                     onComplete.sendToTarget();
   1620                 }
   1621                 break;
   1622 
   1623             case EVENT_SS:
   1624                 ar = (AsyncResult)msg.obj;
   1625                 Rlog.d(LOG_TAG, "Event EVENT_SS received");
   1626                 // SS data is already being handled through MMI codes.
   1627                 // So, this result if processed as MMI response would help
   1628                 // in re-using the existing functionality.
   1629                 GsmMmiCode mmi = new GsmMmiCode(this, mUiccApplication.get());
   1630                 mmi.processSsData(ar);
   1631                 break;
   1632 
   1633              default:
   1634                  super.handleMessage(msg);
   1635         }
   1636     }
   1637 
   1638     protected UiccCardApplication getUiccCardApplication() {
   1639             return  mUiccController.getUiccCardApplication(mPhoneId,
   1640                     UiccController.APP_FAM_3GPP);
   1641     }
   1642 
   1643     @Override
   1644     protected void onUpdateIccAvailability() {
   1645         if (mUiccController == null ) {
   1646             return;
   1647         }
   1648 
   1649         UiccCardApplication newUiccApplication =
   1650                 mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_IMS);
   1651         IsimUiccRecords newIsimUiccRecords = null;
   1652 
   1653         if (newUiccApplication != null) {
   1654             newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
   1655             if (LOCAL_DEBUG) log("New ISIM application found");
   1656         }
   1657         mIsimUiccRecords = newIsimUiccRecords;
   1658 
   1659         newUiccApplication = getUiccCardApplication();
   1660 
   1661         UiccCardApplication app = mUiccApplication.get();
   1662         if (app != newUiccApplication) {
   1663             if (app != null) {
   1664                 if (LOCAL_DEBUG) log("Removing stale icc objects.");
   1665                 if (mIccRecords.get() != null) {
   1666                     unregisterForSimRecordEvents();
   1667                     mSimPhoneBookIntManager.updateIccRecords(null);
   1668                 }
   1669                 mIccRecords.set(null);
   1670                 mUiccApplication.set(null);
   1671             }
   1672             if (newUiccApplication != null) {
   1673                 if (LOCAL_DEBUG) log("New Uicc application found");
   1674                 mUiccApplication.set(newUiccApplication);
   1675                 mIccRecords.set(newUiccApplication.getIccRecords());
   1676                 registerForSimRecordEvents();
   1677                 mSimPhoneBookIntManager.updateIccRecords(mIccRecords.get());
   1678             }
   1679         }
   1680     }
   1681 
   1682     private void processIccRecordEvents(int eventCode) {
   1683         switch (eventCode) {
   1684             case IccRecords.EVENT_CFI:
   1685                 notifyCallForwardingIndicator();
   1686                 break;
   1687         }
   1688     }
   1689 
   1690     /**
   1691      * Sets the "current" field in the telephony provider according to the SIM's operator
   1692      *
   1693      * @return true for success; false otherwise.
   1694      */
   1695     public boolean updateCurrentCarrierInProvider() {
   1696         long currentDds = SubscriptionManager.getDefaultDataSubId();
   1697         String operatorNumeric = getOperatorNumeric();
   1698 
   1699         log("updateCurrentCarrierInProvider: mSubId = " + getSubId()
   1700                 + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
   1701 
   1702         if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
   1703             try {
   1704                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
   1705                 ContentValues map = new ContentValues();
   1706                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
   1707                 mContext.getContentResolver().insert(uri, map);
   1708                 return true;
   1709             } catch (SQLException e) {
   1710                 Rlog.e(LOG_TAG, "Can't store current operator", e);
   1711             }
   1712         }
   1713         return false;
   1714     }
   1715 
   1716     /**
   1717      * Saves CLIR setting so that we can re-apply it as necessary
   1718      * (in case the RIL resets it across reboots).
   1719      */
   1720     public void saveClirSetting(int commandInterfaceCLIRMode) {
   1721         // open the shared preferences editor, and write the value.
   1722         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1723         SharedPreferences.Editor editor = sp.edit();
   1724         editor.putInt(CLIR_KEY + getPhoneId(), commandInterfaceCLIRMode);
   1725 
   1726         // commit and log the result.
   1727         if (! editor.commit()) {
   1728             Rlog.e(LOG_TAG, "failed to commit CLIR preference");
   1729         }
   1730     }
   1731 
   1732     private void handleCfuQueryResult(CallForwardInfo[] infos) {
   1733         IccRecords r = mIccRecords.get();
   1734         if (r != null) {
   1735             if (infos == null || infos.length == 0) {
   1736                 // Assume the default is not active
   1737                 // Set unconditional CFF in SIM to false
   1738                 r.setVoiceCallForwardingFlag(1, false, null);
   1739             } else {
   1740                 for (int i = 0, s = infos.length; i < s; i++) {
   1741                     if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
   1742                         r.setVoiceCallForwardingFlag(1, (infos[i].status == 1),
   1743                             infos[i].number);
   1744                         // should only have the one
   1745                         break;
   1746                     }
   1747                 }
   1748             }
   1749         }
   1750     }
   1751 
   1752     /**
   1753      * Retrieves the PhoneSubInfo of the GSMPhone
   1754      */
   1755     @Override
   1756     public PhoneSubInfo getPhoneSubInfo(){
   1757         return mSubInfo;
   1758     }
   1759 
   1760     /**
   1761      * Retrieves the IccPhoneBookInterfaceManager of the GSMPhone
   1762      */
   1763     @Override
   1764     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
   1765         return mSimPhoneBookIntManager;
   1766     }
   1767 
   1768     /**
   1769      * Activate or deactivate cell broadcast SMS.
   1770      *
   1771      * @param activate 0 = activate, 1 = deactivate
   1772      * @param response Callback message is empty on completion
   1773      */
   1774     @Override
   1775     public void activateCellBroadcastSms(int activate, Message response) {
   1776         Rlog.e(LOG_TAG, "[GSMPhone] activateCellBroadcastSms() is obsolete; use SmsManager");
   1777         response.sendToTarget();
   1778     }
   1779 
   1780     /**
   1781      * Query the current configuration of cdma cell broadcast SMS.
   1782      *
   1783      * @param response Callback message is empty on completion
   1784      */
   1785     @Override
   1786     public void getCellBroadcastSmsConfig(Message response) {
   1787         Rlog.e(LOG_TAG, "[GSMPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager");
   1788         response.sendToTarget();
   1789     }
   1790 
   1791     /**
   1792      * Configure cdma cell broadcast SMS.
   1793      *
   1794      * @param response Callback message is empty on completion
   1795      */
   1796     @Override
   1797     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
   1798         Rlog.e(LOG_TAG, "[GSMPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager");
   1799         response.sendToTarget();
   1800     }
   1801 
   1802     @Override
   1803     public boolean isCspPlmnEnabled() {
   1804         IccRecords r = mIccRecords.get();
   1805         return (r != null) ? r.isCspPlmnEnabled() : false;
   1806     }
   1807 
   1808     boolean isManualNetSelAllowed() {
   1809 
   1810         int nwMode = Phone.PREFERRED_NT_MODE;
   1811         int subId = getSubId();
   1812 
   1813         nwMode = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
   1814                     android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, nwMode);
   1815 
   1816         Rlog.d(LOG_TAG, "isManualNetSelAllowed in mode = " + nwMode);
   1817         /*
   1818          *  For multimode targets in global mode manual network
   1819          *  selection is disallowed
   1820          */
   1821         if (isManualSelProhibitedInGlobalMode()
   1822                 && ((nwMode == Phone.NT_MODE_LTE_CDMA_EVDO_GSM_WCDMA)
   1823                         || (nwMode == Phone.NT_MODE_GLOBAL)) ){
   1824             Rlog.d(LOG_TAG, "Manual selection not supported in mode = " + nwMode);
   1825             return false;
   1826         } else {
   1827             Rlog.d(LOG_TAG, "Manual selection is supported in mode = " + nwMode);
   1828         }
   1829 
   1830         /*
   1831          *  Single mode phone with - GSM network modes/global mode
   1832          *  LTE only for 3GPP
   1833          *  LTE centric + 3GPP Legacy
   1834          *  Note: the actual enabling/disabling manual selection for these
   1835          *  cases will be controlled by csp
   1836          */
   1837         return true;
   1838     }
   1839 
   1840     private boolean isManualSelProhibitedInGlobalMode() {
   1841         boolean isProhibited = false;
   1842         final String configString = getContext().getResources().getString(com.android.internal.
   1843                                             R.string.prohibit_manual_network_selection_in_gobal_mode);
   1844 
   1845         if (!TextUtils.isEmpty(configString)) {
   1846             String[] configArray = configString.split(";");
   1847 
   1848             if (configArray != null &&
   1849                     ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true")) ||
   1850                         (configArray.length == 2 && !TextUtils.isEmpty(configArray[1]) &&
   1851                             configArray[0].equalsIgnoreCase("true") &&
   1852                             configArray[1].equalsIgnoreCase(getGroupIdLevel1())))) {
   1853                             isProhibited = true;
   1854             }
   1855         }
   1856         Rlog.d(LOG_TAG, "isManualNetSelAllowedInGlobal in current carrier is " + isProhibited);
   1857         return isProhibited;
   1858     }
   1859 
   1860     private void registerForSimRecordEvents() {
   1861         IccRecords r = mIccRecords.get();
   1862         if (r == null) {
   1863             return;
   1864         }
   1865         r.registerForNetworkSelectionModeAutomatic(
   1866                 this, EVENT_SET_NETWORK_AUTOMATIC, null);
   1867         r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null);
   1868         r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
   1869     }
   1870 
   1871     private void unregisterForSimRecordEvents() {
   1872         IccRecords r = mIccRecords.get();
   1873         if (r == null) {
   1874             return;
   1875         }
   1876         r.unregisterForNetworkSelectionModeAutomatic(this);
   1877         r.unregisterForRecordsEvents(this);
   1878         r.unregisterForRecordsLoaded(this);
   1879     }
   1880 
   1881     @Override
   1882     public void exitEmergencyCallbackMode() {
   1883         if (mImsPhone != null) {
   1884             mImsPhone.exitEmergencyCallbackMode();
   1885         }
   1886     }
   1887 
   1888     @Override
   1889     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1890         pw.println("GSMPhone extends:");
   1891         super.dump(fd, pw, args);
   1892         pw.println(" mCT=" + mCT);
   1893         pw.println(" mSST=" + mSST);
   1894         pw.println(" mPendingMMIs=" + mPendingMMIs);
   1895         pw.println(" mSimPhoneBookIntManager=" + mSimPhoneBookIntManager);
   1896         pw.println(" mSubInfo=" + mSubInfo);
   1897         if (VDBG) pw.println(" mImei=" + mImei);
   1898         if (VDBG) pw.println(" mImeiSv=" + mImeiSv);
   1899         pw.println(" mVmNumber=" + mVmNumber);
   1900     }
   1901 
   1902     @Override
   1903     public boolean setOperatorBrandOverride(String brand) {
   1904         if (mUiccController == null) {
   1905             return false;
   1906         }
   1907 
   1908         UiccCard card = mUiccController.getUiccCard(getPhoneId());
   1909         if (card == null) {
   1910             return false;
   1911         }
   1912 
   1913         boolean status = card.setOperatorBrandOverride(brand);
   1914 
   1915         // Refresh.
   1916         if (status) {
   1917             IccRecords iccRecords = mIccRecords.get();
   1918             if (iccRecords != null) {
   1919                 TelephonyManager.from(mContext).setSimOperatorNameForPhone(
   1920                         getPhoneId(), iccRecords.getServiceProviderName());
   1921             }
   1922             if (mSST != null) {
   1923                 mSST.pollState();
   1924             }
   1925         }
   1926         return status;
   1927     }
   1928 
   1929     /**
   1930      * @return operator numeric.
   1931      */
   1932     public String getOperatorNumeric() {
   1933         String operatorNumeric = null;
   1934         IccRecords r = mIccRecords.get();
   1935         if (r != null) {
   1936             operatorNumeric = r.getOperatorNumeric();
   1937         }
   1938         return operatorNumeric;
   1939     }
   1940 
   1941     public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
   1942         ((DcTracker)mDcTracker)
   1943                 .registerForAllDataDisconnected(h, what, obj);
   1944     }
   1945 
   1946     public void unregisterForAllDataDisconnected(Handler h) {
   1947         ((DcTracker)mDcTracker).unregisterForAllDataDisconnected(h);
   1948     }
   1949 
   1950     public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
   1951         ((DcTracker)mDcTracker)
   1952                 .setInternalDataEnabled(enable, onCompleteMsg);
   1953     }
   1954 
   1955 
   1956     public boolean setInternalDataEnabledFlag(boolean enable) {
   1957         return ((DcTracker)mDcTracker)
   1958                 .setInternalDataEnabledFlag(enable);
   1959     }
   1960 
   1961     public void notifyEcbmTimerReset(Boolean flag) {
   1962         mEcmTimerResetRegistrants.notifyResult(flag);
   1963     }
   1964 
   1965     /**
   1966      * Registration point for Ecm timer reset
   1967      *
   1968      * @param h handler to notify
   1969      * @param what User-defined message code
   1970      * @param obj placed in Message.obj
   1971      */
   1972     @Override
   1973     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
   1974         mEcmTimerResetRegistrants.addUnique(h, what, obj);
   1975     }
   1976 
   1977     @Override
   1978     public void unregisterForEcmTimerReset(Handler h) {
   1979         mEcmTimerResetRegistrants.remove(h);
   1980     }
   1981 
   1982     /**
   1983      * Sets the SIM voice message waiting indicator records.
   1984      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
   1985      * @param countWaiting The number of messages waiting, if known. Use
   1986      *                     -1 to indicate that an unknown number of
   1987      *                      messages are waiting
   1988      */
   1989     @Override
   1990     public void setVoiceMessageWaiting(int line, int countWaiting) {
   1991         IccRecords r = mIccRecords.get();
   1992         if (r != null) {
   1993             r.setVoiceMessageWaiting(line, countWaiting);
   1994         } else {
   1995             log("SIM Records not found, MWI not updated");
   1996         }
   1997     }
   1998 
   1999     protected void log(String s) {
   2000         Rlog.d(LOG_TAG, "[GSMPhone] " + s);
   2001     }
   2002 }
   2003