Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2015 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 android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.IntentFilter;
     23 import android.content.SharedPreferences;
     24 import android.net.LinkProperties;
     25 import android.net.NetworkCapabilities;
     26 import android.net.Uri;
     27 import android.net.wifi.WifiManager;
     28 import android.os.AsyncResult;
     29 import android.os.Build;
     30 import android.os.Bundle;
     31 import android.os.Handler;
     32 import android.os.Looper;
     33 import android.os.Message;
     34 import android.os.Registrant;
     35 import android.os.RegistrantList;
     36 import android.os.SystemProperties;
     37 import android.preference.PreferenceManager;
     38 import android.provider.Settings;
     39 import android.service.carrier.CarrierIdentifier;
     40 import android.telecom.VideoProfile;
     41 import android.telephony.CellIdentityCdma;
     42 import android.telephony.CellInfo;
     43 import android.telephony.CellInfoCdma;
     44 import android.telephony.PhoneStateListener;
     45 import android.telephony.RadioAccessFamily;
     46 import android.telephony.Rlog;
     47 import android.telephony.ServiceState;
     48 import android.telephony.SignalStrength;
     49 import android.telephony.SubscriptionManager;
     50 import android.telephony.VoLteServiceState;
     51 import android.text.TextUtils;
     52 
     53 import com.android.ims.ImsConfig;
     54 import com.android.ims.ImsManager;
     55 import com.android.internal.R;
     56 import com.android.internal.telephony.dataconnection.DcTracker;
     57 import com.android.internal.telephony.test.SimulatedRadioControl;
     58 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
     59 import com.android.internal.telephony.uicc.IccFileHandler;
     60 import com.android.internal.telephony.uicc.IccRecords;
     61 import com.android.internal.telephony.uicc.IsimRecords;
     62 import com.android.internal.telephony.uicc.UiccCard;
     63 import com.android.internal.telephony.uicc.UiccCardApplication;
     64 import com.android.internal.telephony.uicc.UiccController;
     65 import com.android.internal.telephony.uicc.UsimServiceTable;
     66 
     67 import java.io.FileDescriptor;
     68 import java.io.PrintWriter;
     69 import java.util.ArrayList;
     70 import java.util.HashSet;
     71 import java.util.List;
     72 import java.util.Locale;
     73 import java.util.Set;
     74 import java.util.concurrent.atomic.AtomicReference;
     75 
     76 /**
     77  * (<em>Not for SDK use</em>)
     78  * A base implementation for the com.android.internal.telephony.Phone interface.
     79  *
     80  * Note that implementations of Phone.java are expected to be used
     81  * from a single application thread. This should be the same thread that
     82  * originally called PhoneFactory to obtain the interface.
     83  *
     84  *  {@hide}
     85  *
     86  */
     87 
     88 public abstract class Phone extends Handler implements PhoneInternalInterface {
     89     private static final String LOG_TAG = "Phone";
     90 
     91     protected final static Object lockForRadioTechnologyChange = new Object();
     92 
     93     private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
     94         @Override
     95         public void onReceive(Context context, Intent intent) {
     96             Rlog.d(LOG_TAG, "mImsIntentReceiver: action " + intent.getAction());
     97             if (intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
     98                 int extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
     99                         SubscriptionManager.INVALID_PHONE_INDEX);
    100                 Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " + extraPhoneId);
    101                 if (extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
    102                         extraPhoneId != getPhoneId()) {
    103                     return;
    104                 }
    105             }
    106 
    107             synchronized (Phone.lockForRadioTechnologyChange) {
    108                 if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
    109                     mImsServiceReady = true;
    110                     updateImsPhone();
    111                     ImsManager.updateImsServiceConfig(mContext, mPhoneId, false);
    112                 } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
    113                     mImsServiceReady = false;
    114                     updateImsPhone();
    115                 } else if (intent.getAction().equals(ImsConfig.ACTION_IMS_CONFIG_CHANGED)) {
    116                     int item = intent.getIntExtra(ImsConfig.EXTRA_CHANGED_ITEM, -1);
    117                     String value = intent.getStringExtra(ImsConfig.EXTRA_NEW_VALUE);
    118                     ImsManager.onProvisionedValueChanged(context, item, value);
    119                 }
    120             }
    121         }
    122     };
    123 
    124     // Key used to read and write the saved network selection numeric value
    125     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
    126     // Key used to read and write the saved network selection operator name
    127     public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
    128     // Key used to read and write the saved network selection operator short name
    129     public static final String NETWORK_SELECTION_SHORT_KEY = "network_selection_short_key";
    130 
    131 
    132     // Key used to read/write "disable data connection on boot" pref (used for testing)
    133     public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
    134 
    135     /* Event Constants */
    136     protected static final int EVENT_RADIO_AVAILABLE             = 1;
    137     /** Supplementary Service Notification received. */
    138     protected static final int EVENT_SSN                         = 2;
    139     protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
    140     private static final int EVENT_MMI_DONE                      = 4;
    141     protected static final int EVENT_RADIO_ON                    = 5;
    142     protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
    143     protected static final int EVENT_USSD                        = 7;
    144     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
    145     protected static final int EVENT_GET_IMEI_DONE               = 9;
    146     protected static final int EVENT_GET_IMEISV_DONE             = 10;
    147     private static final int EVENT_GET_SIM_STATUS_DONE           = 11;
    148     protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
    149     protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
    150     protected static final int EVENT_CALL_RING                   = 14;
    151     private static final int EVENT_CALL_RING_CONTINUE            = 15;
    152 
    153     // Used to intercept the carrier selection calls so that
    154     // we can save the values.
    155     private static final int EVENT_SET_NETWORK_MANUAL_COMPLETE      = 16;
    156     private static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE   = 17;
    157     protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
    158     protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
    159     protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
    160     // Events for CDMA support
    161     protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
    162     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
    163     protected static final int EVENT_NV_READY                       = 23;
    164     private static final int EVENT_SET_ENHANCED_VP                  = 24;
    165     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
    166     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
    167     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
    168     // other
    169     protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
    170     protected static final int EVENT_ICC_RECORD_EVENTS              = 29;
    171     private static final int EVENT_ICC_CHANGED                      = 30;
    172     // Single Radio Voice Call Continuity
    173     private static final int EVENT_SRVCC_STATE_CHANGED              = 31;
    174     private static final int EVENT_INITIATE_SILENT_REDIAL           = 32;
    175     private static final int EVENT_RADIO_NOT_AVAILABLE              = 33;
    176     private static final int EVENT_UNSOL_OEM_HOOK_RAW               = 34;
    177     protected static final int EVENT_GET_RADIO_CAPABILITY           = 35;
    178     protected static final int EVENT_SS                             = 36;
    179     private static final int EVENT_CONFIG_LCE                       = 37;
    180     private static final int EVENT_CHECK_FOR_NETWORK_AUTOMATIC      = 38;
    181     protected static final int EVENT_VOICE_RADIO_TECH_CHANGED       = 39;
    182     protected static final int EVENT_REQUEST_VOICE_RADIO_TECH_DONE  = 40;
    183     protected static final int EVENT_RIL_CONNECTED                  = 41;
    184     protected static final int EVENT_UPDATE_PHONE_OBJECT            = 42;
    185     protected static final int EVENT_CARRIER_CONFIG_CHANGED         = 43;
    186     // Carrier's CDMA prefer mode setting
    187     protected static final int EVENT_SET_ROAMING_PREFERENCE_DONE    = 44;
    188 
    189     protected static final int EVENT_LAST                       = EVENT_SET_ROAMING_PREFERENCE_DONE;
    190 
    191     // For shared prefs.
    192     private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
    193     private static final String GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_non_roaming_list_";
    194     private static final String CDMA_ROAMING_LIST_OVERRIDE_PREFIX = "cdma_roaming_list_";
    195     private static final String CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX = "cdma_non_roaming_list_";
    196 
    197     // Key used to read/write current CLIR setting
    198     public static final String CLIR_KEY = "clir_key";
    199 
    200     // Key used for storing voice mail count
    201     private static final String VM_COUNT = "vm_count_key";
    202     // Key used to read/write the ID for storing the voice mail
    203     private static final String VM_ID = "vm_id_key";
    204 
    205     // Key used for storing call forwarding status
    206     public static final String CF_STATUS = "cf_status_key";
    207     // Key used to read/write the ID for storing the call forwarding status
    208     public static final String CF_ID = "cf_id_key";
    209 
    210     // Key used to read/write "disable DNS server check" pref (used for testing)
    211     private static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
    212 
    213     /**
    214      * Small container class used to hold information relevant to
    215      * the carrier selection process. operatorNumeric can be ""
    216      * if we are looking for automatic selection. operatorAlphaLong is the
    217      * corresponding operator name.
    218      */
    219     private static class NetworkSelectMessage {
    220         public Message message;
    221         public String operatorNumeric;
    222         public String operatorAlphaLong;
    223         public String operatorAlphaShort;
    224     }
    225 
    226     /* Instance Variables */
    227     public CommandsInterface mCi;
    228     protected int mVmCount = 0;
    229     private boolean mDnsCheckDisabled;
    230     public DcTracker mDcTracker;
    231     private boolean mDoesRilSendMultipleCallRing;
    232     private int mCallRingContinueToken;
    233     private int mCallRingDelay;
    234     private boolean mIsVoiceCapable = true;
    235     /* Used for communicate between configured CarrierSignalling receivers */
    236     private CarrierSignalAgent mCarrierSignalAgent;
    237 
    238     // Variable to cache the video capability. When RAT changes, we lose this info and are unable
    239     // to recover from the state. We cache it and notify listeners when they register.
    240     protected boolean mIsVideoCapable = false;
    241     protected UiccController mUiccController = null;
    242     protected final AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
    243     public SmsStorageMonitor mSmsStorageMonitor;
    244     public SmsUsageMonitor mSmsUsageMonitor;
    245     protected AtomicReference<UiccCardApplication> mUiccApplication =
    246             new AtomicReference<UiccCardApplication>();
    247 
    248     private TelephonyTester mTelephonyTester;
    249     private String mName;
    250     private final String mActionDetached;
    251     private final String mActionAttached;
    252 
    253     protected int mPhoneId;
    254 
    255     private boolean mImsServiceReady = false;
    256     protected Phone mImsPhone = null;
    257 
    258     private final AtomicReference<RadioCapability> mRadioCapability =
    259             new AtomicReference<RadioCapability>();
    260 
    261     private static final int DEFAULT_REPORT_INTERVAL_MS = 200;
    262     private static final boolean LCE_PULL_MODE = true;
    263     private int mLceStatus = RILConstants.LCE_NOT_AVAILABLE;
    264     protected TelephonyComponentFactory mTelephonyComponentFactory;
    265 
    266     //IMS
    267     public static final String CS_FALLBACK = "cs_fallback";
    268     public static final String EXTRA_KEY_ALERT_TITLE = "alertTitle";
    269     public static final String EXTRA_KEY_ALERT_MESSAGE = "alertMessage";
    270     public static final String EXTRA_KEY_ALERT_SHOW = "alertShow";
    271     public static final String EXTRA_KEY_NOTIFICATION_MESSAGE = "notificationMessage";
    272 
    273     private final RegistrantList mPreciseCallStateRegistrants
    274             = new RegistrantList();
    275 
    276     private final RegistrantList mHandoverRegistrants
    277             = new RegistrantList();
    278 
    279     private final RegistrantList mNewRingingConnectionRegistrants
    280             = new RegistrantList();
    281 
    282     private final RegistrantList mIncomingRingRegistrants
    283             = new RegistrantList();
    284 
    285     protected final RegistrantList mDisconnectRegistrants
    286             = new RegistrantList();
    287 
    288     private final RegistrantList mServiceStateRegistrants
    289             = new RegistrantList();
    290 
    291     protected final RegistrantList mMmiCompleteRegistrants
    292             = new RegistrantList();
    293 
    294     protected final RegistrantList mMmiRegistrants
    295             = new RegistrantList();
    296 
    297     protected final RegistrantList mUnknownConnectionRegistrants
    298             = new RegistrantList();
    299 
    300     protected final RegistrantList mSuppServiceFailedRegistrants
    301             = new RegistrantList();
    302 
    303     protected final RegistrantList mRadioOffOrNotAvailableRegistrants
    304             = new RegistrantList();
    305 
    306     protected final RegistrantList mSimRecordsLoadedRegistrants
    307             = new RegistrantList();
    308 
    309     private final RegistrantList mVideoCapabilityChangedRegistrants
    310             = new RegistrantList();
    311 
    312     protected final RegistrantList mEmergencyCallToggledRegistrants
    313             = new RegistrantList();
    314 
    315     protected Registrant mPostDialHandler;
    316 
    317     private Looper mLooper; /* to insure registrants are in correct thread*/
    318 
    319     protected final Context mContext;
    320 
    321     /**
    322      * PhoneNotifier is an abstraction for all system-wide
    323      * state change notification. DefaultPhoneNotifier is
    324      * used here unless running we're inside a unit test.
    325      */
    326     protected PhoneNotifier mNotifier;
    327 
    328     protected SimulatedRadioControl mSimulatedRadioControl;
    329 
    330     private boolean mUnitTestMode;
    331 
    332     public IccRecords getIccRecords() {
    333         return mIccRecords.get();
    334     }
    335 
    336     /**
    337      * Returns a string identifier for this phone interface for parties
    338      *  outside the phone app process.
    339      *  @return The string name.
    340      */
    341     public String getPhoneName() {
    342         return mName;
    343     }
    344 
    345     protected void setPhoneName(String name) {
    346         mName = name;
    347     }
    348 
    349     /**
    350      * Retrieves Nai for phones. Returns null if Nai is not set.
    351      */
    352     public String getNai(){
    353          return null;
    354     }
    355 
    356     /**
    357      * Return the ActionDetached string. When this action is received by components
    358      * they are to simulate detaching from the network.
    359      *
    360      * @return com.android.internal.telephony.{mName}.action_detached
    361      *          {mName} is GSM, CDMA ...
    362      */
    363     public String getActionDetached() {
    364         return mActionDetached;
    365     }
    366 
    367     /**
    368      * Return the ActionAttached string. When this action is received by components
    369      * they are to simulate attaching to the network.
    370      *
    371      * @return com.android.internal.telephony.{mName}.action_detached
    372      *          {mName} is GSM, CDMA ...
    373      */
    374     public String getActionAttached() {
    375         return mActionAttached;
    376     }
    377 
    378     /**
    379      * Set a system property, unless we're in unit test mode
    380      */
    381     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
    382     public void setSystemProperty(String property, String value) {
    383         if(getUnitTestMode()) {
    384             return;
    385         }
    386         SystemProperties.set(property, value);
    387     }
    388 
    389     /**
    390      * Set a system property, unless we're in unit test mode
    391      */
    392     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
    393     public String getSystemProperty(String property, String defValue) {
    394         if(getUnitTestMode()) {
    395             return null;
    396         }
    397         return SystemProperties.get(property, defValue);
    398     }
    399 
    400     /**
    401      * Constructs a Phone in normal (non-unit test) mode.
    402      *
    403      * @param notifier An instance of DefaultPhoneNotifier,
    404      * @param context Context object from hosting application
    405      * unless unit testing.
    406      * @param ci is CommandsInterface
    407      * @param unitTestMode when true, prevents notifications
    408      * of state change events
    409      */
    410     protected Phone(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
    411                     boolean unitTestMode) {
    412         this(name, notifier, context, ci, unitTestMode, SubscriptionManager.DEFAULT_PHONE_INDEX,
    413                 TelephonyComponentFactory.getInstance());
    414     }
    415 
    416     /**
    417      * Constructs a Phone in normal (non-unit test) mode.
    418      *
    419      * @param notifier An instance of DefaultPhoneNotifier,
    420      * @param context Context object from hosting application
    421      * unless unit testing.
    422      * @param ci is CommandsInterface
    423      * @param unitTestMode when true, prevents notifications
    424      * of state change events
    425      * @param phoneId the phone-id of this phone.
    426      */
    427     protected Phone(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
    428                     boolean unitTestMode, int phoneId,
    429                     TelephonyComponentFactory telephonyComponentFactory) {
    430         mPhoneId = phoneId;
    431         mName = name;
    432         mNotifier = notifier;
    433         mContext = context;
    434         mLooper = Looper.myLooper();
    435         mCi = ci;
    436         mCarrierSignalAgent = new CarrierSignalAgent(this);
    437         mActionDetached = this.getClass().getPackage().getName() + ".action_detached";
    438         mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
    439 
    440         if (Build.IS_DEBUGGABLE) {
    441             mTelephonyTester = new TelephonyTester(this);
    442         }
    443 
    444         setUnitTestMode(unitTestMode);
    445 
    446         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
    447         mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
    448         mCi.setOnCallRing(this, EVENT_CALL_RING, null);
    449 
    450         /* "Voice capable" means that this device supports circuit-switched
    451         * (i.e. voice) phone calls over the telephony network, and is allowed
    452         * to display the in-call UI while a cellular voice call is active.
    453         * This will be false on "data only" devices which can't make voice
    454         * calls and don't support any in-call UI.
    455         */
    456         mIsVoiceCapable = mContext.getResources().getBoolean(
    457                 com.android.internal.R.bool.config_voice_capable);
    458 
    459         /**
    460          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
    461          *  to be generated locally. Ideally all ring tones should be loops
    462          * and this wouldn't be necessary. But to minimize changes to upper
    463          * layers it is requested that it be generated by lower layers.
    464          *
    465          * By default old phones won't have the property set but do generate
    466          * the RIL_UNSOL_CALL_RING so the default if there is no property is
    467          * true.
    468          */
    469         mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
    470                 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
    471         Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
    472 
    473         mCallRingDelay = SystemProperties.getInt(
    474                 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
    475         Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
    476 
    477         if (getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
    478             return;
    479         }
    480 
    481         // The locale from the "ro.carrier" system property or R.array.carrier_properties.
    482         // This will be overwritten by the Locale from the SIM language settings (EF-PL, EF-LI)
    483         // if applicable.
    484         final Locale carrierLocale = getLocaleFromCarrierProperties(mContext);
    485         if (carrierLocale != null && !TextUtils.isEmpty(carrierLocale.getCountry())) {
    486             final String country = carrierLocale.getCountry();
    487             try {
    488                 Settings.Global.getInt(mContext.getContentResolver(),
    489                         Settings.Global.WIFI_COUNTRY_CODE);
    490             } catch (Settings.SettingNotFoundException e) {
    491                 // note this is not persisting
    492                 WifiManager wM = (WifiManager)
    493                         mContext.getSystemService(Context.WIFI_SERVICE);
    494                 wM.setCountryCode(country, false);
    495             }
    496         }
    497 
    498         // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
    499         mTelephonyComponentFactory = telephonyComponentFactory;
    500         mSmsStorageMonitor = mTelephonyComponentFactory.makeSmsStorageMonitor(this);
    501         mSmsUsageMonitor = mTelephonyComponentFactory.makeSmsUsageMonitor(context);
    502         mUiccController = UiccController.getInstance();
    503         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
    504         if (getPhoneType() != PhoneConstants.PHONE_TYPE_SIP) {
    505             mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
    506         }
    507         mCi.setOnUnsolOemHookRaw(this, EVENT_UNSOL_OEM_HOOK_RAW, null);
    508         mCi.startLceService(DEFAULT_REPORT_INTERVAL_MS, LCE_PULL_MODE,
    509                 obtainMessage(EVENT_CONFIG_LCE));
    510     }
    511 
    512     /**
    513      * Start listening for IMS service UP/DOWN events.
    514      */
    515     public void startMonitoringImsService() {
    516         if (getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
    517             return;
    518         }
    519 
    520         synchronized(Phone.lockForRadioTechnologyChange) {
    521             IntentFilter filter = new IntentFilter();
    522             filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
    523             filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
    524             filter.addAction(ImsConfig.ACTION_IMS_CONFIG_CHANGED);
    525             mContext.registerReceiver(mImsIntentReceiver, filter);
    526 
    527             // Monitor IMS service - but first poll to see if already up (could miss
    528             // intent)
    529             ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId());
    530             if (imsManager != null && imsManager.isServiceAvailable()) {
    531                 mImsServiceReady = true;
    532                 updateImsPhone();
    533                 ImsManager.updateImsServiceConfig(mContext, mPhoneId, false);
    534             }
    535         }
    536     }
    537 
    538     /**
    539      * When overridden the derived class needs to call
    540      * super.handleMessage(msg) so this method has a
    541      * a chance to process the message.
    542      *
    543      * @param msg
    544      */
    545     @Override
    546     public void handleMessage(Message msg) {
    547         AsyncResult ar;
    548 
    549         // messages to be handled whether or not the phone is being destroyed
    550         // should only include messages which are being re-directed and do not use
    551         // resources of the phone being destroyed
    552         switch (msg.what) {
    553             // handle the select network completion callbacks.
    554             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
    555             case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
    556                 handleSetSelectNetwork((AsyncResult) msg.obj);
    557                 return;
    558         }
    559 
    560         switch(msg.what) {
    561             case EVENT_CALL_RING:
    562                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
    563                 ar = (AsyncResult)msg.obj;
    564                 if (ar.exception == null) {
    565                     PhoneConstants.State state = getState();
    566                     if ((!mDoesRilSendMultipleCallRing)
    567                             && ((state == PhoneConstants.State.RINGING) ||
    568                                     (state == PhoneConstants.State.IDLE))) {
    569                         mCallRingContinueToken += 1;
    570                         sendIncomingCallRingNotification(mCallRingContinueToken);
    571                     } else {
    572                         notifyIncomingRing();
    573                     }
    574                 }
    575                 break;
    576 
    577             case EVENT_CALL_RING_CONTINUE:
    578                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received state=" + getState());
    579                 if (getState() == PhoneConstants.State.RINGING) {
    580                     sendIncomingCallRingNotification(msg.arg1);
    581                 }
    582                 break;
    583 
    584             case EVENT_ICC_CHANGED:
    585                 onUpdateIccAvailability();
    586                 break;
    587 
    588             case EVENT_INITIATE_SILENT_REDIAL:
    589                 Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
    590                 ar = (AsyncResult) msg.obj;
    591                 if ((ar.exception == null) && (ar.result != null)) {
    592                     String dialString = (String) ar.result;
    593                     if (TextUtils.isEmpty(dialString)) return;
    594                     try {
    595                         dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, null);
    596                     } catch (CallStateException e) {
    597                         Rlog.e(LOG_TAG, "silent redial failed: " + e);
    598                     }
    599                 }
    600                 break;
    601 
    602             case EVENT_SRVCC_STATE_CHANGED:
    603                 ar = (AsyncResult)msg.obj;
    604                 if (ar.exception == null) {
    605                     handleSrvccStateChanged((int[]) ar.result);
    606                 } else {
    607                     Rlog.e(LOG_TAG, "Srvcc exception: " + ar.exception);
    608                 }
    609                 break;
    610 
    611             case EVENT_UNSOL_OEM_HOOK_RAW:
    612                 ar = (AsyncResult)msg.obj;
    613                 if (ar.exception == null) {
    614                     byte[] data = (byte[])ar.result;
    615                     mNotifier.notifyOemHookRawEventForSubscriber(getSubId(), data);
    616                 } else {
    617                     Rlog.e(LOG_TAG, "OEM hook raw exception: " + ar.exception);
    618                 }
    619                 break;
    620 
    621             case EVENT_CONFIG_LCE:
    622                 ar = (AsyncResult) msg.obj;
    623                 if (ar.exception != null) {
    624                     Rlog.d(LOG_TAG, "config LCE service failed: " + ar.exception);
    625                 } else {
    626                     final ArrayList<Integer> statusInfo = (ArrayList<Integer>)ar.result;
    627                     mLceStatus = statusInfo.get(0);
    628                 }
    629                 break;
    630 
    631             case EVENT_CHECK_FOR_NETWORK_AUTOMATIC: {
    632                 onCheckForNetworkSelectionModeAutomatic(msg);
    633                 break;
    634             }
    635             default:
    636                 throw new RuntimeException("unexpected event not handled");
    637         }
    638     }
    639 
    640     public ArrayList<Connection> getHandoverConnection() {
    641         return null;
    642     }
    643 
    644     public void notifySrvccState(Call.SrvccState state) {
    645     }
    646 
    647     public void registerForSilentRedial(Handler h, int what, Object obj) {
    648     }
    649 
    650     public void unregisterForSilentRedial(Handler h) {
    651     }
    652 
    653     private void handleSrvccStateChanged(int[] ret) {
    654         Rlog.d(LOG_TAG, "handleSrvccStateChanged");
    655 
    656         ArrayList<Connection> conn = null;
    657         Phone imsPhone = mImsPhone;
    658         Call.SrvccState srvccState = Call.SrvccState.NONE;
    659         if (ret != null && ret.length != 0) {
    660             int state = ret[0];
    661             switch(state) {
    662                 case VoLteServiceState.HANDOVER_STARTED:
    663                     srvccState = Call.SrvccState.STARTED;
    664                     if (imsPhone != null) {
    665                         conn = imsPhone.getHandoverConnection();
    666                         migrateFrom(imsPhone);
    667                     } else {
    668                         Rlog.d(LOG_TAG, "HANDOVER_STARTED: mImsPhone null");
    669                     }
    670                     break;
    671                 case VoLteServiceState.HANDOVER_COMPLETED:
    672                     srvccState = Call.SrvccState.COMPLETED;
    673                     if (imsPhone != null) {
    674                         imsPhone.notifySrvccState(srvccState);
    675                     } else {
    676                         Rlog.d(LOG_TAG, "HANDOVER_COMPLETED: mImsPhone null");
    677                     }
    678                     break;
    679                 case VoLteServiceState.HANDOVER_FAILED:
    680                 case VoLteServiceState.HANDOVER_CANCELED:
    681                     srvccState = Call.SrvccState.FAILED;
    682                     break;
    683 
    684                 default:
    685                     //ignore invalid state
    686                     return;
    687             }
    688 
    689             getCallTracker().notifySrvccState(srvccState, conn);
    690 
    691             VoLteServiceState lteState = new VoLteServiceState(state);
    692             notifyVoLteServiceStateChanged(lteState);
    693         }
    694     }
    695 
    696     /**
    697      * Gets the context for the phone, as set at initialization time.
    698      */
    699     public Context getContext() {
    700         return mContext;
    701     }
    702 
    703     // Will be called when icc changed
    704     protected abstract void onUpdateIccAvailability();
    705 
    706     /**
    707      * Disables the DNS check (i.e., allows "0.0.0.0").
    708      * Useful for lab testing environment.
    709      * @param b true disables the check, false enables.
    710      */
    711     public void disableDnsCheck(boolean b) {
    712         mDnsCheckDisabled = b;
    713         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    714         SharedPreferences.Editor editor = sp.edit();
    715         editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
    716         editor.apply();
    717     }
    718 
    719     /**
    720      * Returns true if the DNS check is currently disabled.
    721      */
    722     public boolean isDnsCheckDisabled() {
    723         return mDnsCheckDisabled;
    724     }
    725 
    726     /**
    727      * Register for getting notifications for change in the Call State {@link Call.State}
    728      * This is called PreciseCallState because the call state is more precise than the
    729      * {@link PhoneConstants.State} which can be obtained using the {@link PhoneStateListener}
    730      *
    731      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
    732      * AsyncResult.userData will be set to the obj argument here.
    733      * The <em>h</em> parameter is held only by a weak reference.
    734      */
    735     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
    736         checkCorrectThread(h);
    737 
    738         mPreciseCallStateRegistrants.addUnique(h, what, obj);
    739     }
    740 
    741     /**
    742      * Unregisters for voice call state change notifications.
    743      * Extraneous calls are tolerated silently.
    744      */
    745     public void unregisterForPreciseCallStateChanged(Handler h) {
    746         mPreciseCallStateRegistrants.remove(h);
    747     }
    748 
    749     /**
    750      * Subclasses of Phone probably want to replace this with a
    751      * version scoped to their packages
    752      */
    753     protected void notifyPreciseCallStateChangedP() {
    754         AsyncResult ar = new AsyncResult(null, this, null);
    755         mPreciseCallStateRegistrants.notifyRegistrants(ar);
    756 
    757         mNotifier.notifyPreciseCallState(this);
    758     }
    759 
    760     /**
    761      * Notifies when a Handover happens due to SRVCC or Silent Redial
    762      */
    763     public void registerForHandoverStateChanged(Handler h, int what, Object obj) {
    764         checkCorrectThread(h);
    765         mHandoverRegistrants.addUnique(h, what, obj);
    766     }
    767 
    768     /**
    769      * Unregisters for handover state notifications
    770      */
    771     public void unregisterForHandoverStateChanged(Handler h) {
    772         mHandoverRegistrants.remove(h);
    773     }
    774 
    775     /**
    776      * Subclasses of Phone probably want to replace this with a
    777      * version scoped to their packages
    778      */
    779     public void notifyHandoverStateChanged(Connection cn) {
    780        AsyncResult ar = new AsyncResult(null, cn, null);
    781        mHandoverRegistrants.notifyRegistrants(ar);
    782     }
    783 
    784     protected void setIsInEmergencyCall() {
    785     }
    786 
    787     protected void migrateFrom(Phone from) {
    788         migrate(mHandoverRegistrants, from.mHandoverRegistrants);
    789         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
    790         migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
    791         migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
    792         migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
    793         migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
    794         migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
    795         migrate(mMmiRegistrants, from.mMmiRegistrants);
    796         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
    797         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
    798         if (from.isInEmergencyCall()) {
    799             setIsInEmergencyCall();
    800         }
    801     }
    802 
    803     protected void migrate(RegistrantList to, RegistrantList from) {
    804         from.removeCleared();
    805         for (int i = 0, n = from.size(); i < n; i++) {
    806             Registrant r = (Registrant) from.get(i);
    807             Message msg = r.messageForRegistrant();
    808             // Since CallManager has already registered with both CS and IMS phones,
    809             // the migrate should happen only for those registrants which are not
    810             // registered with CallManager.Hence the below check is needed to add
    811             // only those registrants to the registrant list which are not
    812             // coming from the CallManager.
    813             if (msg != null) {
    814                 if (msg.obj == CallManager.getInstance().getRegistrantIdentifier()) {
    815                     continue;
    816                 } else {
    817                     to.add((Registrant) from.get(i));
    818                 }
    819             } else {
    820                 Rlog.d(LOG_TAG, "msg is null");
    821             }
    822         }
    823     }
    824 
    825     /**
    826      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
    827      * This is likely due to some other entity (eg, SIM card application) initiating a call.
    828      */
    829     public void registerForUnknownConnection(Handler h, int what, Object obj) {
    830         checkCorrectThread(h);
    831 
    832         mUnknownConnectionRegistrants.addUnique(h, what, obj);
    833     }
    834 
    835     /**
    836      * Unregisters for unknown connection notifications.
    837      */
    838     public void unregisterForUnknownConnection(Handler h) {
    839         mUnknownConnectionRegistrants.remove(h);
    840     }
    841 
    842     /**
    843      * Notifies when a new ringing or waiting connection has appeared.<p>
    844      *
    845      *  Messages received from this:
    846      *  Message.obj will be an AsyncResult
    847      *  AsyncResult.userObj = obj
    848      *  AsyncResult.result = a Connection. <p>
    849      *  Please check Connection.isRinging() to make sure the Connection
    850      *  has not dropped since this message was posted.
    851      *  If Connection.isRinging() is true, then
    852      *   Connection.getCall() == Phone.getRingingCall()
    853      */
    854     public void registerForNewRingingConnection(
    855             Handler h, int what, Object obj) {
    856         checkCorrectThread(h);
    857 
    858         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
    859     }
    860 
    861     /**
    862      * Unregisters for new ringing connection notification.
    863      * Extraneous calls are tolerated silently
    864      */
    865     public void unregisterForNewRingingConnection(Handler h) {
    866         mNewRingingConnectionRegistrants.remove(h);
    867     }
    868 
    869     /**
    870      * Notifies when phone's video capabilities changes <p>
    871      *
    872      *  Messages received from this:
    873      *  Message.obj will be an AsyncResult
    874      *  AsyncResult.userObj = obj
    875      *  AsyncResult.result = true if phone supports video calling <p>
    876      */
    877     public void registerForVideoCapabilityChanged(
    878             Handler h, int what, Object obj) {
    879         checkCorrectThread(h);
    880 
    881         mVideoCapabilityChangedRegistrants.addUnique(h, what, obj);
    882 
    883         // Notify any registrants of the cached video capability as soon as they register.
    884         notifyForVideoCapabilityChanged(mIsVideoCapable);
    885     }
    886 
    887     /**
    888      * Unregisters for video capability changed notification.
    889      * Extraneous calls are tolerated silently
    890      */
    891     public void unregisterForVideoCapabilityChanged(Handler h) {
    892         mVideoCapabilityChangedRegistrants.remove(h);
    893     }
    894 
    895     /**
    896      * Register for notifications when a sInCall VoicePrivacy is enabled
    897      *
    898      * @param h Handler that receives the notification message.
    899      * @param what User-defined message code.
    900      * @param obj User object.
    901      */
    902     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
    903         mCi.registerForInCallVoicePrivacyOn(h, what, obj);
    904     }
    905 
    906     /**
    907      * Unegister for notifications when a sInCall VoicePrivacy is enabled
    908      *
    909      * @param h Handler to be removed from the registrant list.
    910      */
    911     public void unregisterForInCallVoicePrivacyOn(Handler h){
    912         mCi.unregisterForInCallVoicePrivacyOn(h);
    913     }
    914 
    915     /**
    916      * Register for notifications when a sInCall VoicePrivacy is disabled
    917      *
    918      * @param h Handler that receives the notification message.
    919      * @param what User-defined message code.
    920      * @param obj User object.
    921      */
    922     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
    923         mCi.registerForInCallVoicePrivacyOff(h, what, obj);
    924     }
    925 
    926     /**
    927      * Unregister for notifications when a sInCall VoicePrivacy is disabled
    928      *
    929      * @param h Handler to be removed from the registrant list.
    930      */
    931     public void unregisterForInCallVoicePrivacyOff(Handler h){
    932         mCi.unregisterForInCallVoicePrivacyOff(h);
    933     }
    934 
    935     /**
    936      * Notifies when an incoming call rings.<p>
    937      *
    938      *  Messages received from this:
    939      *  Message.obj will be an AsyncResult
    940      *  AsyncResult.userObj = obj
    941      *  AsyncResult.result = a Connection. <p>
    942      */
    943     public void registerForIncomingRing(
    944             Handler h, int what, Object obj) {
    945         checkCorrectThread(h);
    946 
    947         mIncomingRingRegistrants.addUnique(h, what, obj);
    948     }
    949 
    950     /**
    951      * Unregisters for ring notification.
    952      * Extraneous calls are tolerated silently
    953      */
    954     public void unregisterForIncomingRing(Handler h) {
    955         mIncomingRingRegistrants.remove(h);
    956     }
    957 
    958     /**
    959      * Notifies when a voice connection has disconnected, either due to local
    960      * or remote hangup or error.
    961      *
    962      *  Messages received from this will have the following members:<p>
    963      *  <ul><li>Message.obj will be an AsyncResult</li>
    964      *  <li>AsyncResult.userObj = obj</li>
    965      *  <li>AsyncResult.result = a Connection object that is
    966      *  no longer connected.</li></ul>
    967      */
    968     public void registerForDisconnect(Handler h, int what, Object obj) {
    969         checkCorrectThread(h);
    970 
    971         mDisconnectRegistrants.addUnique(h, what, obj);
    972     }
    973 
    974     /**
    975      * Unregisters for voice disconnection notification.
    976      * Extraneous calls are tolerated silently
    977      */
    978     public void unregisterForDisconnect(Handler h) {
    979         mDisconnectRegistrants.remove(h);
    980     }
    981 
    982     /**
    983      * Register for notifications when a supplementary service attempt fails.
    984      * Message.obj will contain an AsyncResult.
    985      *
    986      * @param h Handler that receives the notification message.
    987      * @param what User-defined message code.
    988      * @param obj User object.
    989      */
    990     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
    991         checkCorrectThread(h);
    992 
    993         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
    994     }
    995 
    996     /**
    997      * Unregister for notifications when a supplementary service attempt fails.
    998      * Extraneous calls are tolerated silently
    999      *
   1000      * @param h Handler to be removed from the registrant list.
   1001      */
   1002     public void unregisterForSuppServiceFailed(Handler h) {
   1003         mSuppServiceFailedRegistrants.remove(h);
   1004     }
   1005 
   1006     /**
   1007      * Register for notifications of initiation of a new MMI code request.
   1008      * MMI codes for GSM are discussed in 3GPP TS 22.030.<p>
   1009      *
   1010      * Example: If Phone.dial is called with "*#31#", then the app will
   1011      * be notified here.<p>
   1012      *
   1013      * The returned <code>Message.obj</code> will contain an AsyncResult.
   1014      *
   1015      * <code>obj.result</code> will be an "MmiCode" object.
   1016      */
   1017     public void registerForMmiInitiate(Handler h, int what, Object obj) {
   1018         checkCorrectThread(h);
   1019 
   1020         mMmiRegistrants.addUnique(h, what, obj);
   1021     }
   1022 
   1023     /**
   1024      * Unregisters for new MMI initiate notification.
   1025      * Extraneous calls are tolerated silently
   1026      */
   1027     public void unregisterForMmiInitiate(Handler h) {
   1028         mMmiRegistrants.remove(h);
   1029     }
   1030 
   1031     /**
   1032      * Register for notifications that an MMI request has completed
   1033      * its network activity and is in its final state. This may mean a state
   1034      * of COMPLETE, FAILED, or CANCELLED.
   1035      *
   1036      * <code>Message.obj</code> will contain an AsyncResult.
   1037      * <code>obj.result</code> will be an "MmiCode" object
   1038      */
   1039     public void registerForMmiComplete(Handler h, int what, Object obj) {
   1040         checkCorrectThread(h);
   1041 
   1042         mMmiCompleteRegistrants.addUnique(h, what, obj);
   1043     }
   1044 
   1045     /**
   1046      * Unregisters for MMI complete notification.
   1047      * Extraneous calls are tolerated silently
   1048      */
   1049     public void unregisterForMmiComplete(Handler h) {
   1050         checkCorrectThread(h);
   1051 
   1052         mMmiCompleteRegistrants.remove(h);
   1053     }
   1054 
   1055     /**
   1056      * Registration point for Sim records loaded
   1057      * @param h handler to notify
   1058      * @param what what code of message when delivered
   1059      * @param obj placed in Message.obj
   1060      */
   1061     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
   1062     }
   1063 
   1064     /**
   1065      * Unregister for notifications for Sim records loaded
   1066      * @param h Handler to be removed from the registrant list.
   1067      */
   1068     public void unregisterForSimRecordsLoaded(Handler h) {
   1069     }
   1070 
   1071     /**
   1072      * Register for TTY mode change notifications from the network.
   1073      * Message.obj will contain an AsyncResult.
   1074      * AsyncResult.result will be an Integer containing new mode.
   1075      *
   1076      * @param h Handler that receives the notification message.
   1077      * @param what User-defined message code.
   1078      * @param obj User object.
   1079      */
   1080     public void registerForTtyModeReceived(Handler h, int what, Object obj) {
   1081     }
   1082 
   1083     /**
   1084      * Unregisters for TTY mode change notifications.
   1085      * Extraneous calls are tolerated silently
   1086      *
   1087      * @param h Handler to be removed from the registrant list.
   1088      */
   1089     public void unregisterForTtyModeReceived(Handler h) {
   1090     }
   1091 
   1092     /**
   1093      * Switches network selection mode to "automatic", re-scanning and
   1094      * re-selecting a network if appropriate.
   1095      *
   1096      * @param response The message to dispatch when the network selection
   1097      * is complete.
   1098      *
   1099      * @see #selectNetworkManually(OperatorInfo, boolean, android.os.Message)
   1100      */
   1101     public void setNetworkSelectionModeAutomatic(Message response) {
   1102         Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic, querying current mode");
   1103         // we don't want to do this unecesarily - it acutally causes
   1104         // the radio to repeate network selection and is costly
   1105         // first check if we're already in automatic mode
   1106         Message msg = obtainMessage(EVENT_CHECK_FOR_NETWORK_AUTOMATIC);
   1107         msg.obj = response;
   1108         mCi.getNetworkSelectionMode(msg);
   1109     }
   1110 
   1111     private void onCheckForNetworkSelectionModeAutomatic(Message fromRil) {
   1112         AsyncResult ar = (AsyncResult)fromRil.obj;
   1113         Message response = (Message)ar.userObj;
   1114         boolean doAutomatic = true;
   1115         if (ar.exception == null && ar.result != null) {
   1116             try {
   1117                 int[] modes = (int[])ar.result;
   1118                 if (modes[0] == 0) {
   1119                     // already confirmed to be in automatic mode - don't resend
   1120                     doAutomatic = false;
   1121                 }
   1122             } catch (Exception e) {
   1123                 // send the setting on error
   1124             }
   1125         }
   1126 
   1127         // wrap the response message in our own message along with
   1128         // an empty string (to indicate automatic selection) for the
   1129         // operator's id.
   1130         NetworkSelectMessage nsm = new NetworkSelectMessage();
   1131         nsm.message = response;
   1132         nsm.operatorNumeric = "";
   1133         nsm.operatorAlphaLong = "";
   1134         nsm.operatorAlphaShort = "";
   1135 
   1136         if (doAutomatic) {
   1137             Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
   1138             mCi.setNetworkSelectionModeAutomatic(msg);
   1139         } else {
   1140             Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - already auto, ignoring");
   1141             ar.userObj = nsm;
   1142             handleSetSelectNetwork(ar);
   1143         }
   1144 
   1145         updateSavedNetworkOperator(nsm);
   1146     }
   1147 
   1148     /**
   1149      * Query the radio for the current network selection mode.
   1150      *
   1151      * Return values:
   1152      *     0 - automatic.
   1153      *     1 - manual.
   1154      */
   1155     public void getNetworkSelectionMode(Message message) {
   1156         mCi.getNetworkSelectionMode(message);
   1157     }
   1158 
   1159     /**
   1160      * Manually selects a network. <code>response</code> is
   1161      * dispatched when this is complete.  <code>response.obj</code> will be
   1162      * an AsyncResult, and <code>response.obj.exception</code> will be non-null
   1163      * on failure.
   1164      *
   1165      * @see #setNetworkSelectionModeAutomatic(Message)
   1166      */
   1167     public void selectNetworkManually(OperatorInfo network, boolean persistSelection,
   1168             Message response) {
   1169         // wrap the response message in our own message along with
   1170         // the operator's id.
   1171         NetworkSelectMessage nsm = new NetworkSelectMessage();
   1172         nsm.message = response;
   1173         nsm.operatorNumeric = network.getOperatorNumeric();
   1174         nsm.operatorAlphaLong = network.getOperatorAlphaLong();
   1175         nsm.operatorAlphaShort = network.getOperatorAlphaShort();
   1176 
   1177         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
   1178         mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
   1179 
   1180         if (persistSelection) {
   1181             updateSavedNetworkOperator(nsm);
   1182         } else {
   1183             clearSavedNetworkSelection();
   1184         }
   1185     }
   1186 
   1187     /**
   1188      * Registration point for emergency call/callback mode start. Message.obj is AsyncResult and
   1189      * Message.obj.result will be Integer indicating start of call by value 1 or end of call by
   1190      * value 0
   1191      * @param h handler to notify
   1192      * @param what what code of message when delivered
   1193      * @param obj placed in Message.obj.userObj
   1194      */
   1195     public void registerForEmergencyCallToggle(Handler h, int what, Object obj) {
   1196         Registrant r = new Registrant(h, what, obj);
   1197         mEmergencyCallToggledRegistrants.add(r);
   1198     }
   1199 
   1200     public void unregisterForEmergencyCallToggle(Handler h) {
   1201         mEmergencyCallToggledRegistrants.remove(h);
   1202     }
   1203 
   1204     private void updateSavedNetworkOperator(NetworkSelectMessage nsm) {
   1205         int subId = getSubId();
   1206         if (SubscriptionManager.isValidSubscriptionId(subId)) {
   1207             // open the shared preferences editor, and write the value.
   1208             // nsm.operatorNumeric is "" if we're in automatic.selection.
   1209             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1210             SharedPreferences.Editor editor = sp.edit();
   1211             editor.putString(NETWORK_SELECTION_KEY + subId, nsm.operatorNumeric);
   1212             editor.putString(NETWORK_SELECTION_NAME_KEY + subId, nsm.operatorAlphaLong);
   1213             editor.putString(NETWORK_SELECTION_SHORT_KEY + subId, nsm.operatorAlphaShort);
   1214 
   1215             // commit and log the result.
   1216             if (!editor.commit()) {
   1217                 Rlog.e(LOG_TAG, "failed to commit network selection preference");
   1218             }
   1219         } else {
   1220             Rlog.e(LOG_TAG, "Cannot update network selection preference due to invalid subId " +
   1221                     subId);
   1222         }
   1223     }
   1224 
   1225     /**
   1226      * Used to track the settings upon completion of the network change.
   1227      */
   1228     private void handleSetSelectNetwork(AsyncResult ar) {
   1229         // look for our wrapper within the asyncresult, skip the rest if it
   1230         // is null.
   1231         if (!(ar.userObj instanceof NetworkSelectMessage)) {
   1232             Rlog.e(LOG_TAG, "unexpected result from user object.");
   1233             return;
   1234         }
   1235 
   1236         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
   1237 
   1238         // found the object, now we send off the message we had originally
   1239         // attached to the request.
   1240         if (nsm.message != null) {
   1241             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
   1242             nsm.message.sendToTarget();
   1243         }
   1244     }
   1245 
   1246     /**
   1247      * Method to retrieve the saved operator from the Shared Preferences
   1248      */
   1249     private OperatorInfo getSavedNetworkSelection() {
   1250         // open the shared preferences and search with our key.
   1251         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1252         String numeric = sp.getString(NETWORK_SELECTION_KEY + getSubId(), "");
   1253         String name = sp.getString(NETWORK_SELECTION_NAME_KEY + getSubId(), "");
   1254         String shrt = sp.getString(NETWORK_SELECTION_SHORT_KEY + getSubId(), "");
   1255         return new OperatorInfo(name, shrt, numeric);
   1256     }
   1257 
   1258     /**
   1259      * Clears the saved network selection.
   1260      */
   1261     private void clearSavedNetworkSelection() {
   1262         // open the shared preferences and search with our key.
   1263         PreferenceManager.getDefaultSharedPreferences(getContext()).edit().
   1264                 remove(NETWORK_SELECTION_KEY + getSubId()).
   1265                 remove(NETWORK_SELECTION_NAME_KEY + getSubId()).
   1266                 remove(NETWORK_SELECTION_SHORT_KEY + getSubId()).commit();
   1267     }
   1268 
   1269     /**
   1270      * Method to restore the previously saved operator id, or reset to
   1271      * automatic selection, all depending upon the value in the shared
   1272      * preferences.
   1273      */
   1274     private void restoreSavedNetworkSelection(Message response) {
   1275         // retrieve the operator
   1276         OperatorInfo networkSelection = getSavedNetworkSelection();
   1277 
   1278         // set to auto if the id is empty, otherwise select the network.
   1279         if (networkSelection == null || TextUtils.isEmpty(networkSelection.getOperatorNumeric())) {
   1280             setNetworkSelectionModeAutomatic(response);
   1281         } else {
   1282             selectNetworkManually(networkSelection, true, response);
   1283         }
   1284     }
   1285 
   1286     /**
   1287      * Saves CLIR setting so that we can re-apply it as necessary
   1288      * (in case the RIL resets it across reboots).
   1289      */
   1290     public void saveClirSetting(int commandInterfaceCLIRMode) {
   1291         // Open the shared preferences editor, and write the value.
   1292         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1293         SharedPreferences.Editor editor = sp.edit();
   1294         editor.putInt(CLIR_KEY + getPhoneId(), commandInterfaceCLIRMode);
   1295 
   1296         // Commit and log the result.
   1297         if (!editor.commit()) {
   1298             Rlog.e(LOG_TAG, "Failed to commit CLIR preference");
   1299         }
   1300     }
   1301 
   1302     /**
   1303      * For unit tests; don't send notifications to "Phone"
   1304      * mailbox registrants if true.
   1305      */
   1306     private void setUnitTestMode(boolean f) {
   1307         mUnitTestMode = f;
   1308     }
   1309 
   1310     /**
   1311      * @return true If unit test mode is enabled
   1312      */
   1313     public boolean getUnitTestMode() {
   1314         return mUnitTestMode;
   1315     }
   1316 
   1317     /**
   1318      * To be invoked when a voice call Connection disconnects.
   1319      *
   1320      * Subclasses of Phone probably want to replace this with a
   1321      * version scoped to their packages
   1322      */
   1323     protected void notifyDisconnectP(Connection cn) {
   1324         AsyncResult ar = new AsyncResult(null, cn, null);
   1325         mDisconnectRegistrants.notifyRegistrants(ar);
   1326     }
   1327 
   1328     /**
   1329      * Register for ServiceState changed.
   1330      * Message.obj will contain an AsyncResult.
   1331      * AsyncResult.result will be a ServiceState instance
   1332      */
   1333     public void registerForServiceStateChanged(
   1334             Handler h, int what, Object obj) {
   1335         checkCorrectThread(h);
   1336 
   1337         mServiceStateRegistrants.add(h, what, obj);
   1338     }
   1339 
   1340     /**
   1341      * Unregisters for ServiceStateChange notification.
   1342      * Extraneous calls are tolerated silently
   1343      */
   1344     public void unregisterForServiceStateChanged(Handler h) {
   1345         mServiceStateRegistrants.remove(h);
   1346     }
   1347 
   1348     /**
   1349      * Notifies when out-band ringback tone is needed.<p>
   1350      *
   1351      *  Messages received from this:
   1352      *  Message.obj will be an AsyncResult
   1353      *  AsyncResult.userObj = obj
   1354      *  AsyncResult.result = boolean, true to start play ringback tone
   1355      *                       and false to stop. <p>
   1356      */
   1357     public void registerForRingbackTone(Handler h, int what, Object obj) {
   1358         mCi.registerForRingbackTone(h, what, obj);
   1359     }
   1360 
   1361     /**
   1362      * Unregisters for ringback tone notification.
   1363      */
   1364     public void unregisterForRingbackTone(Handler h) {
   1365         mCi.unregisterForRingbackTone(h);
   1366     }
   1367 
   1368     /**
   1369      * Notifies when out-band on-hold tone is needed.<p>
   1370      *
   1371      *  Messages received from this:
   1372      *  Message.obj will be an AsyncResult
   1373      *  AsyncResult.userObj = obj
   1374      *  AsyncResult.result = boolean, true to start play on-hold tone
   1375      *                       and false to stop. <p>
   1376      */
   1377     public void registerForOnHoldTone(Handler h, int what, Object obj) {
   1378     }
   1379 
   1380     /**
   1381      * Unregisters for on-hold tone notification.
   1382      */
   1383     public void unregisterForOnHoldTone(Handler h) {
   1384     }
   1385 
   1386     /**
   1387      * Registers the handler to reset the uplink mute state to get
   1388      * uplink audio.
   1389      */
   1390     public void registerForResendIncallMute(Handler h, int what, Object obj) {
   1391         mCi.registerForResendIncallMute(h, what, obj);
   1392     }
   1393 
   1394     /**
   1395      * Unregisters for resend incall mute notifications.
   1396      */
   1397     public void unregisterForResendIncallMute(Handler h) {
   1398         mCi.unregisterForResendIncallMute(h);
   1399     }
   1400 
   1401     /**
   1402      * Enables or disables echo suppression.
   1403      */
   1404     public void setEchoSuppressionEnabled() {
   1405         // no need for regular phone
   1406     }
   1407 
   1408     /**
   1409      * Subclasses of Phone probably want to replace this with a
   1410      * version scoped to their packages
   1411      */
   1412     protected void notifyServiceStateChangedP(ServiceState ss) {
   1413         AsyncResult ar = new AsyncResult(null, ss, null);
   1414         mServiceStateRegistrants.notifyRegistrants(ar);
   1415 
   1416         mNotifier.notifyServiceState(this);
   1417     }
   1418 
   1419     /**
   1420      * If this is a simulated phone interface, returns a SimulatedRadioControl.
   1421      * @return SimulatedRadioControl if this is a simulated interface;
   1422      * otherwise, null.
   1423      */
   1424     public SimulatedRadioControl getSimulatedRadioControl() {
   1425         return mSimulatedRadioControl;
   1426     }
   1427 
   1428     /**
   1429      * Verifies the current thread is the same as the thread originally
   1430      * used in the initialization of this instance. Throws RuntimeException
   1431      * if not.
   1432      *
   1433      * @exception RuntimeException if the current thread is not
   1434      * the thread that originally obtained this Phone instance.
   1435      */
   1436     private void checkCorrectThread(Handler h) {
   1437         if (h.getLooper() != mLooper) {
   1438             throw new RuntimeException(
   1439                     "com.android.internal.telephony.Phone must be used from within one thread");
   1440         }
   1441     }
   1442 
   1443     /**
   1444      * Set the properties by matching the carrier string in
   1445      * a string-array resource
   1446      */
   1447     private static Locale getLocaleFromCarrierProperties(Context ctx) {
   1448         String carrier = SystemProperties.get("ro.carrier");
   1449 
   1450         if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
   1451             return null;
   1452         }
   1453 
   1454         CharSequence[] carrierLocales = ctx.getResources().getTextArray(R.array.carrier_properties);
   1455 
   1456         for (int i = 0; i < carrierLocales.length; i+=3) {
   1457             String c = carrierLocales[i].toString();
   1458             if (carrier.equals(c)) {
   1459                 return Locale.forLanguageTag(carrierLocales[i + 1].toString().replace('_', '-'));
   1460             }
   1461         }
   1462 
   1463         return null;
   1464     }
   1465 
   1466     /**
   1467      * Get current coarse-grained voice call state.
   1468      * Use {@link #registerForPreciseCallStateChanged(Handler, int, Object)
   1469      * registerForPreciseCallStateChanged()} for change notification. <p>
   1470      * If the phone has an active call and call waiting occurs,
   1471      * then the phone state is RINGING not OFFHOOK
   1472      * <strong>Note:</strong>
   1473      * This registration point provides notification of finer-grained
   1474      * changes.<p>
   1475      */
   1476     public abstract PhoneConstants.State getState();
   1477 
   1478     /**
   1479      * Retrieves the IccFileHandler of the Phone instance
   1480      */
   1481     public IccFileHandler getIccFileHandler(){
   1482         UiccCardApplication uiccApplication = mUiccApplication.get();
   1483         IccFileHandler fh;
   1484 
   1485         if (uiccApplication == null) {
   1486             Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
   1487             fh = null;
   1488         } else {
   1489             fh = uiccApplication.getIccFileHandler();
   1490         }
   1491 
   1492         Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
   1493         return fh;
   1494     }
   1495 
   1496     /*
   1497      * Retrieves the Handler of the Phone instance
   1498      */
   1499     public Handler getHandler() {
   1500         return this;
   1501     }
   1502 
   1503     /**
   1504      * Update the phone object if the voice radio technology has changed
   1505      *
   1506      * @param voiceRadioTech The new voice radio technology
   1507      */
   1508     public void updatePhoneObject(int voiceRadioTech) {
   1509     }
   1510 
   1511     /**
   1512     * Retrieves the ServiceStateTracker of the phone instance.
   1513     */
   1514     public ServiceStateTracker getServiceStateTracker() {
   1515         return null;
   1516     }
   1517 
   1518     /**
   1519     * Get call tracker
   1520     */
   1521     public CallTracker getCallTracker() {
   1522         return null;
   1523     }
   1524 
   1525     /**
   1526      * Update voice mail count related fields and notify listeners
   1527      */
   1528     public void updateVoiceMail() {
   1529         Rlog.e(LOG_TAG, "updateVoiceMail() should be overridden");
   1530     }
   1531 
   1532     public AppType getCurrentUiccAppType() {
   1533         UiccCardApplication currentApp = mUiccApplication.get();
   1534         if (currentApp != null) {
   1535             return currentApp.getType();
   1536         }
   1537         return AppType.APPTYPE_UNKNOWN;
   1538     }
   1539 
   1540     /**
   1541      * Returns the ICC card interface for this phone, or null
   1542      * if not applicable to underlying technology.
   1543      */
   1544     public IccCard getIccCard() {
   1545         return null;
   1546         //throw new Exception("getIccCard Shouldn't be called from Phone");
   1547     }
   1548 
   1549     /**
   1550      * Retrieves the serial number of the ICC, if applicable. Returns only the decimal digits before
   1551      * the first hex digit in the ICC ID.
   1552      */
   1553     public String getIccSerialNumber() {
   1554         IccRecords r = mIccRecords.get();
   1555         return (r != null) ? r.getIccId() : null;
   1556     }
   1557 
   1558     /**
   1559      * Retrieves the full serial number of the ICC (including hex digits), if applicable.
   1560      */
   1561     public String getFullIccSerialNumber() {
   1562         IccRecords r = mIccRecords.get();
   1563         return (r != null) ? r.getFullIccId() : null;
   1564     }
   1565 
   1566     /**
   1567      * Returns SIM record load state. Use
   1568      * <code>getSimCard().registerForReady()</code> for change notification.
   1569      *
   1570      * @return true if records from the SIM have been loaded and are
   1571      * available (if applicable). If not applicable to the underlying
   1572      * technology, returns true as well.
   1573      */
   1574     public boolean getIccRecordsLoaded() {
   1575         IccRecords r = mIccRecords.get();
   1576         return (r != null) ? r.getRecordsLoaded() : false;
   1577     }
   1578 
   1579     /**
   1580      * @return all available cell information or null if none.
   1581      */
   1582     public List<CellInfo> getAllCellInfo() {
   1583         List<CellInfo> cellInfoList = getServiceStateTracker().getAllCellInfo();
   1584         return privatizeCellInfoList(cellInfoList);
   1585     }
   1586 
   1587     /**
   1588      * Clear CDMA base station lat/long values if location setting is disabled.
   1589      * @param cellInfoList the original cell info list from the RIL
   1590      * @return the original list with CDMA lat/long cleared if necessary
   1591      */
   1592     private List<CellInfo> privatizeCellInfoList(List<CellInfo> cellInfoList) {
   1593         if (cellInfoList == null) return null;
   1594         int mode = Settings.Secure.getInt(getContext().getContentResolver(),
   1595                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
   1596         if (mode == Settings.Secure.LOCATION_MODE_OFF) {
   1597             ArrayList<CellInfo> privateCellInfoList = new ArrayList<CellInfo>(cellInfoList.size());
   1598             // clear lat/lon values for location privacy
   1599             for (CellInfo c : cellInfoList) {
   1600                 if (c instanceof CellInfoCdma) {
   1601                     CellInfoCdma cellInfoCdma = (CellInfoCdma) c;
   1602                     CellIdentityCdma cellIdentity = cellInfoCdma.getCellIdentity();
   1603                     CellIdentityCdma maskedCellIdentity = new CellIdentityCdma(
   1604                             cellIdentity.getNetworkId(),
   1605                             cellIdentity.getSystemId(),
   1606                             cellIdentity.getBasestationId(),
   1607                             Integer.MAX_VALUE, Integer.MAX_VALUE);
   1608                     CellInfoCdma privateCellInfoCdma = new CellInfoCdma(cellInfoCdma);
   1609                     privateCellInfoCdma.setCellIdentity(maskedCellIdentity);
   1610                     privateCellInfoList.add(privateCellInfoCdma);
   1611                 } else {
   1612                     privateCellInfoList.add(c);
   1613                 }
   1614             }
   1615             cellInfoList = privateCellInfoList;
   1616         }
   1617         return cellInfoList;
   1618     }
   1619 
   1620     /**
   1621      * Sets the minimum time in milli-seconds between {@link PhoneStateListener#onCellInfoChanged
   1622      * PhoneStateListener.onCellInfoChanged} will be invoked.
   1623      *
   1624      * The default, 0, means invoke onCellInfoChanged when any of the reported
   1625      * information changes. Setting the value to INT_MAX(0x7fffffff) means never issue
   1626      * A onCellInfoChanged.
   1627      *
   1628      * @param rateInMillis the rate
   1629      */
   1630     public void setCellInfoListRate(int rateInMillis) {
   1631         mCi.setCellInfoListRate(rateInMillis, null);
   1632     }
   1633 
   1634     /**
   1635      * Get voice message waiting indicator status. No change notification
   1636      * available on this interface. Use PhoneStateNotifier or similar instead.
   1637      *
   1638      * @return true if there is a voice message waiting
   1639      */
   1640     public boolean getMessageWaitingIndicator() {
   1641         return mVmCount != 0;
   1642     }
   1643 
   1644     private int getCallForwardingIndicatorFromSharedPref() {
   1645         int status = IccRecords.CALL_FORWARDING_STATUS_DISABLED;
   1646         int subId = getSubId();
   1647         if (SubscriptionManager.isValidSubscriptionId(subId)) {
   1648             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   1649             status = sp.getInt(CF_STATUS + subId, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN);
   1650             Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: for subId " + subId + "= " +
   1651                     status);
   1652             // Check for old preference if status is UNKNOWN for current subId. This part of the
   1653             // code is needed only when upgrading from M to N.
   1654             if (status == IccRecords.CALL_FORWARDING_STATUS_UNKNOWN) {
   1655                 String subscriberId = sp.getString(CF_ID, null);
   1656                 if (subscriberId != null) {
   1657                     String currentSubscriberId = getSubscriberId();
   1658 
   1659                     if (subscriberId.equals(currentSubscriberId)) {
   1660                         // get call forwarding status from preferences
   1661                         status = sp.getInt(CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_DISABLED);
   1662                         setCallForwardingIndicatorInSharedPref(
   1663                                 status == IccRecords.CALL_FORWARDING_STATUS_ENABLED ? true : false);
   1664                         Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: " + status);
   1665                     } else {
   1666                         Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: returning " +
   1667                                 "DISABLED as status for matching subscriberId not found");
   1668                     }
   1669 
   1670                     // get rid of old preferences.
   1671                     SharedPreferences.Editor editor = sp.edit();
   1672                     editor.remove(CF_ID);
   1673                     editor.remove(CF_STATUS);
   1674                     editor.apply();
   1675                 }
   1676             }
   1677         } else {
   1678             Rlog.e(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: invalid subId " + subId);
   1679         }
   1680         return status;
   1681     }
   1682 
   1683     private void setCallForwardingIndicatorInSharedPref(boolean enable) {
   1684         int status = enable ? IccRecords.CALL_FORWARDING_STATUS_ENABLED :
   1685                 IccRecords.CALL_FORWARDING_STATUS_DISABLED;
   1686         int subId = getSubId();
   1687         Rlog.d(LOG_TAG, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
   1688                 " in pref " + CF_STATUS + subId);
   1689 
   1690         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   1691         SharedPreferences.Editor editor = sp.edit();
   1692         editor.putInt(CF_STATUS + subId, status);
   1693         editor.apply();
   1694     }
   1695 
   1696     public void setVoiceCallForwardingFlag(int line, boolean enable, String number) {
   1697         setCallForwardingIndicatorInSharedPref(enable);
   1698         IccRecords r = mIccRecords.get();
   1699         if (r != null) {
   1700             r.setVoiceCallForwardingFlag(line, enable, number);
   1701         }
   1702     }
   1703 
   1704     protected void setVoiceCallForwardingFlag(IccRecords r, int line, boolean enable,
   1705                                               String number) {
   1706         setCallForwardingIndicatorInSharedPref(enable);
   1707         r.setVoiceCallForwardingFlag(line, enable, number);
   1708     }
   1709 
   1710     /**
   1711      * Get voice call forwarding indicator status. No change notification
   1712      * available on this interface. Use PhoneStateNotifier or similar instead.
   1713      *
   1714      * @return true if there is a voice call forwarding
   1715      */
   1716     public boolean getCallForwardingIndicator() {
   1717         if (getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
   1718             Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
   1719             return false;
   1720         }
   1721         IccRecords r = mIccRecords.get();
   1722         int callForwardingIndicator = IccRecords.CALL_FORWARDING_STATUS_UNKNOWN;
   1723         if (r != null) {
   1724             callForwardingIndicator = r.getVoiceCallForwardingFlag();
   1725         }
   1726         if (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_UNKNOWN) {
   1727             callForwardingIndicator = getCallForwardingIndicatorFromSharedPref();
   1728         }
   1729         return (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_ENABLED);
   1730     }
   1731 
   1732     public CarrierSignalAgent getCarrierSignalAgent() {
   1733         return mCarrierSignalAgent;
   1734     }
   1735 
   1736     /**
   1737      *  Query the CDMA roaming preference setting
   1738      *
   1739      * @param response is callback message to report one of  CDMA_RM_*
   1740      */
   1741     public void queryCdmaRoamingPreference(Message response) {
   1742         mCi.queryCdmaRoamingPreference(response);
   1743     }
   1744 
   1745     /**
   1746      * Get current signal strength. No change notification available on this
   1747      * interface. Use <code>PhoneStateNotifier</code> or an equivalent.
   1748      * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu).
   1749      * The following special values are defined:</p>
   1750      * <ul><li>0 means "-113 dBm or less".</li>
   1751      * <li>31 means "-51 dBm or greater".</li></ul>
   1752      *
   1753      * @return Current signal strength as SignalStrength
   1754      */
   1755     public SignalStrength getSignalStrength() {
   1756         ServiceStateTracker sst = getServiceStateTracker();
   1757         if (sst == null) {
   1758             return new SignalStrength();
   1759         } else {
   1760             return sst.getSignalStrength();
   1761         }
   1762     }
   1763 
   1764     /**
   1765      *  Requests to set the CDMA roaming preference
   1766      * @param cdmaRoamingType one of  CDMA_RM_*
   1767      * @param response is callback message
   1768      */
   1769     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
   1770         mCi.setCdmaRoamingPreference(cdmaRoamingType, response);
   1771     }
   1772 
   1773     /**
   1774      *  Requests to set the CDMA subscription mode
   1775      * @param cdmaSubscriptionType one of  CDMA_SUBSCRIPTION_*
   1776      * @param response is callback message
   1777      */
   1778     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
   1779         mCi.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
   1780     }
   1781 
   1782     /**
   1783      *  Requests to set the preferred network type for searching and registering
   1784      * (CS/PS domain, RAT, and operation mode)
   1785      * @param networkType one of  NT_*_TYPE
   1786      * @param response is callback message
   1787      */
   1788     public void setPreferredNetworkType(int networkType, Message response) {
   1789         // Only set preferred network types to that which the modem supports
   1790         int modemRaf = getRadioAccessFamily();
   1791         int rafFromType = RadioAccessFamily.getRafFromNetworkType(networkType);
   1792 
   1793         if (modemRaf == RadioAccessFamily.RAF_UNKNOWN
   1794                 || rafFromType == RadioAccessFamily.RAF_UNKNOWN) {
   1795             Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
   1796                     + modemRaf + " " + rafFromType);
   1797             if (response != null) {
   1798                 CommandException ex;
   1799 
   1800                 ex = new CommandException(CommandException.Error.GENERIC_FAILURE);
   1801                 AsyncResult.forMessage(response, null, ex);
   1802                 response.sendToTarget();
   1803             }
   1804             return;
   1805         }
   1806 
   1807         int filteredRaf = (rafFromType & modemRaf);
   1808         int filteredType = RadioAccessFamily.getNetworkTypeFromRaf(filteredRaf);
   1809 
   1810         Rlog.d(LOG_TAG, "setPreferredNetworkType: networkType = " + networkType
   1811                 + " modemRaf = " + modemRaf
   1812                 + " rafFromType = " + rafFromType
   1813                 + " filteredType = " + filteredType);
   1814 
   1815         mCi.setPreferredNetworkType(filteredType, response);
   1816     }
   1817 
   1818     /**
   1819      *  Query the preferred network type setting
   1820      *
   1821      * @param response is callback message to report one of  NT_*_TYPE
   1822      */
   1823     public void getPreferredNetworkType(Message response) {
   1824         mCi.getPreferredNetworkType(response);
   1825     }
   1826 
   1827     /**
   1828      * Gets the default SMSC address.
   1829      *
   1830      * @param result Callback message contains the SMSC address.
   1831      */
   1832     public void getSmscAddress(Message result) {
   1833         mCi.getSmscAddress(result);
   1834     }
   1835 
   1836     /**
   1837      * Sets the default SMSC address.
   1838      *
   1839      * @param address new SMSC address
   1840      * @param result Callback message is empty on completion
   1841      */
   1842     public void setSmscAddress(String address, Message result) {
   1843         mCi.setSmscAddress(address, result);
   1844     }
   1845 
   1846     /**
   1847      * setTTYMode
   1848      * sets a TTY mode option.
   1849      * @param ttyMode is a one of the following:
   1850      * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
   1851      * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
   1852      * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
   1853      * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
   1854      * @param onComplete a callback message when the action is completed
   1855      */
   1856     public void setTTYMode(int ttyMode, Message onComplete) {
   1857         mCi.setTTYMode(ttyMode, onComplete);
   1858     }
   1859 
   1860     /**
   1861      * setUiTTYMode
   1862      * sets a TTY mode option.
   1863      * @param ttyMode is a one of the following:
   1864      * - {@link com.android.internal.telephony.Phone#TTY_MODE_OFF}
   1865      * - {@link com.android.internal.telephony.Phone#TTY_MODE_FULL}
   1866      * - {@link com.android.internal.telephony.Phone#TTY_MODE_HCO}
   1867      * - {@link com.android.internal.telephony.Phone#TTY_MODE_VCO}
   1868      * @param onComplete a callback message when the action is completed
   1869      */
   1870     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
   1871         Rlog.d(LOG_TAG, "unexpected setUiTTYMode method call");
   1872     }
   1873 
   1874     /**
   1875      * queryTTYMode
   1876      * query the status of the TTY mode
   1877      *
   1878      * @param onComplete a callback message when the action is completed.
   1879      */
   1880     public void queryTTYMode(Message onComplete) {
   1881         mCi.queryTTYMode(onComplete);
   1882     }
   1883 
   1884     /**
   1885      * Enable or disable enhanced Voice Privacy (VP). If enhanced VP is
   1886      * disabled, normal VP is enabled.
   1887      *
   1888      * @param enable whether true or false to enable or disable.
   1889      * @param onComplete a callback message when the action is completed.
   1890      */
   1891     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
   1892     }
   1893 
   1894     /**
   1895      * Get the currently set Voice Privacy (VP) mode.
   1896      *
   1897      * @param onComplete a callback message when the action is completed.
   1898      */
   1899     public void getEnhancedVoicePrivacy(Message onComplete) {
   1900     }
   1901 
   1902     /**
   1903      * Assign a specified band for RF configuration.
   1904      *
   1905      * @param bandMode one of BM_*_BAND
   1906      * @param response is callback message
   1907      */
   1908     public void setBandMode(int bandMode, Message response) {
   1909         mCi.setBandMode(bandMode, response);
   1910     }
   1911 
   1912     /**
   1913      * Query the list of band mode supported by RF.
   1914      *
   1915      * @param response is callback message
   1916      *        ((AsyncResult)response.obj).result  is an int[] where int[0] is
   1917      *        the size of the array and the rest of each element representing
   1918      *        one available BM_*_BAND
   1919      */
   1920     public void queryAvailableBandMode(Message response) {
   1921         mCi.queryAvailableBandMode(response);
   1922     }
   1923 
   1924     /**
   1925      * Invokes RIL_REQUEST_OEM_HOOK_RAW on RIL implementation.
   1926      *
   1927      * @param data The data for the request.
   1928      * @param response <strong>On success</strong>,
   1929      * (byte[])(((AsyncResult)response.obj).result)
   1930      * <strong>On failure</strong>,
   1931      * (((AsyncResult)response.obj).result) == null and
   1932      * (((AsyncResult)response.obj).exception) being an instance of
   1933      * com.android.internal.telephony.gsm.CommandException
   1934      *
   1935      * @see #invokeOemRilRequestRaw(byte[], android.os.Message)
   1936      */
   1937     public void invokeOemRilRequestRaw(byte[] data, Message response) {
   1938         mCi.invokeOemRilRequestRaw(data, response);
   1939     }
   1940 
   1941     /**
   1942      * Invokes RIL_REQUEST_OEM_HOOK_Strings on RIL implementation.
   1943      *
   1944      * @param strings The strings to make available as the request data.
   1945      * @param response <strong>On success</strong>, "response" bytes is
   1946      * made available as:
   1947      * (String[])(((AsyncResult)response.obj).result).
   1948      * <strong>On failure</strong>,
   1949      * (((AsyncResult)response.obj).result) == null and
   1950      * (((AsyncResult)response.obj).exception) being an instance of
   1951      * com.android.internal.telephony.gsm.CommandException
   1952      *
   1953      * @see #invokeOemRilRequestStrings(java.lang.String[], android.os.Message)
   1954      */
   1955     public void invokeOemRilRequestStrings(String[] strings, Message response) {
   1956         mCi.invokeOemRilRequestStrings(strings, response);
   1957     }
   1958 
   1959     /**
   1960      * Read one of the NV items defined in {@link RadioNVItems} / {@code ril_nv_items.h}.
   1961      * Used for device configuration by some CDMA operators.
   1962      *
   1963      * @param itemID the ID of the item to read
   1964      * @param response callback message with the String response in the obj field
   1965      */
   1966     public void nvReadItem(int itemID, Message response) {
   1967         mCi.nvReadItem(itemID, response);
   1968     }
   1969 
   1970     /**
   1971      * Write one of the NV items defined in {@link RadioNVItems} / {@code ril_nv_items.h}.
   1972      * Used for device configuration by some CDMA operators.
   1973      *
   1974      * @param itemID the ID of the item to read
   1975      * @param itemValue the value to write, as a String
   1976      * @param response Callback message.
   1977      */
   1978     public void nvWriteItem(int itemID, String itemValue, Message response) {
   1979         mCi.nvWriteItem(itemID, itemValue, response);
   1980     }
   1981 
   1982     /**
   1983      * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
   1984      * Used for device configuration by some CDMA operators.
   1985      *
   1986      * @param preferredRoamingList byte array containing the new PRL
   1987      * @param response Callback message.
   1988      */
   1989     public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
   1990         mCi.nvWriteCdmaPrl(preferredRoamingList, response);
   1991     }
   1992 
   1993     /**
   1994      * Perform the specified type of NV config reset. The radio will be taken offline
   1995      * and the device must be rebooted after erasing the NV. Used for device
   1996      * configuration by some CDMA operators.
   1997      *
   1998      * @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
   1999      * @param response Callback message.
   2000      */
   2001     public void nvResetConfig(int resetType, Message response) {
   2002         mCi.nvResetConfig(resetType, response);
   2003     }
   2004 
   2005     public void notifyDataActivity() {
   2006         mNotifier.notifyDataActivity(this);
   2007     }
   2008 
   2009     private void notifyMessageWaitingIndicator() {
   2010         // Do not notify voice mail waiting if device doesn't support voice
   2011         if (!mIsVoiceCapable)
   2012             return;
   2013 
   2014         // This function is added to send the notification to DefaultPhoneNotifier.
   2015         mNotifier.notifyMessageWaitingChanged(this);
   2016     }
   2017 
   2018     public void notifyDataConnection(String reason, String apnType,
   2019             PhoneConstants.DataState state) {
   2020         mNotifier.notifyDataConnection(this, reason, apnType, state);
   2021     }
   2022 
   2023     public void notifyDataConnection(String reason, String apnType) {
   2024         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
   2025     }
   2026 
   2027     public void notifyDataConnection(String reason) {
   2028         String types[] = getActiveApnTypes();
   2029         for (String apnType : types) {
   2030             mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
   2031         }
   2032     }
   2033 
   2034     public void notifyOtaspChanged(int otaspMode) {
   2035         mNotifier.notifyOtaspChanged(this, otaspMode);
   2036     }
   2037 
   2038     public void notifySignalStrength() {
   2039         mNotifier.notifySignalStrength(this);
   2040     }
   2041 
   2042     public void notifyCellInfo(List<CellInfo> cellInfo) {
   2043         mNotifier.notifyCellInfo(this, privatizeCellInfoList(cellInfo));
   2044     }
   2045 
   2046     public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
   2047         mNotifier.notifyVoLteServiceStateChanged(this, lteState);
   2048     }
   2049 
   2050     /**
   2051      * @return true if a mobile originating emergency call is active
   2052      */
   2053     public boolean isInEmergencyCall() {
   2054         return false;
   2055     }
   2056 
   2057     /**
   2058      * @return {@code true} if we are in emergency call back mode. This is a period where the phone
   2059      * should be using as little power as possible and be ready to receive an incoming call from the
   2060      * emergency operator.
   2061      */
   2062     public boolean isInEcm() {
   2063         return false;
   2064     }
   2065 
   2066     private static int getVideoState(Call call) {
   2067         int videoState = VideoProfile.STATE_AUDIO_ONLY;
   2068         Connection conn = call.getEarliestConnection();
   2069         if (conn != null) {
   2070             videoState = conn.getVideoState();
   2071         }
   2072         return videoState;
   2073     }
   2074 
   2075     private boolean isVideoCall(Call call) {
   2076         int videoState = getVideoState(call);
   2077         return (VideoProfile.isVideo(videoState));
   2078     }
   2079 
   2080     /**
   2081      * @return {@code true} if video call is present, false otherwise.
   2082      */
   2083     public boolean isVideoCallPresent() {
   2084         boolean isVideoCallActive = false;
   2085         if (mImsPhone != null) {
   2086             isVideoCallActive = isVideoCall(mImsPhone.getForegroundCall()) ||
   2087                     isVideoCall(mImsPhone.getBackgroundCall()) ||
   2088                     isVideoCall(mImsPhone.getRingingCall());
   2089         }
   2090         Rlog.d(LOG_TAG, "isVideoCallActive: " + isVideoCallActive);
   2091         return isVideoCallActive;
   2092     }
   2093 
   2094     /**
   2095      * Return a numerical identifier for the phone radio interface.
   2096      * @return PHONE_TYPE_XXX as defined above.
   2097      */
   2098     public abstract int getPhoneType();
   2099 
   2100     /**
   2101      * Returns unread voicemail count. This count is shown when the  voicemail
   2102      * notification is expanded.<p>
   2103      */
   2104     public int getVoiceMessageCount(){
   2105         return mVmCount;
   2106     }
   2107 
   2108     /** sets the voice mail count of the phone and notifies listeners. */
   2109     public void setVoiceMessageCount(int countWaiting) {
   2110         mVmCount = countWaiting;
   2111         int subId = getSubId();
   2112         if (SubscriptionManager.isValidSubscriptionId(subId)) {
   2113 
   2114             Rlog.d(LOG_TAG, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting +
   2115                     " for mVmCountKey = " + VM_COUNT + subId + " in preferences.");
   2116 
   2117             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   2118             SharedPreferences.Editor editor = sp.edit();
   2119             editor.putInt(VM_COUNT + subId, countWaiting);
   2120             editor.apply();
   2121         } else {
   2122             Rlog.e(LOG_TAG, "setVoiceMessageCount in sharedPreference: invalid subId " + subId);
   2123         }
   2124         // notify listeners of voice mail
   2125         notifyMessageWaitingIndicator();
   2126     }
   2127 
   2128     /** gets the voice mail count from preferences */
   2129     protected int getStoredVoiceMessageCount() {
   2130         int countVoiceMessages = 0;
   2131         int subId = getSubId();
   2132         if (SubscriptionManager.isValidSubscriptionId(subId)) {
   2133             int invalidCount = -2;  //-1 is not really invalid. It is used for unknown number of vm
   2134             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   2135             int countFromSP = sp.getInt(VM_COUNT + subId, invalidCount);
   2136             if (countFromSP != invalidCount) {
   2137                 countVoiceMessages = countFromSP;
   2138                 Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference for subId " + subId +
   2139                         "= " + countVoiceMessages);
   2140             } else {
   2141                 // Check for old preference if count not found for current subId. This part of the
   2142                 // code is needed only when upgrading from M to N.
   2143                 String subscriberId = sp.getString(VM_ID, null);
   2144                 if (subscriberId != null) {
   2145                     String currentSubscriberId = getSubscriberId();
   2146 
   2147                     if (currentSubscriberId != null && currentSubscriberId.equals(subscriberId)) {
   2148                         // get voice mail count from preferences
   2149                         countVoiceMessages = sp.getInt(VM_COUNT, 0);
   2150                         setVoiceMessageCount(countVoiceMessages);
   2151                         Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference = " +
   2152                                 countVoiceMessages);
   2153                     } else {
   2154                         Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: returning 0 as count for " +
   2155                                 "matching subscriberId not found");
   2156 
   2157                     }
   2158                     // get rid of old preferences.
   2159                     SharedPreferences.Editor editor = sp.edit();
   2160                     editor.remove(VM_ID);
   2161                     editor.remove(VM_COUNT);
   2162                     editor.apply();
   2163                 }
   2164             }
   2165         } else {
   2166             Rlog.e(LOG_TAG, "getStoredVoiceMessageCount: invalid subId " + subId);
   2167         }
   2168         return countVoiceMessages;
   2169     }
   2170 
   2171     /**
   2172      * Returns the CDMA ERI icon index to display
   2173      */
   2174     public int getCdmaEriIconIndex() {
   2175         return -1;
   2176     }
   2177 
   2178     /**
   2179      * Returns the CDMA ERI icon mode,
   2180      * 0 - ON
   2181      * 1 - FLASHING
   2182      */
   2183     public int getCdmaEriIconMode() {
   2184         return -1;
   2185     }
   2186 
   2187     /**
   2188      * Returns the CDMA ERI text,
   2189      */
   2190     public String getCdmaEriText() {
   2191         return "GSM nw, no ERI";
   2192     }
   2193 
   2194     /**
   2195      * Retrieves the MIN for CDMA phones.
   2196      */
   2197     public String getCdmaMin() {
   2198         return null;
   2199     }
   2200 
   2201     /**
   2202      * Check if subscription data has been assigned to mMin
   2203      *
   2204      * return true if MIN info is ready; false otherwise.
   2205      */
   2206     public boolean isMinInfoReady() {
   2207         return false;
   2208     }
   2209 
   2210     /**
   2211      *  Retrieves PRL Version for CDMA phones
   2212      */
   2213     public String getCdmaPrlVersion(){
   2214         return null;
   2215     }
   2216 
   2217     /**
   2218      * send burst DTMF tone, it can send the string as single character or multiple character
   2219      * ignore if there is no active call or not valid digits string.
   2220      * Valid digit means only includes characters ISO-LATIN characters 0-9, *, #
   2221      * The difference between sendDtmf and sendBurstDtmf is sendDtmf only sends one character,
   2222      * this api can send single character and multiple character, also, this api has response
   2223      * back to caller.
   2224      *
   2225      * @param dtmfString is string representing the dialing digit(s) in the active call
   2226      * @param on the DTMF ON length in milliseconds, or 0 for default
   2227      * @param off the DTMF OFF length in milliseconds, or 0 for default
   2228      * @param onComplete is the callback message when the action is processed by BP
   2229      *
   2230      */
   2231     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
   2232     }
   2233 
   2234     /**
   2235      * Sets an event to be fired when the telephony system processes
   2236      * a post-dial character on an outgoing call.<p>
   2237      *
   2238      * Messages of type <code>what</code> will be sent to <code>h</code>.
   2239      * The <code>obj</code> field of these Message's will be instances of
   2240      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
   2241      * a Connection object.<p>
   2242      *
   2243      * Message.arg1 will be the post dial character being processed,
   2244      * or 0 ('\0') if end of string.<p>
   2245      *
   2246      * If Connection.getPostDialState() == WAIT,
   2247      * the application must call
   2248      * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
   2249      * Connection.proceedAfterWaitChar()} or
   2250      * {@link com.android.internal.telephony.Connection#cancelPostDial()
   2251      * Connection.cancelPostDial()}
   2252      * for the telephony system to continue playing the post-dial
   2253      * DTMF sequence.<p>
   2254      *
   2255      * If Connection.getPostDialState() == WILD,
   2256      * the application must call
   2257      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
   2258      * Connection.proceedAfterWildChar()}
   2259      * or
   2260      * {@link com.android.internal.telephony.Connection#cancelPostDial()
   2261      * Connection.cancelPostDial()}
   2262      * for the telephony system to continue playing the
   2263      * post-dial DTMF sequence.<p>
   2264      *
   2265      * Only one post dial character handler may be set. <p>
   2266      * Calling this method with "h" equal to null unsets this handler.<p>
   2267      */
   2268     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
   2269         mPostDialHandler = new Registrant(h, what, obj);
   2270     }
   2271 
   2272     public Registrant getPostDialHandler() {
   2273         return mPostDialHandler;
   2274     }
   2275 
   2276     /**
   2277      * request to exit emergency call back mode
   2278      * the caller should use setOnECMModeExitResponse
   2279      * to receive the emergency callback mode exit response
   2280      */
   2281     public void exitEmergencyCallbackMode() {
   2282     }
   2283 
   2284     /**
   2285      * Register for notifications when CDMA OTA Provision status change
   2286      *
   2287      * @param h Handler that receives the notification message.
   2288      * @param what User-defined message code.
   2289      * @param obj User object.
   2290      */
   2291     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
   2292     }
   2293 
   2294     /**
   2295      * Unregister for notifications when CDMA OTA Provision status change
   2296      * @param h Handler to be removed from the registrant list.
   2297      */
   2298     public void unregisterForCdmaOtaStatusChange(Handler h) {
   2299     }
   2300 
   2301     /**
   2302      * Registration point for subscription info ready
   2303      * @param h handler to notify
   2304      * @param what what code of message when delivered
   2305      * @param obj placed in Message.obj
   2306      */
   2307     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
   2308     }
   2309 
   2310     /**
   2311      * Unregister for notifications for subscription info
   2312      * @param h Handler to be removed from the registrant list.
   2313      */
   2314     public void unregisterForSubscriptionInfoReady(Handler h) {
   2315     }
   2316 
   2317     /**
   2318      * Returns true if OTA Service Provisioning needs to be performed.
   2319      */
   2320     public boolean needsOtaServiceProvisioning() {
   2321         return false;
   2322     }
   2323 
   2324     /**
   2325      * this decides if the dial number is OTA(Over the air provision) number or not
   2326      * @param dialStr is string representing the dialing digit(s)
   2327      * @return  true means the dialStr is OTA number, and false means the dialStr is not OTA number
   2328      */
   2329     public  boolean isOtaSpNumber(String dialStr) {
   2330         return false;
   2331     }
   2332 
   2333     /**
   2334      * Register for notifications when CDMA call waiting comes
   2335      *
   2336      * @param h Handler that receives the notification message.
   2337      * @param what User-defined message code.
   2338      * @param obj User object.
   2339      */
   2340     public void registerForCallWaiting(Handler h, int what, Object obj){
   2341     }
   2342 
   2343     /**
   2344      * Unegister for notifications when CDMA Call waiting comes
   2345      * @param h Handler to be removed from the registrant list.
   2346      */
   2347     public void unregisterForCallWaiting(Handler h){
   2348     }
   2349 
   2350     /**
   2351      * Registration point for Ecm timer reset
   2352      * @param h handler to notify
   2353      * @param what user-defined message code
   2354      * @param obj placed in Message.obj
   2355      */
   2356     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
   2357     }
   2358 
   2359     /**
   2360      * Unregister for notification for Ecm timer reset
   2361      * @param h Handler to be removed from the registrant list.
   2362      */
   2363     public void unregisterForEcmTimerReset(Handler h) {
   2364     }
   2365 
   2366     /**
   2367      * Register for signal information notifications from the network.
   2368      * Message.obj will contain an AsyncResult.
   2369      * AsyncResult.result will be a SuppServiceNotification instance.
   2370      *
   2371      * @param h Handler that receives the notification message.
   2372      * @param what User-defined message code.
   2373      * @param obj User object.
   2374      */
   2375     public void registerForSignalInfo(Handler h, int what, Object obj) {
   2376         mCi.registerForSignalInfo(h, what, obj);
   2377     }
   2378 
   2379     /**
   2380      * Unregisters for signal information notifications.
   2381      * Extraneous calls are tolerated silently
   2382      *
   2383      * @param h Handler to be removed from the registrant list.
   2384      */
   2385     public void unregisterForSignalInfo(Handler h) {
   2386         mCi.unregisterForSignalInfo(h);
   2387     }
   2388 
   2389     /**
   2390      * Register for display information notifications from the network.
   2391      * Message.obj will contain an AsyncResult.
   2392      * AsyncResult.result will be a SuppServiceNotification instance.
   2393      *
   2394      * @param h Handler that receives the notification message.
   2395      * @param what User-defined message code.
   2396      * @param obj User object.
   2397      */
   2398     public void registerForDisplayInfo(Handler h, int what, Object obj) {
   2399         mCi.registerForDisplayInfo(h, what, obj);
   2400     }
   2401 
   2402     /**
   2403      * Unregisters for display information notifications.
   2404      * Extraneous calls are tolerated silently
   2405      *
   2406      * @param h Handler to be removed from the registrant list.
   2407      */
   2408     public void unregisterForDisplayInfo(Handler h) {
   2409          mCi.unregisterForDisplayInfo(h);
   2410     }
   2411 
   2412     /**
   2413      * Register for CDMA number information record notification from the network.
   2414      * Message.obj will contain an AsyncResult.
   2415      * AsyncResult.result will be a CdmaInformationRecords.CdmaNumberInfoRec
   2416      * instance.
   2417      *
   2418      * @param h Handler that receives the notification message.
   2419      * @param what User-defined message code.
   2420      * @param obj User object.
   2421      */
   2422     public void registerForNumberInfo(Handler h, int what, Object obj) {
   2423         mCi.registerForNumberInfo(h, what, obj);
   2424     }
   2425 
   2426     /**
   2427      * Unregisters for number information record notifications.
   2428      * Extraneous calls are tolerated silently
   2429      *
   2430      * @param h Handler to be removed from the registrant list.
   2431      */
   2432     public void unregisterForNumberInfo(Handler h) {
   2433         mCi.unregisterForNumberInfo(h);
   2434     }
   2435 
   2436     /**
   2437      * Register for CDMA redirected number information record notification
   2438      * from the network.
   2439      * Message.obj will contain an AsyncResult.
   2440      * AsyncResult.result will be a CdmaInformationRecords.CdmaRedirectingNumberInfoRec
   2441      * instance.
   2442      *
   2443      * @param h Handler that receives the notification message.
   2444      * @param what User-defined message code.
   2445      * @param obj User object.
   2446      */
   2447     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
   2448         mCi.registerForRedirectedNumberInfo(h, what, obj);
   2449     }
   2450 
   2451     /**
   2452      * Unregisters for redirected number information record notification.
   2453      * Extraneous calls are tolerated silently
   2454      *
   2455      * @param h Handler to be removed from the registrant list.
   2456      */
   2457     public void unregisterForRedirectedNumberInfo(Handler h) {
   2458         mCi.unregisterForRedirectedNumberInfo(h);
   2459     }
   2460 
   2461     /**
   2462      * Register for CDMA line control information record notification
   2463      * from the network.
   2464      * Message.obj will contain an AsyncResult.
   2465      * AsyncResult.result will be a CdmaInformationRecords.CdmaLineControlInfoRec
   2466      * instance.
   2467      *
   2468      * @param h Handler that receives the notification message.
   2469      * @param what User-defined message code.
   2470      * @param obj User object.
   2471      */
   2472     public void registerForLineControlInfo(Handler h, int what, Object obj) {
   2473         mCi.registerForLineControlInfo(h, what, obj);
   2474     }
   2475 
   2476     /**
   2477      * Unregisters for line control information notifications.
   2478      * Extraneous calls are tolerated silently
   2479      *
   2480      * @param h Handler to be removed from the registrant list.
   2481      */
   2482     public void unregisterForLineControlInfo(Handler h) {
   2483         mCi.unregisterForLineControlInfo(h);
   2484     }
   2485 
   2486     /**
   2487      * Register for CDMA T53 CLIR information record notifications
   2488      * from the network.
   2489      * Message.obj will contain an AsyncResult.
   2490      * AsyncResult.result will be a CdmaInformationRecords.CdmaT53ClirInfoRec
   2491      * instance.
   2492      *
   2493      * @param h Handler that receives the notification message.
   2494      * @param what User-defined message code.
   2495      * @param obj User object.
   2496      */
   2497     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
   2498         mCi.registerFoT53ClirlInfo(h, what, obj);
   2499     }
   2500 
   2501     /**
   2502      * Unregisters for T53 CLIR information record notification
   2503      * Extraneous calls are tolerated silently
   2504      *
   2505      * @param h Handler to be removed from the registrant list.
   2506      */
   2507     public void unregisterForT53ClirInfo(Handler h) {
   2508         mCi.unregisterForT53ClirInfo(h);
   2509     }
   2510 
   2511     /**
   2512      * Register for CDMA T53 audio control information record notifications
   2513      * from the network.
   2514      * Message.obj will contain an AsyncResult.
   2515      * AsyncResult.result will be a CdmaInformationRecords.CdmaT53AudioControlInfoRec
   2516      * instance.
   2517      *
   2518      * @param h Handler that receives the notification message.
   2519      * @param what User-defined message code.
   2520      * @param obj User object.
   2521      */
   2522     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
   2523         mCi.registerForT53AudioControlInfo(h, what, obj);
   2524     }
   2525 
   2526     /**
   2527      * Unregisters for T53 audio control information record notifications.
   2528      * Extraneous calls are tolerated silently
   2529      *
   2530      * @param h Handler to be removed from the registrant list.
   2531      */
   2532     public void unregisterForT53AudioControlInfo(Handler h) {
   2533         mCi.unregisterForT53AudioControlInfo(h);
   2534     }
   2535 
   2536     /**
   2537      * registers for exit emergency call back mode request response
   2538      *
   2539      * @param h Handler that receives the notification message.
   2540      * @param what User-defined message code.
   2541      * @param obj User object.
   2542      */
   2543     public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
   2544     }
   2545 
   2546     /**
   2547      * Unregisters for exit emergency call back mode request response
   2548      *
   2549      * @param h Handler to be removed from the registrant list.
   2550      */
   2551     public void unsetOnEcbModeExitResponse(Handler h){
   2552     }
   2553 
   2554     /**
   2555      * Register for radio off or not available
   2556      *
   2557      * @param h Handler that receives the notification message.
   2558      * @param what User-defined message code.
   2559      * @param obj User object.
   2560      */
   2561     public void registerForRadioOffOrNotAvailable(Handler h, int what, Object obj) {
   2562         mRadioOffOrNotAvailableRegistrants.addUnique(h, what, obj);
   2563     }
   2564 
   2565     /**
   2566      * Unregisters for radio off or not available
   2567      *
   2568      * @param h Handler to be removed from the registrant list.
   2569      */
   2570     public void unregisterForRadioOffOrNotAvailable(Handler h) {
   2571         mRadioOffOrNotAvailableRegistrants.remove(h);
   2572     }
   2573 
   2574     /**
   2575      * Returns an array of string identifiers for the APN types serviced by the
   2576      * currently active.
   2577      *  @return The string array will always return at least one entry, Phone.APN_TYPE_DEFAULT.
   2578      * TODO: Revisit if we always should return at least one entry.
   2579      */
   2580     public String[] getActiveApnTypes() {
   2581         if (mDcTracker == null) {
   2582             return null;
   2583         }
   2584 
   2585         return mDcTracker.getActiveApnTypes();
   2586     }
   2587 
   2588     /**
   2589      * Check if TETHER_DUN_APN setting or config_tether_apndata includes APN that matches
   2590      * current operator.
   2591      * @return true if there is a matching DUN APN.
   2592      */
   2593     public boolean hasMatchedTetherApnSetting() {
   2594         return mDcTracker.hasMatchedTetherApnSetting();
   2595     }
   2596 
   2597     /**
   2598      * Returns string for the active APN host.
   2599      *  @return type as a string or null if none.
   2600      */
   2601     public String getActiveApnHost(String apnType) {
   2602         return mDcTracker.getActiveApnString(apnType);
   2603     }
   2604 
   2605     /**
   2606      * Return the LinkProperties for the named apn or null if not available
   2607      */
   2608     public LinkProperties getLinkProperties(String apnType) {
   2609         return mDcTracker.getLinkProperties(apnType);
   2610     }
   2611 
   2612     /**
   2613      * Return the NetworkCapabilities
   2614      */
   2615     public NetworkCapabilities getNetworkCapabilities(String apnType) {
   2616         return mDcTracker.getNetworkCapabilities(apnType);
   2617     }
   2618 
   2619     /**
   2620      * Report on whether data connectivity is allowed.
   2621      */
   2622     public boolean isDataConnectivityPossible() {
   2623         return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
   2624     }
   2625 
   2626     /**
   2627      * Report on whether data connectivity is allowed for an APN.
   2628      */
   2629     public boolean isDataConnectivityPossible(String apnType) {
   2630         return ((mDcTracker != null) &&
   2631                 (mDcTracker.isDataPossible(apnType)));
   2632     }
   2633 
   2634 
   2635     /**
   2636      * Action set from carrier signalling broadcast receivers to enable/disable metered apns.
   2637      */
   2638     public void carrierActionSetMeteredApnsEnabled(boolean enabled) {
   2639         if(mDcTracker != null) {
   2640             mDcTracker.setApnsEnabledByCarrier(enabled);
   2641         }
   2642     }
   2643 
   2644     /**
   2645      * Action set from carrier signalling broadcast receivers to enable/disable radio
   2646      */
   2647     public void carrierActionSetRadioEnabled(boolean enabled) {
   2648         if(mDcTracker != null) {
   2649             mDcTracker.carrierActionSetRadioEnabled(enabled);
   2650         }
   2651     }
   2652 
   2653     /**
   2654      * Notify registrants of a new ringing Connection.
   2655      * Subclasses of Phone probably want to replace this with a
   2656      * version scoped to their packages
   2657      */
   2658     public void notifyNewRingingConnectionP(Connection cn) {
   2659         if (!mIsVoiceCapable)
   2660             return;
   2661         AsyncResult ar = new AsyncResult(null, cn, null);
   2662         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
   2663     }
   2664 
   2665     /**
   2666      * Notify registrants of a new unknown connection.
   2667      */
   2668     public void notifyUnknownConnectionP(Connection cn) {
   2669         mUnknownConnectionRegistrants.notifyResult(cn);
   2670     }
   2671 
   2672     /**
   2673      * Notify registrants if phone is video capable.
   2674      */
   2675     public void notifyForVideoCapabilityChanged(boolean isVideoCallCapable) {
   2676         // Cache the current video capability so that we don't lose the information.
   2677         mIsVideoCapable = isVideoCallCapable;
   2678 
   2679         AsyncResult ar = new AsyncResult(null, isVideoCallCapable, null);
   2680         mVideoCapabilityChangedRegistrants.notifyRegistrants(ar);
   2681     }
   2682 
   2683     /**
   2684      * Notify registrants of a RING event.
   2685      */
   2686     private void notifyIncomingRing() {
   2687         if (!mIsVoiceCapable)
   2688             return;
   2689         AsyncResult ar = new AsyncResult(null, this, null);
   2690         mIncomingRingRegistrants.notifyRegistrants(ar);
   2691     }
   2692 
   2693     /**
   2694      * Send the incoming call Ring notification if conditions are right.
   2695      */
   2696     private void sendIncomingCallRingNotification(int token) {
   2697         if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
   2698                 (token == mCallRingContinueToken)) {
   2699             Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
   2700             notifyIncomingRing();
   2701             sendMessageDelayed(
   2702                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
   2703         } else {
   2704             Rlog.d(LOG_TAG, "Ignoring ring notification request,"
   2705                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
   2706                     + " token=" + token
   2707                     + " mCallRingContinueToken=" + mCallRingContinueToken
   2708                     + " mIsVoiceCapable=" + mIsVoiceCapable);
   2709         }
   2710     }
   2711 
   2712     /**
   2713      * TODO: Adding a function for each property is not good.
   2714      * A fucntion of type getPhoneProp(propType) where propType is an
   2715      * enum of GSM+CDMA+LTE props would be a better approach.
   2716      *
   2717      * Get "Restriction of menu options for manual PLMN selection" bit
   2718      * status from EF_CSP data, this belongs to "Value Added Services Group".
   2719      * @return true if this bit is set or EF_CSP data is unavailable,
   2720      * false otherwise
   2721      */
   2722     public boolean isCspPlmnEnabled() {
   2723         return false;
   2724     }
   2725 
   2726     /**
   2727      * Return an interface to retrieve the ISIM records for IMS, if available.
   2728      * @return the interface to retrieve the ISIM records, or null if not supported
   2729      */
   2730     public IsimRecords getIsimRecords() {
   2731         Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
   2732         return null;
   2733     }
   2734 
   2735     /**
   2736      * Retrieves the MSISDN from the UICC. For GSM/UMTS phones, this is equivalent to
   2737      * {@link #getLine1Number()}. For CDMA phones, {@link #getLine1Number()} returns
   2738      * the MDN, so this method is provided to return the MSISDN on CDMA/LTE phones.
   2739      */
   2740     public String getMsisdn() {
   2741         return null;
   2742     }
   2743 
   2744     /**
   2745      * Get the current for the default apn DataState. No change notification
   2746      * exists at this interface -- use
   2747      * {@link android.telephony.PhoneStateListener} instead.
   2748      */
   2749     public PhoneConstants.DataState getDataConnectionState() {
   2750         return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
   2751     }
   2752 
   2753     public void notifyCallForwardingIndicator() {
   2754     }
   2755 
   2756     public void notifyDataConnectionFailed(String reason, String apnType) {
   2757         mNotifier.notifyDataConnectionFailed(this, reason, apnType);
   2758     }
   2759 
   2760     public void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
   2761             String failCause) {
   2762         mNotifier.notifyPreciseDataConnectionFailed(this, reason, apnType, apn, failCause);
   2763     }
   2764 
   2765     /**
   2766      * Return if the current radio is LTE on CDMA. This
   2767      * is a tri-state return value as for a period of time
   2768      * the mode may be unknown.
   2769      *
   2770      * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
   2771      * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
   2772      */
   2773     public int getLteOnCdmaMode() {
   2774         return mCi.getLteOnCdmaMode();
   2775     }
   2776 
   2777     /**
   2778      * Sets the SIM voice message waiting indicator records.
   2779      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
   2780      * @param countWaiting The number of messages waiting, if known. Use
   2781      *                     -1 to indicate that an unknown number of
   2782      *                      messages are waiting
   2783      */
   2784     public void setVoiceMessageWaiting(int line, int countWaiting) {
   2785         // This function should be overridden by class GsmCdmaPhone.
   2786         Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
   2787     }
   2788 
   2789     /**
   2790      * Gets the USIM service table from the UICC, if present and available.
   2791      * @return an interface to the UsimServiceTable record, or null if not available
   2792      */
   2793     public UsimServiceTable getUsimServiceTable() {
   2794         IccRecords r = mIccRecords.get();
   2795         return (r != null) ? r.getUsimServiceTable() : null;
   2796     }
   2797 
   2798     /**
   2799      * Gets the Uicc card corresponding to this phone.
   2800      * @return the UiccCard object corresponding to the phone ID.
   2801      */
   2802     public UiccCard getUiccCard() {
   2803         return mUiccController.getUiccCard(mPhoneId);
   2804     }
   2805 
   2806     /**
   2807      * Get P-CSCF address from PCO after data connection is established or modified.
   2808      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
   2809      */
   2810     public String[] getPcscfAddress(String apnType) {
   2811         return mDcTracker.getPcscfAddress(apnType);
   2812     }
   2813 
   2814     /**
   2815      * Set IMS registration state
   2816      */
   2817     public void setImsRegistrationState(boolean registered) {
   2818     }
   2819 
   2820     /**
   2821      * Return an instance of a IMS phone
   2822      */
   2823     public Phone getImsPhone() {
   2824         return mImsPhone;
   2825     }
   2826 
   2827     /**
   2828      * Return if UT capability of ImsPhone is enabled or not
   2829      */
   2830     public boolean isUtEnabled() {
   2831         return false;
   2832     }
   2833 
   2834     public void dispose() {
   2835     }
   2836 
   2837     private void updateImsPhone() {
   2838         Rlog.d(LOG_TAG, "updateImsPhone"
   2839                 + " mImsServiceReady=" + mImsServiceReady);
   2840 
   2841         if (mImsServiceReady && (mImsPhone == null)) {
   2842             mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
   2843             CallManager.getInstance().registerPhone(mImsPhone);
   2844             mImsPhone.registerForSilentRedial(
   2845                     this, EVENT_INITIATE_SILENT_REDIAL, null);
   2846         } else if (!mImsServiceReady && (mImsPhone != null)) {
   2847             CallManager.getInstance().unregisterPhone(mImsPhone);
   2848             mImsPhone.unregisterForSilentRedial(this);
   2849 
   2850             mImsPhone.dispose();
   2851             // Potential GC issue if someone keeps a reference to ImsPhone.
   2852             // However: this change will make sure that such a reference does
   2853             // not access functions through NULL pointer.
   2854             //mImsPhone.removeReferences();
   2855             mImsPhone = null;
   2856         }
   2857     }
   2858 
   2859     /**
   2860      * Dials a number.
   2861      *
   2862      * @param dialString The number to dial.
   2863      * @param uusInfo The UUSInfo.
   2864      * @param videoState The video state for the call.
   2865      * @param intentExtras Extras from the original CALL intent.
   2866      * @return The Connection.
   2867      * @throws CallStateException
   2868      */
   2869     protected Connection dialInternal(
   2870             String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
   2871             throws CallStateException {
   2872         // dialInternal shall be overriden by GsmCdmaPhone
   2873         return null;
   2874     }
   2875 
   2876     /*
   2877      * Returns the subscription id.
   2878      */
   2879     public int getSubId() {
   2880         return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhoneId);
   2881     }
   2882 
   2883     /**
   2884      * Returns the phone id.
   2885      */
   2886     public int getPhoneId() {
   2887         return mPhoneId;
   2888     }
   2889 
   2890     /**
   2891      * Return the service state of mImsPhone if it is STATE_IN_SERVICE
   2892      * otherwise return the current voice service state
   2893      */
   2894     public int getVoicePhoneServiceState() {
   2895         Phone imsPhone = mImsPhone;
   2896         if (imsPhone != null
   2897                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
   2898             return ServiceState.STATE_IN_SERVICE;
   2899         }
   2900         return getServiceState().getState();
   2901     }
   2902 
   2903     /**
   2904      * Override the service provider name and the operator name for the current ICCID.
   2905      */
   2906     public boolean setOperatorBrandOverride(String brand) {
   2907         return false;
   2908     }
   2909 
   2910     /**
   2911      * Override the roaming indicator for the current ICCID.
   2912      */
   2913     public boolean setRoamingOverride(List<String> gsmRoamingList,
   2914             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
   2915             List<String> cdmaNonRoamingList) {
   2916         String iccId = getIccSerialNumber();
   2917         if (TextUtils.isEmpty(iccId)) {
   2918             return false;
   2919         }
   2920 
   2921         setRoamingOverrideHelper(gsmRoamingList, GSM_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
   2922         setRoamingOverrideHelper(gsmNonRoamingList, GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
   2923         setRoamingOverrideHelper(cdmaRoamingList, CDMA_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
   2924         setRoamingOverrideHelper(cdmaNonRoamingList, CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
   2925 
   2926         // Refresh.
   2927         ServiceStateTracker tracker = getServiceStateTracker();
   2928         if (tracker != null) {
   2929             tracker.pollState();
   2930         }
   2931         return true;
   2932     }
   2933 
   2934     private void setRoamingOverrideHelper(List<String> list, String prefix, String iccId) {
   2935         SharedPreferences.Editor spEditor =
   2936                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
   2937         String key = prefix + iccId;
   2938         if (list == null || list.isEmpty()) {
   2939             spEditor.remove(key).commit();
   2940         } else {
   2941             spEditor.putStringSet(key, new HashSet<String>(list)).commit();
   2942         }
   2943     }
   2944 
   2945     public boolean isMccMncMarkedAsRoaming(String mccMnc) {
   2946         return getRoamingOverrideHelper(GSM_ROAMING_LIST_OVERRIDE_PREFIX, mccMnc);
   2947     }
   2948 
   2949     public boolean isMccMncMarkedAsNonRoaming(String mccMnc) {
   2950         return getRoamingOverrideHelper(GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX, mccMnc);
   2951     }
   2952 
   2953     public boolean isSidMarkedAsRoaming(int SID) {
   2954         return getRoamingOverrideHelper(CDMA_ROAMING_LIST_OVERRIDE_PREFIX,
   2955                 Integer.toString(SID));
   2956     }
   2957 
   2958     public boolean isSidMarkedAsNonRoaming(int SID) {
   2959         return getRoamingOverrideHelper(CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX,
   2960                 Integer.toString(SID));
   2961     }
   2962 
   2963     /**
   2964      * Query the IMS Registration Status.
   2965      *
   2966      * @return true if IMS is Registered
   2967      */
   2968     public boolean isImsRegistered() {
   2969         Phone imsPhone = mImsPhone;
   2970         boolean isImsRegistered = false;
   2971         if (imsPhone != null) {
   2972             isImsRegistered = imsPhone.isImsRegistered();
   2973         } else {
   2974             ServiceStateTracker sst = getServiceStateTracker();
   2975             if (sst != null) {
   2976                 isImsRegistered = sst.isImsRegistered();
   2977             }
   2978         }
   2979         Rlog.d(LOG_TAG, "isImsRegistered =" + isImsRegistered);
   2980         return isImsRegistered;
   2981     }
   2982 
   2983     /**
   2984      * Get Wifi Calling Feature Availability
   2985      */
   2986     public boolean isWifiCallingEnabled() {
   2987         Phone imsPhone = mImsPhone;
   2988         boolean isWifiCallingEnabled = false;
   2989         if (imsPhone != null) {
   2990             isWifiCallingEnabled = imsPhone.isWifiCallingEnabled();
   2991         }
   2992         Rlog.d(LOG_TAG, "isWifiCallingEnabled =" + isWifiCallingEnabled);
   2993         return isWifiCallingEnabled;
   2994     }
   2995 
   2996     /**
   2997      * Get Volte Feature Availability
   2998      */
   2999     public boolean isVolteEnabled() {
   3000         Phone imsPhone = mImsPhone;
   3001         boolean isVolteEnabled = false;
   3002         if (imsPhone != null) {
   3003             isVolteEnabled = imsPhone.isVolteEnabled();
   3004         }
   3005         Rlog.d(LOG_TAG, "isImsRegistered =" + isVolteEnabled);
   3006         return isVolteEnabled;
   3007     }
   3008 
   3009     private boolean getRoamingOverrideHelper(String prefix, String key) {
   3010         String iccId = getIccSerialNumber();
   3011         if (TextUtils.isEmpty(iccId) || TextUtils.isEmpty(key)) {
   3012             return false;
   3013         }
   3014 
   3015         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
   3016         Set<String> value = sp.getStringSet(prefix + iccId, null);
   3017         if (value == null) {
   3018             return false;
   3019         }
   3020         return value.contains(key);
   3021     }
   3022 
   3023     /**
   3024      * Is Radio Present on the device and is it accessible
   3025      */
   3026     public boolean isRadioAvailable() {
   3027         return mCi.getRadioState().isAvailable();
   3028     }
   3029 
   3030     /**
   3031      * Is Radio turned on
   3032      */
   3033     public boolean isRadioOn() {
   3034         return mCi.getRadioState().isOn();
   3035     }
   3036 
   3037     /**
   3038      * shutdown Radio gracefully
   3039      */
   3040     public void shutdownRadio() {
   3041         getServiceStateTracker().requestShutdown();
   3042     }
   3043 
   3044     /**
   3045      * Return true if the device is shutting down.
   3046      */
   3047     public boolean isShuttingDown() {
   3048         return getServiceStateTracker().isDeviceShuttingDown();
   3049     }
   3050 
   3051     /**
   3052      *  Set phone radio capability
   3053      *
   3054      *  @param rc the phone radio capability defined in
   3055      *         RadioCapability. It's a input object used to transfer parameter to logic modem
   3056      *  @param response Callback message.
   3057      */
   3058     public void setRadioCapability(RadioCapability rc, Message response) {
   3059         mCi.setRadioCapability(rc, response);
   3060     }
   3061 
   3062     /**
   3063      *  Get phone radio access family
   3064      *
   3065      *  @return a bit mask to identify the radio access family.
   3066      */
   3067     public int getRadioAccessFamily() {
   3068         final RadioCapability rc = getRadioCapability();
   3069         return (rc == null ? RadioAccessFamily.RAF_UNKNOWN : rc.getRadioAccessFamily());
   3070     }
   3071 
   3072     /**
   3073      *  Get the associated data modems Id.
   3074      *
   3075      *  @return a String containing the id of the data modem
   3076      */
   3077     public String getModemUuId() {
   3078         final RadioCapability rc = getRadioCapability();
   3079         return (rc == null ? "" : rc.getLogicalModemUuid());
   3080     }
   3081 
   3082     /**
   3083      *  Get phone radio capability
   3084      *
   3085      *  @return the capability of the radio defined in RadioCapability
   3086      */
   3087     public RadioCapability getRadioCapability() {
   3088         return mRadioCapability.get();
   3089     }
   3090 
   3091     /**
   3092      *  The RadioCapability has changed. This comes up from the RIL and is called when radios first
   3093      *  become available or after a capability switch.  The flow is we use setRadioCapability to
   3094      *  request a change with the RIL and get an UNSOL response with the new data which gets set
   3095      *  here.
   3096      *
   3097      *  @param rc the phone radio capability currently in effect for this phone.
   3098      */
   3099     public void radioCapabilityUpdated(RadioCapability rc) {
   3100         // Called when radios first become available or after a capability switch
   3101         // Update the cached value
   3102         mRadioCapability.set(rc);
   3103 
   3104         if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
   3105             sendSubscriptionSettings(true);
   3106         }
   3107     }
   3108 
   3109     public void sendSubscriptionSettings(boolean restoreNetworkSelection) {
   3110         // Send settings down
   3111         int type = PhoneFactory.calculatePreferredNetworkType(mContext, getSubId());
   3112         setPreferredNetworkType(type, null);
   3113 
   3114         if (restoreNetworkSelection) {
   3115             restoreSavedNetworkSelection(null);
   3116         }
   3117     }
   3118 
   3119     protected void setPreferredNetworkTypeIfSimLoaded() {
   3120         int subId = getSubId();
   3121         if (SubscriptionManager.isValidSubscriptionId(subId)) {
   3122             int type = PhoneFactory.calculatePreferredNetworkType(mContext, getSubId());
   3123             setPreferredNetworkType(type, null);
   3124         }
   3125     }
   3126 
   3127     /**
   3128      * Registers the handler when phone radio  capability is changed.
   3129      *
   3130      * @param h Handler for notification message.
   3131      * @param what User-defined message code.
   3132      * @param obj User object.
   3133      */
   3134     public void registerForRadioCapabilityChanged(Handler h, int what, Object obj) {
   3135         mCi.registerForRadioCapabilityChanged(h, what, obj);
   3136     }
   3137 
   3138     /**
   3139      * Unregister for notifications when phone radio type and access technology is changed.
   3140      *
   3141      * @param h Handler to be removed from the registrant list.
   3142      */
   3143     public void unregisterForRadioCapabilityChanged(Handler h) {
   3144         mCi.unregisterForRadioCapabilityChanged(this);
   3145     }
   3146 
   3147     /**
   3148      * Determines if  IMS is enabled for call.
   3149      *
   3150      * @return {@code true} if IMS calling is enabled.
   3151      */
   3152     public boolean isImsUseEnabled() {
   3153         boolean imsUseEnabled =
   3154                 ((ImsManager.isVolteEnabledByPlatform(mContext) &&
   3155                 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mContext)) ||
   3156                 (ImsManager.isWfcEnabledByPlatform(mContext) &&
   3157                 ImsManager.isWfcEnabledByUser(mContext)) &&
   3158                 ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext));
   3159         return imsUseEnabled;
   3160     }
   3161 
   3162     /**
   3163      * Determines if video calling is enabled for the phone.
   3164      *
   3165      * @return {@code true} if video calling is enabled, {@code false} otherwise.
   3166      */
   3167     public boolean isVideoEnabled() {
   3168         Phone imsPhone = mImsPhone;
   3169         if ((imsPhone != null)
   3170                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
   3171             return imsPhone.isVideoEnabled();
   3172         }
   3173         return false;
   3174     }
   3175 
   3176     /**
   3177      * Returns the status of Link Capacity Estimation (LCE) service.
   3178      */
   3179     public int getLceStatus() {
   3180         return mLceStatus;
   3181     }
   3182 
   3183     /**
   3184      * Returns the modem activity information
   3185      */
   3186     public void getModemActivityInfo(Message response)  {
   3187         mCi.getModemActivityInfo(response);
   3188     }
   3189 
   3190     /**
   3191      * Starts LCE service after radio becomes available.
   3192      * LCE service state may get destroyed on the modem when radio becomes unavailable.
   3193      */
   3194     public void startLceAfterRadioIsAvailable() {
   3195         mCi.startLceService(DEFAULT_REPORT_INTERVAL_MS, LCE_PULL_MODE,
   3196                 obtainMessage(EVENT_CONFIG_LCE));
   3197     }
   3198 
   3199     /**
   3200      * Set allowed carriers
   3201      */
   3202     public void setAllowedCarriers(List<CarrierIdentifier> carriers, Message response) {
   3203         mCi.setAllowedCarriers(carriers, response);
   3204     }
   3205 
   3206     /**
   3207      * Get allowed carriers
   3208      */
   3209     public void getAllowedCarriers(Message response) {
   3210         mCi.getAllowedCarriers(response);
   3211     }
   3212 
   3213     /**
   3214      * Returns the locale based on the carrier properties (such as {@code ro.carrier}) and
   3215      * SIM preferences.
   3216      */
   3217     public Locale getLocaleFromSimAndCarrierPrefs() {
   3218         final IccRecords records = mIccRecords.get();
   3219         if (records != null && records.getSimLanguage() != null) {
   3220             return new Locale(records.getSimLanguage());
   3221         }
   3222 
   3223         return getLocaleFromCarrierProperties(mContext);
   3224     }
   3225 
   3226     public void updateDataConnectionTracker() {
   3227         mDcTracker.update();
   3228     }
   3229 
   3230     public void setInternalDataEnabled(boolean enable, Message onCompleteMsg) {
   3231         mDcTracker.setInternalDataEnabled(enable, onCompleteMsg);
   3232     }
   3233 
   3234     public boolean updateCurrentCarrierInProvider() {
   3235         return false;
   3236     }
   3237 
   3238     public void registerForAllDataDisconnected(Handler h, int what, Object obj) {
   3239         mDcTracker.registerForAllDataDisconnected(h, what, obj);
   3240     }
   3241 
   3242     public void unregisterForAllDataDisconnected(Handler h) {
   3243         mDcTracker.unregisterForAllDataDisconnected(h);
   3244     }
   3245 
   3246     public void registerForDataEnabledChanged(Handler h, int what, Object obj) {
   3247         mDcTracker.registerForDataEnabledChanged(h, what, obj);
   3248     }
   3249 
   3250     public void unregisterForDataEnabledChanged(Handler h) {
   3251         mDcTracker.unregisterForDataEnabledChanged(h);
   3252     }
   3253 
   3254     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
   3255         return null;
   3256     }
   3257 
   3258     protected boolean isMatchGid(String gid) {
   3259         String gid1 = getGroupIdLevel1();
   3260         int gidLength = gid.length();
   3261         if (!TextUtils.isEmpty(gid1) && (gid1.length() >= gidLength)
   3262                 && gid1.substring(0, gidLength).equalsIgnoreCase(gid)) {
   3263             return true;
   3264         }
   3265         return false;
   3266     }
   3267 
   3268     public static void checkWfcWifiOnlyModeBeforeDial(Phone imsPhone, Context context)
   3269             throws CallStateException {
   3270         if (imsPhone == null || !imsPhone.isWifiCallingEnabled()) {
   3271             boolean wfcWiFiOnly = (ImsManager.isWfcEnabledByPlatform(context) &&
   3272                     ImsManager.isWfcEnabledByUser(context) &&
   3273                     (ImsManager.getWfcMode(context) ==
   3274                             ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY));
   3275             if (wfcWiFiOnly) {
   3276                 throw new CallStateException(
   3277                         CallStateException.ERROR_DISCONNECTED,
   3278                         "WFC Wi-Fi Only Mode: IMS not registered");
   3279             }
   3280         }
   3281     }
   3282 
   3283     public void startRingbackTone() {
   3284     }
   3285 
   3286     public void stopRingbackTone() {
   3287     }
   3288 
   3289     public void callEndCleanupHandOverCallIfAny() {
   3290     }
   3291 
   3292     public void cancelUSSD() {
   3293     }
   3294 
   3295     /**
   3296      * Set boolean broadcastEmergencyCallStateChanges
   3297      */
   3298     public abstract void setBroadcastEmergencyCallStateChanges(boolean broadcast);
   3299 
   3300     public abstract void sendEmergencyCallStateChange(boolean callActive);
   3301 
   3302     /**
   3303      * This function returns the parent phone of the current phone. It is applicable
   3304      * only for IMS phone (function is overridden by ImsPhone). For others the phone
   3305      * object itself is returned.
   3306      * @return
   3307      */
   3308     public Phone getDefaultPhone() {
   3309         return this;
   3310     }
   3311 
   3312     public long getVtDataUsage() {
   3313         if (mImsPhone == null) return 0;
   3314         return mImsPhone.getVtDataUsage();
   3315     }
   3316 
   3317     /**
   3318      * Policy control of data connection. Usually used when we hit data limit.
   3319      * @param enabled True if enabling the data, otherwise disabling.
   3320      */
   3321     public void setPolicyDataEnabled(boolean enabled) {
   3322         mDcTracker.setPolicyDataEnabled(enabled);
   3323     }
   3324 
   3325     /**
   3326      * SIP URIs aliased to the current subscriber given by the IMS implementation.
   3327      * Applicable only on IMS; used in absence of line1number.
   3328      * @return array of SIP URIs aliased to the current subscriber
   3329      */
   3330     public Uri[] getCurrentSubscriberUris() {
   3331         return null;
   3332     }
   3333 
   3334     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   3335         pw.println("Phone: subId=" + getSubId());
   3336         pw.println(" mPhoneId=" + mPhoneId);
   3337         pw.println(" mCi=" + mCi);
   3338         pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
   3339         pw.println(" mDcTracker=" + mDcTracker);
   3340         pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
   3341         pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
   3342         pw.println(" mCallRingDelay=" + mCallRingDelay);
   3343         pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
   3344         pw.println(" mIccRecords=" + mIccRecords.get());
   3345         pw.println(" mUiccApplication=" + mUiccApplication.get());
   3346         pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
   3347         pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
   3348         pw.flush();
   3349         pw.println(" mLooper=" + mLooper);
   3350         pw.println(" mContext=" + mContext);
   3351         pw.println(" mNotifier=" + mNotifier);
   3352         pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
   3353         pw.println(" mUnitTestMode=" + mUnitTestMode);
   3354         pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
   3355         pw.println(" getUnitTestMode()=" + getUnitTestMode());
   3356         pw.println(" getState()=" + getState());
   3357         pw.println(" getIccSerialNumber()=" + getIccSerialNumber());
   3358         pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
   3359         pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
   3360         pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
   3361         pw.println(" isInEmergencyCall()=" + isInEmergencyCall());
   3362         pw.flush();
   3363         pw.println(" isInEcm()=" + isInEcm());
   3364         pw.println(" getPhoneName()=" + getPhoneName());
   3365         pw.println(" getPhoneType()=" + getPhoneType());
   3366         pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
   3367         pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
   3368         pw.println(" isDataConnectivityPossible()=" + isDataConnectivityPossible());
   3369         pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
   3370         pw.flush();
   3371         pw.println("++++++++++++++++++++++++++++++++");
   3372 
   3373         if (mImsPhone != null) {
   3374             try {
   3375                 mImsPhone.dump(fd, pw, args);
   3376             } catch (Exception e) {
   3377                 e.printStackTrace();
   3378             }
   3379 
   3380             pw.flush();
   3381             pw.println("++++++++++++++++++++++++++++++++");
   3382         }
   3383 
   3384         if (mDcTracker != null) {
   3385             try {
   3386                 mDcTracker.dump(fd, pw, args);
   3387             } catch (Exception e) {
   3388                 e.printStackTrace();
   3389             }
   3390 
   3391             pw.flush();
   3392             pw.println("++++++++++++++++++++++++++++++++");
   3393         }
   3394 
   3395         if (getServiceStateTracker() != null) {
   3396             try {
   3397                 getServiceStateTracker().dump(fd, pw, args);
   3398             } catch (Exception e) {
   3399                 e.printStackTrace();
   3400             }
   3401 
   3402             pw.flush();
   3403             pw.println("++++++++++++++++++++++++++++++++");
   3404         }
   3405 
   3406         if (getCallTracker() != null) {
   3407             try {
   3408                 getCallTracker().dump(fd, pw, args);
   3409             } catch (Exception e) {
   3410                 e.printStackTrace();
   3411             }
   3412 
   3413             pw.flush();
   3414             pw.println("++++++++++++++++++++++++++++++++");
   3415         }
   3416 
   3417         if (mCi != null && mCi instanceof RIL) {
   3418             try {
   3419                 ((RIL)mCi).dump(fd, pw, args);
   3420             } catch (Exception e) {
   3421                 e.printStackTrace();
   3422             }
   3423 
   3424             pw.flush();
   3425             pw.println("++++++++++++++++++++++++++++++++");
   3426         }
   3427     }
   3428 }
   3429