Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony;
     18 
     19 import static android.provider.Telephony.ServiceStateTable.getContentValuesForServiceState;
     20 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
     21 
     22 import static com.android.internal.telephony.CarrierActionAgent.CARRIER_ACTION_SET_RADIO_ENABLED;
     23 
     24 import android.app.AlarmManager;
     25 import android.app.Notification;
     26 import android.app.NotificationManager;
     27 import android.app.PendingIntent;
     28 import android.content.BroadcastReceiver;
     29 import android.content.ContentResolver;
     30 import android.content.Context;
     31 import android.content.Intent;
     32 import android.content.IntentFilter;
     33 import android.content.SharedPreferences;
     34 import android.content.res.Resources;
     35 import android.hardware.radio.V1_0.CellInfoType;
     36 import android.os.AsyncResult;
     37 import android.os.BaseBundle;
     38 import android.os.Build;
     39 import android.os.Handler;
     40 import android.os.HandlerThread;
     41 import android.os.Message;
     42 import android.os.PersistableBundle;
     43 import android.os.Registrant;
     44 import android.os.RegistrantList;
     45 import android.os.SystemClock;
     46 import android.os.SystemProperties;
     47 import android.os.UserHandle;
     48 import android.os.WorkSource;
     49 import android.preference.PreferenceManager;
     50 import android.provider.Settings;
     51 import android.telephony.AccessNetworkConstants;
     52 import android.telephony.AccessNetworkConstants.AccessNetworkType;
     53 import android.telephony.CarrierConfigManager;
     54 import android.telephony.CellIdentity;
     55 import android.telephony.CellIdentityCdma;
     56 import android.telephony.CellIdentityGsm;
     57 import android.telephony.CellIdentityLte;
     58 import android.telephony.CellIdentityTdscdma;
     59 import android.telephony.CellIdentityWcdma;
     60 import android.telephony.CellInfo;
     61 import android.telephony.CellInfoGsm;
     62 import android.telephony.CellInfoLte;
     63 import android.telephony.CellInfoWcdma;
     64 import android.telephony.CellLocation;
     65 import android.telephony.DataSpecificRegistrationStates;
     66 import android.telephony.NetworkRegistrationState;
     67 import android.telephony.PhysicalChannelConfig;
     68 import android.telephony.Rlog;
     69 import android.telephony.ServiceState;
     70 import android.telephony.SignalStrength;
     71 import android.telephony.SubscriptionManager;
     72 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
     73 import android.telephony.TelephonyManager;
     74 import android.telephony.VoiceSpecificRegistrationStates;
     75 import android.telephony.cdma.CdmaCellLocation;
     76 import android.telephony.gsm.GsmCellLocation;
     77 import android.text.TextUtils;
     78 import android.util.EventLog;
     79 import android.util.LocalLog;
     80 import android.util.Pair;
     81 import android.util.SparseArray;
     82 import android.util.StatsLog;
     83 import android.util.TimeUtils;
     84 
     85 import com.android.internal.annotations.VisibleForTesting;
     86 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
     87 import com.android.internal.telephony.cdma.EriInfo;
     88 import com.android.internal.telephony.dataconnection.DcTracker;
     89 import com.android.internal.telephony.dataconnection.TransportManager;
     90 import com.android.internal.telephony.metrics.TelephonyMetrics;
     91 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
     92 import com.android.internal.telephony.uicc.IccRecords;
     93 import com.android.internal.telephony.uicc.RuimRecords;
     94 import com.android.internal.telephony.uicc.SIMRecords;
     95 import com.android.internal.telephony.uicc.UiccCardApplication;
     96 import com.android.internal.telephony.uicc.UiccController;
     97 import com.android.internal.telephony.util.NotificationChannelController;
     98 import com.android.internal.telephony.util.TimeStampedValue;
     99 import com.android.internal.util.ArrayUtils;
    100 import com.android.internal.util.IndentingPrintWriter;
    101 
    102 import java.io.FileDescriptor;
    103 import java.io.PrintWriter;
    104 import java.util.ArrayList;
    105 import java.util.Arrays;
    106 import java.util.List;
    107 import java.util.TimeZone;
    108 import java.util.concurrent.atomic.AtomicInteger;
    109 import java.util.regex.PatternSyntaxException;
    110 
    111 /**
    112  * {@hide}
    113  */
    114 public class ServiceStateTracker extends Handler {
    115     static final String LOG_TAG = "SST";
    116     static final boolean DBG = true;
    117     private static final boolean VDBG = false;  // STOPSHIP if true
    118 
    119     private static final String PROP_FORCE_ROAMING = "telephony.test.forceRoaming";
    120 
    121     private CommandsInterface mCi;
    122     private UiccController mUiccController = null;
    123     private UiccCardApplication mUiccApplcation = null;
    124     private IccRecords mIccRecords = null;
    125 
    126     private boolean mVoiceCapable;
    127 
    128     public ServiceState mSS;
    129     private ServiceState mNewSS;
    130 
    131     private static final long LAST_CELL_INFO_LIST_MAX_AGE_MS = 2000;
    132     private long mLastCellInfoListTime;
    133     private List<CellInfo> mLastCellInfoList = null;
    134     private List<PhysicalChannelConfig> mLastPhysicalChannelConfigList = null;
    135 
    136     private SignalStrength mSignalStrength;
    137 
    138     // TODO - this should not be public, right now used externally GsmConnetion.
    139     public RestrictedState mRestrictedState;
    140 
    141     /**
    142      * A unique identifier to track requests associated with a poll
    143      * and ignore stale responses.  The value is a count-down of
    144      * expected responses in this pollingContext.
    145      */
    146     @VisibleForTesting
    147     public int[] mPollingContext;
    148     private boolean mDesiredPowerState;
    149 
    150     /**
    151      * By default, strength polling is enabled.  However, if we're
    152      * getting unsolicited signal strength updates from the radio, set
    153      * value to true and don't bother polling any more.
    154      */
    155     private boolean mDontPollSignalStrength = false;
    156 
    157     private RegistrantList mVoiceRoamingOnRegistrants = new RegistrantList();
    158     private RegistrantList mVoiceRoamingOffRegistrants = new RegistrantList();
    159     private RegistrantList mDataRoamingOnRegistrants = new RegistrantList();
    160     private RegistrantList mDataRoamingOffRegistrants = new RegistrantList();
    161     protected RegistrantList mAttachedRegistrants = new RegistrantList();
    162     protected RegistrantList mDetachedRegistrants = new RegistrantList();
    163     private RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList();
    164     private RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
    165     private RegistrantList mNetworkDetachedRegistrants = new RegistrantList();
    166     private RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
    167     private RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
    168 
    169     /* Radio power off pending flag and tag counter */
    170     private boolean mPendingRadioPowerOffAfterDataOff = false;
    171     private int mPendingRadioPowerOffAfterDataOffTag = 0;
    172 
    173     /** Signal strength poll rate. */
    174     private static final int POLL_PERIOD_MILLIS = 20 * 1000;
    175 
    176     /** Waiting period before recheck gprs and voice registration. */
    177     public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
    178 
    179     /** GSM events */
    180     protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
    181     protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
    182     protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
    183     protected static final int EVENT_POLL_STATE_REGISTRATION           = 4;
    184     protected static final int EVENT_POLL_STATE_GPRS                   = 5;
    185     protected static final int EVENT_POLL_STATE_OPERATOR               = 6;
    186     protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
    187     protected static final int EVENT_NITZ_TIME                         = 11;
    188     protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
    189     protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
    190     protected static final int EVENT_GET_LOC_DONE                      = 15;
    191     protected static final int EVENT_SIM_RECORDS_LOADED                = 16;
    192     protected static final int EVENT_SIM_READY                         = 17;
    193     protected static final int EVENT_LOCATION_UPDATES_ENABLED          = 18;
    194     protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE        = 19;
    195     protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE        = 20;
    196     protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE      = 21;
    197     protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
    198     protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
    199 
    200     /** CDMA events */
    201     protected static final int EVENT_RUIM_READY                        = 26;
    202     protected static final int EVENT_RUIM_RECORDS_LOADED               = 27;
    203     protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION      = 34;
    204     protected static final int EVENT_NV_READY                          = 35;
    205     protected static final int EVENT_ERI_FILE_LOADED                   = 36;
    206     protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE       = 37;
    207     protected static final int EVENT_SET_RADIO_POWER_OFF               = 38;
    208     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED  = 39;
    209     protected static final int EVENT_CDMA_PRL_VERSION_CHANGED          = 40;
    210 
    211     protected static final int EVENT_RADIO_ON                          = 41;
    212     public    static final int EVENT_ICC_CHANGED                       = 42;
    213     protected static final int EVENT_GET_CELL_INFO_LIST                = 43;
    214     protected static final int EVENT_UNSOL_CELL_INFO_LIST              = 44;
    215     protected static final int EVENT_CHANGE_IMS_STATE                  = 45;
    216     protected static final int EVENT_IMS_STATE_CHANGED                 = 46;
    217     protected static final int EVENT_IMS_STATE_DONE                    = 47;
    218     protected static final int EVENT_IMS_CAPABILITY_CHANGED            = 48;
    219     protected static final int EVENT_ALL_DATA_DISCONNECTED             = 49;
    220     protected static final int EVENT_PHONE_TYPE_SWITCHED               = 50;
    221     protected static final int EVENT_RADIO_POWER_FROM_CARRIER          = 51;
    222     protected static final int EVENT_SIM_NOT_INSERTED                  = 52;
    223     protected static final int EVENT_IMS_SERVICE_STATE_CHANGED         = 53;
    224     protected static final int EVENT_RADIO_POWER_OFF_DONE              = 54;
    225     protected static final int EVENT_PHYSICAL_CHANNEL_CONFIG           = 55;
    226 
    227     private class CellInfoResult {
    228         List<CellInfo> list;
    229         Object lockObj = new Object();
    230     }
    231 
    232     /** Reason for registration denial. */
    233     protected static final String REGISTRATION_DENIED_GEN  = "General";
    234     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
    235 
    236     private boolean mImsRegistrationOnOff = false;
    237     private boolean mAlarmSwitch = false;
    238     /** Radio is disabled by carrier. Radio power will not be override if this field is set */
    239     private boolean mRadioDisabledByCarrier = false;
    240     private PendingIntent mRadioOffIntent = null;
    241     private static final String ACTION_RADIO_OFF = "android.intent.action.ACTION_RADIO_OFF";
    242     private boolean mPowerOffDelayNeed = true;
    243     private boolean mDeviceShuttingDown = false;
    244     /** Keep track of SPN display rules, so we only broadcast intent if something changes. */
    245     private boolean mSpnUpdatePending = false;
    246     private String mCurSpn = null;
    247     private String mCurDataSpn = null;
    248     private String mCurPlmn = null;
    249     private boolean mCurShowPlmn = false;
    250     private boolean mCurShowSpn = false;
    251     @VisibleForTesting
    252     public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    253     private int mPrevSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    254 
    255     private boolean mImsRegistered = false;
    256 
    257     private SubscriptionManager mSubscriptionManager;
    258     private SubscriptionController mSubscriptionController;
    259     private final SstSubscriptionsChangedListener mOnSubscriptionsChangedListener =
    260         new SstSubscriptionsChangedListener();
    261 
    262 
    263     private final RatRatcheter mRatRatcheter;
    264 
    265     private final HandlerThread mHandlerThread;
    266     private final LocaleTracker mLocaleTracker;
    267 
    268     private final LocalLog mRoamingLog = new LocalLog(10);
    269     private final LocalLog mAttachLog = new LocalLog(10);
    270     private final LocalLog mPhoneTypeLog = new LocalLog(10);
    271     private final LocalLog mRatLog = new LocalLog(20);
    272     private final LocalLog mRadioPowerLog = new LocalLog(20);
    273 
    274     private class SstSubscriptionsChangedListener extends OnSubscriptionsChangedListener {
    275         public final AtomicInteger mPreviousSubId =
    276                 new AtomicInteger(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
    277 
    278         /**
    279          * Callback invoked when there is any change to any SubscriptionInfo. Typically
    280          * this method would invoke {@link SubscriptionManager#getActiveSubscriptionInfoList}
    281          */
    282         @Override
    283         public void onSubscriptionsChanged() {
    284             if (DBG) log("SubscriptionListener.onSubscriptionInfoChanged");
    285             // Set the network type, in case the radio does not restore it.
    286             int subId = mPhone.getSubId();
    287             ServiceStateTracker.this.mPrevSubId = mPreviousSubId.get();
    288             if (mPreviousSubId.getAndSet(subId) != subId) {
    289                 if (SubscriptionManager.isValidSubscriptionId(subId)) {
    290                     Context context = mPhone.getContext();
    291 
    292                     mPhone.notifyPhoneStateChanged();
    293                     mPhone.notifyCallForwardingIndicator();
    294 
    295                     boolean restoreSelection = !context.getResources().getBoolean(
    296                             com.android.internal.R.bool.skip_restoring_network_selection);
    297                     mPhone.sendSubscriptionSettings(restoreSelection);
    298 
    299                     mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
    300                             ServiceState.rilRadioTechnologyToString(
    301                                     mSS.getRilDataRadioTechnology()));
    302 
    303                     if (mSpnUpdatePending) {
    304                         mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), mCurShowPlmn,
    305                                 mCurPlmn, mCurShowSpn, mCurSpn);
    306                         mSpnUpdatePending = false;
    307                     }
    308 
    309                     // Remove old network selection sharedPreferences since SP key names are now
    310                     // changed to include subId. This will be done only once when upgrading from an
    311                     // older build that did not include subId in the names.
    312                     SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
    313                             context);
    314                     String oldNetworkSelection = sp.getString(
    315                             Phone.NETWORK_SELECTION_KEY, "");
    316                     String oldNetworkSelectionName = sp.getString(
    317                             Phone.NETWORK_SELECTION_NAME_KEY, "");
    318                     String oldNetworkSelectionShort = sp.getString(
    319                             Phone.NETWORK_SELECTION_SHORT_KEY, "");
    320                     if (!TextUtils.isEmpty(oldNetworkSelection) ||
    321                             !TextUtils.isEmpty(oldNetworkSelectionName) ||
    322                             !TextUtils.isEmpty(oldNetworkSelectionShort)) {
    323                         SharedPreferences.Editor editor = sp.edit();
    324                         editor.putString(Phone.NETWORK_SELECTION_KEY + subId,
    325                                 oldNetworkSelection);
    326                         editor.putString(Phone.NETWORK_SELECTION_NAME_KEY + subId,
    327                                 oldNetworkSelectionName);
    328                         editor.putString(Phone.NETWORK_SELECTION_SHORT_KEY + subId,
    329                                 oldNetworkSelectionShort);
    330                         editor.remove(Phone.NETWORK_SELECTION_KEY);
    331                         editor.remove(Phone.NETWORK_SELECTION_NAME_KEY);
    332                         editor.remove(Phone.NETWORK_SELECTION_SHORT_KEY);
    333                         editor.commit();
    334                     }
    335 
    336                     // Once sub id becomes valid, we need to update the service provider name
    337                     // displayed on the UI again. The old SPN update intents sent to
    338                     // MobileSignalController earlier were actually ignored due to invalid sub id.
    339                     updateSpnDisplay();
    340                 }
    341                 // update voicemail count and notify message waiting changed
    342                 mPhone.updateVoiceMail();
    343 
    344                 // cancel notifications if we see SIM_NOT_INSERTED (This happens on bootup before
    345                 // the SIM is first detected and then subsequently on SIM removals)
    346                 if (mSubscriptionController.getSlotIndex(subId)
    347                         == SubscriptionManager.SIM_NOT_INSERTED) {
    348                     // this is handled on the main thread to mitigate racing with setNotification().
    349                     sendMessage(obtainMessage(EVENT_SIM_NOT_INSERTED));
    350                 }
    351             }
    352         }
    353     };
    354 
    355     //Common
    356     private final GsmCdmaPhone mPhone;
    357 
    358     public CellLocation mCellLoc;
    359     private CellLocation mNewCellLoc;
    360     private static final int MS_PER_HOUR = 60 * 60 * 1000;
    361     private final NitzStateMachine mNitzState;
    362     private final ContentResolver mCr;
    363 
    364     //GSM
    365     private int mPreferredNetworkType;
    366     private int mMaxDataCalls = 1;
    367     private int mNewMaxDataCalls = 1;
    368     private int mReasonDataDenied = -1;
    369     private int mNewReasonDataDenied = -1;
    370 
    371     /**
    372      * The code of the rejection cause that is sent by network when the CS
    373      * registration is rejected. It should be shown to the user as a notification.
    374      */
    375     private int mRejectCode;
    376     private int mNewRejectCode;
    377 
    378     /**
    379      * GSM roaming status solely based on TS 27.007 7.2 CREG. Only used by
    380      * handlePollStateResult to store CREG roaming result.
    381      */
    382     private boolean mGsmRoaming = false;
    383     /**
    384      * Data roaming status solely based on TS 27.007 10.1.19 CGREG. Only used by
    385      * handlePollStateResult to store CGREG roaming result.
    386      */
    387     private boolean mDataRoaming = false;
    388     /**
    389      * Mark when service state is in emergency call only mode
    390      */
    391     private boolean mEmergencyOnly = false;
    392     /** Started the recheck process after finding gprs should registered but not. */
    393     private boolean mStartedGprsRegCheck;
    394     /** Already sent the event-log for no gprs register. */
    395     private boolean mReportedGprsNoReg;
    396 
    397     private CarrierServiceStateTracker mCSST;
    398     /**
    399      * The Notification object given to the NotificationManager.
    400      */
    401     private Notification mNotification;
    402     /** Notification type. */
    403     public static final int PS_ENABLED = 1001;            // Access Control blocks data service
    404     public static final int PS_DISABLED = 1002;           // Access Control enables data service
    405     public static final int CS_ENABLED = 1003;            // Access Control blocks all voice/sms service
    406     public static final int CS_DISABLED = 1004;           // Access Control enables all voice/sms service
    407     public static final int CS_NORMAL_ENABLED = 1005;     // Access Control blocks normal voice/sms service
    408     public static final int CS_EMERGENCY_ENABLED = 1006;  // Access Control blocks emergency call service
    409     public static final int CS_REJECT_CAUSE_ENABLED = 2001;     // Notify MM rejection cause
    410     /** Notification id. */
    411     public static final int PS_NOTIFICATION = 888;  // Id to update and cancel PS restricted
    412     public static final int CS_NOTIFICATION = 999;  // Id to update and cancel CS restricted
    413     public static final int CS_REJECT_CAUSE_NOTIFICATION = 111; // Id to update and cancel MM
    414                                                                 // rejection cause
    415 
    416     /** To identify whether EVENT_SIM_READY is received or not */
    417     private boolean mIsSimReady = false;
    418 
    419     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    420         @Override
    421         public void onReceive(Context context, Intent intent) {
    422             if (intent.getAction().equals(
    423                     CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
    424                 onCarrierConfigChanged();
    425                 return;
    426             }
    427 
    428             if (!mPhone.isPhoneTypeGsm()) {
    429                 loge("Ignoring intent " + intent + " received on CDMA phone");
    430                 return;
    431             }
    432 
    433             if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) {
    434                 // update emergency string whenever locale changed
    435                 updateSpnDisplay();
    436             } else if (intent.getAction().equals(ACTION_RADIO_OFF)) {
    437                 mAlarmSwitch = false;
    438                 DcTracker dcTracker = mPhone.mDcTracker;
    439                 powerOffRadioSafely(dcTracker);
    440             }
    441         }
    442     };
    443 
    444     //CDMA
    445     // Min values used to by getOtasp()
    446     public static final String UNACTIVATED_MIN2_VALUE = "000000";
    447     public static final String UNACTIVATED_MIN_VALUE = "1111110111";
    448     // Current Otasp value
    449     private int mCurrentOtaspMode = TelephonyManager.OTASP_UNINITIALIZED;
    450     private int mRoamingIndicator;
    451     private boolean mIsInPrl;
    452     private int mDefaultRoamingIndicator;
    453     /**
    454      * Initially assume no data connection.
    455      */
    456     private int mRegistrationState = -1;
    457     private RegistrantList mCdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
    458     private String mMdn;
    459     private int mHomeSystemId[] = null;
    460     private int mHomeNetworkId[] = null;
    461     private String mMin;
    462     private String mPrlVersion;
    463     private boolean mIsMinInfoReady = false;
    464     private boolean mIsEriTextLoaded = false;
    465     private boolean mIsSubscriptionFromRuim = false;
    466     private CdmaSubscriptionSourceManager mCdmaSSM;
    467     public static final String INVALID_MCC = "000";
    468     public static final String DEFAULT_MNC = "00";
    469     private HbpcdUtils mHbpcdUtils = null;
    470     /* Used only for debugging purposes. */
    471     private String mRegistrationDeniedReason;
    472     private String mCurrentCarrier = null;
    473 
    474     private final TransportManager mTransportManager;
    475     private final SparseArray<NetworkRegistrationManager> mRegStateManagers = new SparseArray<>();
    476 
    477     /* list of LTE EARFCNs (E-UTRA Absolute Radio Frequency Channel Number,
    478      * Reference: 3GPP TS 36.104 5.4.3)
    479      * inclusive ranges for which the lte rsrp boost is applied */
    480     private ArrayList<Pair<Integer, Integer>> mEarfcnPairListForRsrpBoost = null;
    481 
    482     private int mLteRsrpBoost = 0; // offset which is reduced from the rsrp threshold
    483                                    // while calculating signal strength level.
    484     private final Object mLteRsrpBoostLock = new Object();
    485     private static final int INVALID_LTE_EARFCN = -1;
    486 
    487     public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
    488         mNitzState = TelephonyComponentFactory.getInstance().makeNitzStateMachine(phone);
    489         mPhone = phone;
    490         mCi = ci;
    491 
    492         mRatRatcheter = new RatRatcheter(mPhone);
    493         mVoiceCapable = mPhone.getContext().getResources().getBoolean(
    494                 com.android.internal.R.bool.config_voice_capable);
    495         mUiccController = UiccController.getInstance();
    496 
    497         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
    498         mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
    499         mCi.registerForCellInfoList(this, EVENT_UNSOL_CELL_INFO_LIST, null);
    500         mCi.registerForPhysicalChannelConfiguration(this, EVENT_PHYSICAL_CHANNEL_CONFIG, null);
    501 
    502         mSubscriptionController = SubscriptionController.getInstance();
    503         mSubscriptionManager = SubscriptionManager.from(phone.getContext());
    504         mSubscriptionManager
    505                 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
    506         mRestrictedState = new RestrictedState();
    507 
    508         mTransportManager = new TransportManager();
    509 
    510         for (int transportType : mTransportManager.getAvailableTransports()) {
    511             mRegStateManagers.append(transportType, new NetworkRegistrationManager(
    512                     transportType, phone));
    513             mRegStateManagers.get(transportType).registerForNetworkRegistrationStateChanged(
    514                     this, EVENT_NETWORK_STATE_CHANGED, null);
    515         }
    516 
    517         // Create a new handler thread dedicated for locale tracker because the blocking
    518         // getAllCellInfo call requires clients calling from a different thread.
    519         mHandlerThread = new HandlerThread(LocaleTracker.class.getSimpleName());
    520         mHandlerThread.start();
    521         mLocaleTracker = TelephonyComponentFactory.getInstance().makeLocaleTracker(
    522                 mPhone, mHandlerThread.getLooper());
    523 
    524         mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
    525         mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
    526         mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);
    527 
    528         mCr = phone.getContext().getContentResolver();
    529         // system setting property AIRPLANE_MODE_ON is set in Settings.
    530         int airplaneMode = Settings.Global.getInt(mCr, Settings.Global.AIRPLANE_MODE_ON, 0);
    531         int enableCellularOnBoot = Settings.Global.getInt(mCr,
    532                 Settings.Global.ENABLE_CELLULAR_ON_BOOT, 1);
    533         mDesiredPowerState = (enableCellularOnBoot > 0) && ! (airplaneMode > 0);
    534         mRadioPowerLog.log("init : airplane mode = " + airplaneMode + " enableCellularOnBoot = " +
    535                 enableCellularOnBoot);
    536 
    537 
    538         setSignalStrengthDefaultValues();
    539         mPhone.getCarrierActionAgent().registerForCarrierAction(CARRIER_ACTION_SET_RADIO_ENABLED,
    540                 this, EVENT_RADIO_POWER_FROM_CARRIER, null, false);
    541 
    542         // Monitor locale change
    543         Context context = mPhone.getContext();
    544         IntentFilter filter = new IntentFilter();
    545         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
    546         context.registerReceiver(mIntentReceiver, filter);
    547         filter = new IntentFilter();
    548         filter.addAction(ACTION_RADIO_OFF);
    549         context.registerReceiver(mIntentReceiver, filter);
    550         filter = new IntentFilter();
    551         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
    552         context.registerReceiver(mIntentReceiver, filter);
    553 
    554         mPhone.notifyOtaspChanged(TelephonyManager.OTASP_UNINITIALIZED);
    555 
    556         mCi.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
    557         updatePhoneType();
    558 
    559         mCSST = new CarrierServiceStateTracker(phone, this);
    560 
    561         registerForNetworkAttached(mCSST,
    562                 CarrierServiceStateTracker.CARRIER_EVENT_VOICE_REGISTRATION, null);
    563         registerForNetworkDetached(mCSST,
    564                 CarrierServiceStateTracker.CARRIER_EVENT_VOICE_DEREGISTRATION, null);
    565         registerForDataConnectionAttached(mCSST,
    566                 CarrierServiceStateTracker.CARRIER_EVENT_DATA_REGISTRATION, null);
    567         registerForDataConnectionDetached(mCSST,
    568                 CarrierServiceStateTracker.CARRIER_EVENT_DATA_DEREGISTRATION, null);
    569     }
    570 
    571     @VisibleForTesting
    572     public void updatePhoneType() {
    573         // If we are previously voice roaming, we need to notify that roaming status changed before
    574         // we change back to non-roaming.
    575         if (mSS != null && mSS.getVoiceRoaming()) {
    576             mVoiceRoamingOffRegistrants.notifyRegistrants();
    577         }
    578 
    579         // If we are previously data roaming, we need to notify that roaming status changed before
    580         // we change back to non-roaming.
    581         if (mSS != null && mSS.getDataRoaming()) {
    582             mDataRoamingOffRegistrants.notifyRegistrants();
    583         }
    584 
    585         // If we are previously in service, we need to notify that we are out of service now.
    586         if (mSS != null && mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
    587             mNetworkDetachedRegistrants.notifyRegistrants();
    588         }
    589 
    590         // If we are previously in service, we need to notify that we are out of service now.
    591         if (mSS != null && mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE) {
    592             mDetachedRegistrants.notifyRegistrants();
    593         }
    594 
    595         mSS = new ServiceState();
    596         mNewSS = new ServiceState();
    597         mLastCellInfoListTime = 0;
    598         mLastCellInfoList = null;
    599         mSignalStrength = new SignalStrength();
    600         mStartedGprsRegCheck = false;
    601         mReportedGprsNoReg = false;
    602         mMdn = null;
    603         mMin = null;
    604         mPrlVersion = null;
    605         mIsMinInfoReady = false;
    606         mNitzState.handleNetworkUnavailable();
    607 
    608         //cancel any pending pollstate request on voice tech switching
    609         cancelPollState();
    610 
    611         if (mPhone.isPhoneTypeGsm()) {
    612             //clear CDMA registrations first
    613             if (mCdmaSSM != null) {
    614                 mCdmaSSM.dispose(this);
    615             }
    616 
    617             mCi.unregisterForCdmaPrlChanged(this);
    618             mPhone.unregisterForEriFileLoaded(this);
    619             mCi.unregisterForCdmaOtaProvision(this);
    620             mPhone.unregisterForSimRecordsLoaded(this);
    621 
    622             mCellLoc = new GsmCellLocation();
    623             mNewCellLoc = new GsmCellLocation();
    624         } else {
    625             mPhone.registerForSimRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
    626             mCellLoc = new CdmaCellLocation();
    627             mNewCellLoc = new CdmaCellLocation();
    628             mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(), mCi, this,
    629                     EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
    630             mIsSubscriptionFromRuim = (mCdmaSSM.getCdmaSubscriptionSource() ==
    631                     CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
    632 
    633             mCi.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null);
    634             mPhone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
    635             mCi.registerForCdmaOtaProvision(this, EVENT_OTA_PROVISION_STATUS_CHANGE, null);
    636 
    637             mHbpcdUtils = new HbpcdUtils(mPhone.getContext());
    638             // update OTASP state in case previously set by another service
    639             updateOtaspState();
    640         }
    641 
    642         // This should be done after the technology specific initializations above since it relies
    643         // on fields like mIsSubscriptionFromRuim (which is updated above)
    644         onUpdateIccAvailability();
    645 
    646         mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
    647                 ServiceState.rilRadioTechnologyToString(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN));
    648         // Query signal strength from the modem after service tracker is created (i.e. boot up,
    649         // switching between GSM and CDMA phone), because the unsolicited signal strength
    650         // information might come late or even never come. This will get the accurate signal
    651         // strength information displayed on the UI.
    652         mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
    653         sendMessage(obtainMessage(EVENT_PHONE_TYPE_SWITCHED));
    654 
    655         logPhoneTypeChange();
    656 
    657         // Tell everybody that the registration state and RAT have changed.
    658         notifyDataRegStateRilRadioTechnologyChanged();
    659     }
    660 
    661     @VisibleForTesting
    662     public void requestShutdown() {
    663         if (mDeviceShuttingDown == true) return;
    664         mDeviceShuttingDown = true;
    665         mDesiredPowerState = false;
    666         setPowerStateToDesired();
    667     }
    668 
    669     public void dispose() {
    670         mCi.unSetOnSignalStrengthUpdate(this);
    671         mUiccController.unregisterForIccChanged(this);
    672         mCi.unregisterForCellInfoList(this);
    673         mCi.unregisterForPhysicalChannelConfiguration(this);
    674         mSubscriptionManager
    675             .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
    676         mHandlerThread.quit();
    677         mCi.unregisterForImsNetworkStateChanged(this);
    678         mPhone.getCarrierActionAgent().unregisterForCarrierAction(this,
    679                 CARRIER_ACTION_SET_RADIO_ENABLED);
    680         if (mCSST != null) {
    681             mCSST.dispose();
    682             mCSST = null;
    683         }
    684     }
    685 
    686     public boolean getDesiredPowerState() {
    687         return mDesiredPowerState;
    688     }
    689     public boolean getPowerStateFromCarrier() { return !mRadioDisabledByCarrier; }
    690 
    691     private SignalStrength mLastSignalStrength = null;
    692     protected boolean notifySignalStrength() {
    693         boolean notified = false;
    694         if (!mSignalStrength.equals(mLastSignalStrength)) {
    695             try {
    696                 mPhone.notifySignalStrength();
    697                 notified = true;
    698                 mLastSignalStrength = mSignalStrength;
    699             } catch (NullPointerException ex) {
    700                 loge("updateSignalStrength() Phone already destroyed: " + ex
    701                         + "SignalStrength not notified");
    702             }
    703         }
    704         return notified;
    705     }
    706 
    707     /**
    708      * Notify all mDataConnectionRatChangeRegistrants using an
    709      * AsyncResult in msg.obj where AsyncResult#result contains the
    710      * new RAT as an Integer Object.
    711      */
    712     protected void notifyDataRegStateRilRadioTechnologyChanged() {
    713         int rat = mSS.getRilDataRadioTechnology();
    714         int drs = mSS.getDataRegState();
    715         if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat);
    716 
    717         mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
    718                 ServiceState.rilRadioTechnologyToString(rat));
    719         mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat));
    720     }
    721 
    722     /**
    723      * Some operators have been known to report registration failure
    724      * data only devices, to fix that use DataRegState.
    725      */
    726     protected void useDataRegStateForDataOnlyDevices() {
    727         if (mVoiceCapable == false) {
    728             if (DBG) {
    729                 log("useDataRegStateForDataOnlyDevice: VoiceRegState=" + mNewSS.getVoiceRegState()
    730                     + " DataRegState=" + mNewSS.getDataRegState());
    731             }
    732             // TODO: Consider not lying and instead have callers know the difference.
    733             mNewSS.setVoiceRegState(mNewSS.getDataRegState());
    734         }
    735     }
    736 
    737     protected void updatePhoneObject() {
    738         if (mPhone.getContext().getResources().
    739                 getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) {
    740             // If the phone is not registered on a network, no need to update.
    741             boolean isRegistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE ||
    742                     mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY;
    743             if (!isRegistered) {
    744                 log("updatePhoneObject: Ignore update");
    745                 return;
    746             }
    747             mPhone.updatePhoneObject(mSS.getRilVoiceRadioTechnology());
    748         }
    749     }
    750 
    751     /**
    752      * Registration point for combined roaming on of mobile voice
    753      * combined roaming is true when roaming is true and ONS differs SPN
    754      *
    755      * @param h handler to notify
    756      * @param what what code of message when delivered
    757      * @param obj placed in Message.obj
    758      */
    759     public void registerForVoiceRoamingOn(Handler h, int what, Object obj) {
    760         Registrant r = new Registrant(h, what, obj);
    761         mVoiceRoamingOnRegistrants.add(r);
    762 
    763         if (mSS.getVoiceRoaming()) {
    764             r.notifyRegistrant();
    765         }
    766     }
    767 
    768     public void unregisterForVoiceRoamingOn(Handler h) {
    769         mVoiceRoamingOnRegistrants.remove(h);
    770     }
    771 
    772     /**
    773      * Registration point for roaming off of mobile voice
    774      * combined roaming is true when roaming is true and ONS differs SPN
    775      *
    776      * @param h handler to notify
    777      * @param what what code of message when delivered
    778      * @param obj placed in Message.obj
    779      */
    780     public void registerForVoiceRoamingOff(Handler h, int what, Object obj) {
    781         Registrant r = new Registrant(h, what, obj);
    782         mVoiceRoamingOffRegistrants.add(r);
    783 
    784         if (!mSS.getVoiceRoaming()) {
    785             r.notifyRegistrant();
    786         }
    787     }
    788 
    789     public void unregisterForVoiceRoamingOff(Handler h) {
    790         mVoiceRoamingOffRegistrants.remove(h);
    791     }
    792 
    793     /**
    794      * Registration point for combined roaming on of mobile data
    795      * combined roaming is true when roaming is true and ONS differs SPN
    796      *
    797      * @param h handler to notify
    798      * @param what what code of message when delivered
    799      * @param obj placed in Message.obj
    800      */
    801     public void registerForDataRoamingOn(Handler h, int what, Object obj) {
    802         Registrant r = new Registrant(h, what, obj);
    803         mDataRoamingOnRegistrants.add(r);
    804 
    805         if (mSS.getDataRoaming()) {
    806             r.notifyRegistrant();
    807         }
    808     }
    809 
    810     public void unregisterForDataRoamingOn(Handler h) {
    811         mDataRoamingOnRegistrants.remove(h);
    812     }
    813 
    814     /**
    815      * Registration point for roaming off of mobile data
    816      * combined roaming is true when roaming is true and ONS differs SPN
    817      *
    818      * @param h handler to notify
    819      * @param what what code of message when delivered
    820      * @param obj placed in Message.obj
    821      * @param notifyNow notify upon registration if data roaming is off
    822      */
    823     public void registerForDataRoamingOff(Handler h, int what, Object obj, boolean notifyNow) {
    824         Registrant r = new Registrant(h, what, obj);
    825         mDataRoamingOffRegistrants.add(r);
    826 
    827         if (notifyNow && !mSS.getDataRoaming()) {
    828             r.notifyRegistrant();
    829         }
    830     }
    831 
    832     public void unregisterForDataRoamingOff(Handler h) {
    833         mDataRoamingOffRegistrants.remove(h);
    834     }
    835 
    836     /**
    837      * Re-register network by toggling preferred network type.
    838      * This is a work-around to deregister and register network since there is
    839      * no ril api to set COPS=2 (deregister) only.
    840      *
    841      * @param onComplete is dispatched when this is complete.  it will be
    842      * an AsyncResult, and onComplete.obj.exception will be non-null
    843      * on failure.
    844      */
    845     public void reRegisterNetwork(Message onComplete) {
    846         mCi.getPreferredNetworkType(
    847                 obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
    848     }
    849 
    850     public void
    851     setRadioPower(boolean power) {
    852         mDesiredPowerState = power;
    853 
    854         setPowerStateToDesired();
    855     }
    856 
    857     /**
    858      * Radio power set from carrier action. if set to false means carrier desire to turn radio off
    859      * and radio wont be re-enabled unless carrier explicitly turn it back on.
    860      * @param enable indicate if radio power is enabled or disabled from carrier action.
    861      */
    862     public void setRadioPowerFromCarrier(boolean enable) {
    863         mRadioDisabledByCarrier = !enable;
    864         setPowerStateToDesired();
    865     }
    866 
    867     /**
    868      * These two flags manage the behavior of the cell lock -- the
    869      * lock should be held if either flag is true.  The intention is
    870      * to allow temporary acquisition of the lock to get a single
    871      * update.  Such a lock grab and release can thus be made to not
    872      * interfere with more permanent lock holds -- in other words, the
    873      * lock will only be released if both flags are false, and so
    874      * releases by temporary users will only affect the lock state if
    875      * there is no continuous user.
    876      */
    877     private boolean mWantContinuousLocationUpdates;
    878     private boolean mWantSingleLocationUpdate;
    879 
    880     public void enableSingleLocationUpdate() {
    881         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
    882         mWantSingleLocationUpdate = true;
    883         mCi.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
    884     }
    885 
    886     public void enableLocationUpdates() {
    887         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
    888         mWantContinuousLocationUpdates = true;
    889         mCi.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
    890     }
    891 
    892     protected void disableSingleLocationUpdate() {
    893         mWantSingleLocationUpdate = false;
    894         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
    895             mCi.setLocationUpdates(false, null);
    896         }
    897     }
    898 
    899     public void disableLocationUpdates() {
    900         mWantContinuousLocationUpdates = false;
    901         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
    902             mCi.setLocationUpdates(false, null);
    903         }
    904     }
    905 
    906     private void processCellLocationInfo(CellLocation cellLocation, CellIdentity cellIdentity) {
    907         if (mPhone.isPhoneTypeGsm()) {
    908             int psc = -1;
    909             int cid = -1;
    910             int lac = -1;
    911             if (cellIdentity != null) {
    912                 switch (cellIdentity.getType()) {
    913                     case CellInfoType.GSM: {
    914                         cid = ((CellIdentityGsm) cellIdentity).getCid();
    915                         lac = ((CellIdentityGsm) cellIdentity).getLac();
    916                         break;
    917                     }
    918                     case CellInfoType.WCDMA: {
    919                         cid = ((CellIdentityWcdma) cellIdentity).getCid();
    920                         lac = ((CellIdentityWcdma) cellIdentity).getLac();
    921                         psc = ((CellIdentityWcdma) cellIdentity).getPsc();
    922                         break;
    923                     }
    924                     case CellInfoType.TD_SCDMA: {
    925                         cid = ((CellIdentityTdscdma) cellIdentity).getCid();
    926                         lac = ((CellIdentityTdscdma) cellIdentity).getLac();
    927                         break;
    928                     }
    929                     case CellInfoType.LTE: {
    930                         cid = ((CellIdentityLte) cellIdentity).getCi();
    931                         lac = ((CellIdentityLte) cellIdentity).getTac();
    932                         break;
    933                     }
    934                     default: {
    935                         break;
    936                     }
    937                 }
    938             }
    939             // LAC and CID are -1 if not avail
    940             ((GsmCellLocation) cellLocation).setLacAndCid(lac, cid);
    941             ((GsmCellLocation) cellLocation).setPsc(psc);
    942         } else {
    943             int baseStationId = -1;
    944             int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
    945             int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    946             int systemId = 0;
    947             int networkId = 0;
    948 
    949             if (cellIdentity != null) {
    950                 switch (cellIdentity.getType()) {
    951                     case CellInfoType.CDMA: {
    952                         baseStationId = ((CellIdentityCdma) cellIdentity).getBasestationId();
    953                         baseStationLatitude = ((CellIdentityCdma) cellIdentity).getLatitude();
    954                         baseStationLongitude = ((CellIdentityCdma) cellIdentity).getLongitude();
    955                         systemId = ((CellIdentityCdma) cellIdentity).getSystemId();
    956                         networkId = ((CellIdentityCdma) cellIdentity).getNetworkId();
    957                         break;
    958                     }
    959                     default: {
    960                         break;
    961                     }
    962                 }
    963             }
    964 
    965             // Some carriers only return lat-lngs of 0,0
    966             if (baseStationLatitude == 0 && baseStationLongitude == 0) {
    967                 baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
    968                 baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    969             }
    970 
    971             // Values are -1 if not available.
    972             ((CdmaCellLocation) cellLocation).setCellLocationData(baseStationId,
    973                     baseStationLatitude, baseStationLongitude, systemId, networkId);
    974         }
    975     }
    976 
    977     private int getLteEarfcn(CellIdentity cellIdentity) {
    978         int lteEarfcn = INVALID_LTE_EARFCN;
    979         if (cellIdentity != null) {
    980             switch (cellIdentity.getType()) {
    981                 case CellInfoType.LTE: {
    982                     lteEarfcn = ((CellIdentityLte) cellIdentity).getEarfcn();
    983                     break;
    984                 }
    985                 default: {
    986                     break;
    987                 }
    988             }
    989         }
    990 
    991         return lteEarfcn;
    992     }
    993 
    994     @Override
    995     public void handleMessage(Message msg) {
    996         AsyncResult ar;
    997         int[] ints;
    998         Message message;
    999 
   1000         if (VDBG) log("received event " + msg.what);
   1001         switch (msg.what) {
   1002             case EVENT_SET_RADIO_POWER_OFF:
   1003                 synchronized(this) {
   1004                     if (mPendingRadioPowerOffAfterDataOff &&
   1005                             (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
   1006                         if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
   1007                         hangupAndPowerOff();
   1008                         mPendingRadioPowerOffAfterDataOffTag += 1;
   1009                         mPendingRadioPowerOffAfterDataOff = false;
   1010                     } else {
   1011                         log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
   1012                                 "!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
   1013                     }
   1014                 }
   1015                 break;
   1016 
   1017             case EVENT_ICC_CHANGED:
   1018                 onUpdateIccAvailability();
   1019                 if (mUiccApplcation != null
   1020                         && mUiccApplcation.getState() != AppState.APPSTATE_READY) {
   1021                     mIsSimReady = false;
   1022                     updateSpnDisplay();
   1023                 }
   1024                 break;
   1025 
   1026             case EVENT_GET_CELL_INFO_LIST: {
   1027                 ar = (AsyncResult) msg.obj;
   1028                 CellInfoResult result = (CellInfoResult) ar.userObj;
   1029                 synchronized(result.lockObj) {
   1030                     if (ar.exception != null) {
   1031                         log("EVENT_GET_CELL_INFO_LIST: error ret null, e=" + ar.exception);
   1032                         result.list = null;
   1033                     } else {
   1034                         result.list = (List<CellInfo>) ar.result;
   1035 
   1036                         if (VDBG) {
   1037                             log("EVENT_GET_CELL_INFO_LIST: size=" + result.list.size()
   1038                                     + " list=" + result.list);
   1039                         }
   1040                     }
   1041                     mLastCellInfoListTime = SystemClock.elapsedRealtime();
   1042                     mLastCellInfoList = result.list;
   1043                     result.lockObj.notify();
   1044                 }
   1045                 break;
   1046             }
   1047 
   1048             case EVENT_UNSOL_CELL_INFO_LIST: {
   1049                 ar = (AsyncResult) msg.obj;
   1050                 if (ar.exception != null) {
   1051                     log("EVENT_UNSOL_CELL_INFO_LIST: error ignoring, e=" + ar.exception);
   1052                 } else {
   1053                     List<CellInfo> list = (List<CellInfo>) ar.result;
   1054                     if (VDBG) {
   1055                         log("EVENT_UNSOL_CELL_INFO_LIST: size=" + list.size() + " list=" + list);
   1056                     }
   1057                     mLastCellInfoListTime = SystemClock.elapsedRealtime();
   1058                     mLastCellInfoList = list;
   1059                     mPhone.notifyCellInfo(list);
   1060                 }
   1061                 break;
   1062             }
   1063 
   1064             case  EVENT_IMS_STATE_CHANGED: // received unsol
   1065                 mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE));
   1066                 break;
   1067 
   1068             case EVENT_IMS_STATE_DONE:
   1069                 ar = (AsyncResult) msg.obj;
   1070                 if (ar.exception == null) {
   1071                     int[] responseArray = (int[])ar.result;
   1072                     mImsRegistered = (responseArray[0] == 1) ? true : false;
   1073                 }
   1074                 break;
   1075 
   1076             case EVENT_RADIO_POWER_OFF_DONE:
   1077                 if (DBG) log("EVENT_RADIO_POWER_OFF_DONE");
   1078                 if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) {
   1079                     // during shutdown the modem may not send radio state changed event
   1080                     // as a result of radio power request
   1081                     // Hence, issuing shut down regardless of radio power response
   1082                     mCi.requestShutdown(null);
   1083                 }
   1084                 break;
   1085 
   1086             // GSM
   1087             case EVENT_SIM_READY:
   1088                 // Reset the mPreviousSubId so we treat a SIM power bounce
   1089                 // as a first boot.  See b/19194287
   1090                 mOnSubscriptionsChangedListener.mPreviousSubId.set(
   1091                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
   1092                 mPrevSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
   1093                 mIsSimReady = true;
   1094                 pollState();
   1095                 // Signal strength polling stops when radio is off
   1096                 queueNextSignalStrengthPoll();
   1097                 break;
   1098 
   1099             case EVENT_RADIO_STATE_CHANGED:
   1100             case EVENT_PHONE_TYPE_SWITCHED:
   1101                 if(!mPhone.isPhoneTypeGsm() &&
   1102                         mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON) {
   1103                     handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
   1104 
   1105                     // Signal strength polling stops when radio is off.
   1106                     queueNextSignalStrengthPoll();
   1107                 }
   1108                 // This will do nothing in the 'radio not available' case
   1109                 setPowerStateToDesired();
   1110                 // These events are modem triggered, so pollState() needs to be forced
   1111                 modemTriggeredPollState();
   1112                 break;
   1113 
   1114             case EVENT_NETWORK_STATE_CHANGED:
   1115                 modemTriggeredPollState();
   1116                 break;
   1117 
   1118             case EVENT_GET_SIGNAL_STRENGTH:
   1119                 // This callback is called when signal strength is polled
   1120                 // all by itself
   1121 
   1122                 if (!(mCi.getRadioState().isOn())) {
   1123                     // Polling will continue when radio turns back on
   1124                     return;
   1125                 }
   1126                 ar = (AsyncResult) msg.obj;
   1127                 onSignalStrengthResult(ar);
   1128                 queueNextSignalStrengthPoll();
   1129 
   1130                 break;
   1131 
   1132             case EVENT_GET_LOC_DONE:
   1133                 ar = (AsyncResult) msg.obj;
   1134                 if (ar.exception == null) {
   1135                     CellIdentity cellIdentity = ((NetworkRegistrationState) ar.result)
   1136                             .getCellIdentity();
   1137                     processCellLocationInfo(mCellLoc, cellIdentity);
   1138                     mPhone.notifyLocationChanged();
   1139                 }
   1140 
   1141                 // Release any temporary cell lock, which could have been
   1142                 // acquired to allow a single-shot location update.
   1143                 disableSingleLocationUpdate();
   1144                 break;
   1145 
   1146             case EVENT_POLL_STATE_REGISTRATION:
   1147             case EVENT_POLL_STATE_GPRS:
   1148             case EVENT_POLL_STATE_OPERATOR:
   1149                 ar = (AsyncResult) msg.obj;
   1150                 handlePollStateResult(msg.what, ar);
   1151                 break;
   1152 
   1153             case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
   1154                 if (DBG) log("EVENT_POLL_STATE_NETWORK_SELECTION_MODE");
   1155                 ar = (AsyncResult) msg.obj;
   1156                 if (mPhone.isPhoneTypeGsm()) {
   1157                     handlePollStateResult(msg.what, ar);
   1158                 } else {
   1159                     if (ar.exception == null && ar.result != null) {
   1160                         ints = (int[])ar.result;
   1161                         if (ints[0] == 1) {  // Manual selection.
   1162                             mPhone.setNetworkSelectionModeAutomatic(null);
   1163                         }
   1164                     } else {
   1165                         log("Unable to getNetworkSelectionMode");
   1166                     }
   1167                 }
   1168                 break;
   1169 
   1170             case EVENT_POLL_SIGNAL_STRENGTH:
   1171                 // Just poll signal strength...not part of pollState()
   1172 
   1173                 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
   1174                 break;
   1175 
   1176             case EVENT_NITZ_TIME:
   1177                 ar = (AsyncResult) msg.obj;
   1178 
   1179                 String nitzString = (String)((Object[])ar.result)[0];
   1180                 long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
   1181 
   1182                 setTimeFromNITZString(nitzString, nitzReceiveTime);
   1183                 break;
   1184 
   1185             case EVENT_SIGNAL_STRENGTH_UPDATE:
   1186                 // This is a notification from CommandsInterface.setOnSignalStrengthUpdate
   1187 
   1188                 ar = (AsyncResult) msg.obj;
   1189 
   1190                 // The radio is telling us about signal strength changes
   1191                 // we don't have to ask it
   1192                 mDontPollSignalStrength = true;
   1193 
   1194                 onSignalStrengthResult(ar);
   1195                 break;
   1196 
   1197             case EVENT_SIM_RECORDS_LOADED:
   1198                 log("EVENT_SIM_RECORDS_LOADED: what=" + msg.what);
   1199                 updatePhoneObject();
   1200                 updateOtaspState();
   1201                 if (mPhone.isPhoneTypeGsm()) {
   1202                     updateSpnDisplay();
   1203                 }
   1204                 break;
   1205 
   1206             case EVENT_LOCATION_UPDATES_ENABLED:
   1207                 ar = (AsyncResult) msg.obj;
   1208 
   1209                 if (ar.exception == null) {
   1210                     mRegStateManagers.get(AccessNetworkConstants.TransportType.WWAN)
   1211                             .getNetworkRegistrationState(NetworkRegistrationState.DOMAIN_CS,
   1212                             obtainMessage(EVENT_GET_LOC_DONE, null));
   1213                 }
   1214                 break;
   1215 
   1216             case EVENT_SET_PREFERRED_NETWORK_TYPE:
   1217                 ar = (AsyncResult) msg.obj;
   1218                 // Don't care the result, only use for dereg network (COPS=2)
   1219                 message = obtainMessage(EVENT_RESET_PREFERRED_NETWORK_TYPE, ar.userObj);
   1220                 mCi.setPreferredNetworkType(mPreferredNetworkType, message);
   1221                 break;
   1222 
   1223             case EVENT_RESET_PREFERRED_NETWORK_TYPE:
   1224                 ar = (AsyncResult) msg.obj;
   1225                 if (ar.userObj != null) {
   1226                     AsyncResult.forMessage(((Message) ar.userObj)).exception
   1227                             = ar.exception;
   1228                     ((Message) ar.userObj).sendToTarget();
   1229                 }
   1230                 break;
   1231 
   1232             case EVENT_GET_PREFERRED_NETWORK_TYPE:
   1233                 ar = (AsyncResult) msg.obj;
   1234 
   1235                 if (ar.exception == null) {
   1236                     mPreferredNetworkType = ((int[])ar.result)[0];
   1237                 } else {
   1238                     mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
   1239                 }
   1240 
   1241                 message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
   1242                 int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
   1243 
   1244                 mCi.setPreferredNetworkType(toggledNetworkType, message);
   1245                 break;
   1246 
   1247             case EVENT_CHECK_REPORT_GPRS:
   1248                 if (mPhone.isPhoneTypeGsm() && mSS != null &&
   1249                         !isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
   1250 
   1251                     // Can't register data service while voice service is ok
   1252                     // i.e. CREG is ok while CGREG is not
   1253                     // possible a network or baseband side error
   1254                     GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
   1255                     EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL,
   1256                             mSS.getOperatorNumeric(), loc != null ? loc.getCid() : -1);
   1257                     mReportedGprsNoReg = true;
   1258                 }
   1259                 mStartedGprsRegCheck = false;
   1260                 break;
   1261 
   1262             case EVENT_RESTRICTED_STATE_CHANGED:
   1263                 if (mPhone.isPhoneTypeGsm()) {
   1264                     // This is a notification from
   1265                     // CommandsInterface.setOnRestrictedStateChanged
   1266 
   1267                     if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED");
   1268 
   1269                     ar = (AsyncResult) msg.obj;
   1270 
   1271                     onRestrictedStateChanged(ar);
   1272                 }
   1273                 break;
   1274 
   1275             case EVENT_SIM_NOT_INSERTED:
   1276                 if (DBG) log("EVENT_SIM_NOT_INSERTED");
   1277                 cancelAllNotifications();
   1278                 mMdn = null;
   1279                 mMin = null;
   1280                 mIsMinInfoReady = false;
   1281                 break;
   1282 
   1283             case EVENT_ALL_DATA_DISCONNECTED:
   1284                 int dds = SubscriptionManager.getDefaultDataSubscriptionId();
   1285                 ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this);
   1286                 synchronized(this) {
   1287                     if (mPendingRadioPowerOffAfterDataOff) {
   1288                         if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
   1289                         hangupAndPowerOff();
   1290                         mPendingRadioPowerOffAfterDataOff = false;
   1291                     } else {
   1292                         log("EVENT_ALL_DATA_DISCONNECTED is stale");
   1293                     }
   1294                 }
   1295                 break;
   1296 
   1297             case EVENT_CHANGE_IMS_STATE:
   1298                 if (DBG) log("EVENT_CHANGE_IMS_STATE:");
   1299 
   1300                 setPowerStateToDesired();
   1301                 break;
   1302 
   1303             case EVENT_IMS_CAPABILITY_CHANGED:
   1304                 if (DBG) log("EVENT_IMS_CAPABILITY_CHANGED");
   1305                 updateSpnDisplay();
   1306                 break;
   1307 
   1308             case EVENT_IMS_SERVICE_STATE_CHANGED:
   1309                 if (DBG) log("EVENT_IMS_SERVICE_STATE_CHANGED");
   1310                 // IMS state will only affect the merged service state if the service state of
   1311                 // GsmCdma phone is not STATE_IN_SERVICE.
   1312                 if (mSS.getState() != ServiceState.STATE_IN_SERVICE) {
   1313                     mPhone.notifyServiceStateChanged(mPhone.getServiceState());
   1314                 }
   1315                 break;
   1316 
   1317             //CDMA
   1318             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
   1319                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
   1320                 break;
   1321 
   1322             case EVENT_RUIM_READY:
   1323                 if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
   1324                     // Subscription will be read from SIM I/O
   1325                     if (DBG) log("Receive EVENT_RUIM_READY");
   1326                     pollState();
   1327                 } else {
   1328                     if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
   1329                     getSubscriptionInfoAndStartPollingThreads();
   1330                 }
   1331 
   1332                 // Only support automatic selection mode in CDMA.
   1333                 mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE));
   1334 
   1335                 break;
   1336 
   1337             case EVENT_NV_READY:
   1338                 updatePhoneObject();
   1339 
   1340                 // Only support automatic selection mode in CDMA.
   1341                 mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE));
   1342 
   1343                 // For Non-RUIM phones, the subscription information is stored in
   1344                 // Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA
   1345                 // subscription info.
   1346                 getSubscriptionInfoAndStartPollingThreads();
   1347                 break;
   1348 
   1349             case EVENT_POLL_STATE_CDMA_SUBSCRIPTION: // Handle RIL_CDMA_SUBSCRIPTION
   1350                 if (!mPhone.isPhoneTypeGsm()) {
   1351                     ar = (AsyncResult) msg.obj;
   1352 
   1353                     if (ar.exception == null) {
   1354                         String cdmaSubscription[] = (String[]) ar.result;
   1355                         if (cdmaSubscription != null && cdmaSubscription.length >= 5) {
   1356                             mMdn = cdmaSubscription[0];
   1357                             parseSidNid(cdmaSubscription[1], cdmaSubscription[2]);
   1358 
   1359                             mMin = cdmaSubscription[3];
   1360                             mPrlVersion = cdmaSubscription[4];
   1361                             if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn);
   1362 
   1363                             mIsMinInfoReady = true;
   1364 
   1365                             updateOtaspState();
   1366                             // Notify apps subscription info is ready
   1367                             notifyCdmaSubscriptionInfoReady();
   1368 
   1369                             if (!mIsSubscriptionFromRuim && mIccRecords != null) {
   1370                                 if (DBG) {
   1371                                     log("GET_CDMA_SUBSCRIPTION set imsi in mIccRecords");
   1372                                 }
   1373                                 mIccRecords.setImsi(getImsi());
   1374                             } else {
   1375                                 if (DBG) {
   1376                                     log("GET_CDMA_SUBSCRIPTION either mIccRecords is null or NV " +
   1377                                             "type device - not setting Imsi in mIccRecords");
   1378                                 }
   1379                             }
   1380                         } else {
   1381                             if (DBG) {
   1382                                 log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription " +
   1383                                         "params num=" + cdmaSubscription.length);
   1384                             }
   1385                         }
   1386                     }
   1387                 }
   1388                 break;
   1389 
   1390             case EVENT_RUIM_RECORDS_LOADED:
   1391                 if (!mPhone.isPhoneTypeGsm()) {
   1392                     log("EVENT_RUIM_RECORDS_LOADED: what=" + msg.what);
   1393                     updatePhoneObject();
   1394                     if (mPhone.isPhoneTypeCdma()) {
   1395                         updateSpnDisplay();
   1396                     } else {
   1397                         RuimRecords ruim = (RuimRecords) mIccRecords;
   1398                         if (ruim != null) {
   1399                             if (ruim.isProvisioned()) {
   1400                                 mMdn = ruim.getMdn();
   1401                                 mMin = ruim.getMin();
   1402                                 parseSidNid(ruim.getSid(), ruim.getNid());
   1403                                 mPrlVersion = ruim.getPrlVersion();
   1404                                 mIsMinInfoReady = true;
   1405                             }
   1406                             updateOtaspState();
   1407                             // Notify apps subscription info is ready
   1408                             notifyCdmaSubscriptionInfoReady();
   1409                         }
   1410                         // SID/NID/PRL is loaded. Poll service state
   1411                         // again to update to the roaming state with
   1412                         // the latest variables.
   1413                         pollState();
   1414                     }
   1415                 }
   1416                 break;
   1417 
   1418             case EVENT_ERI_FILE_LOADED:
   1419                 // Repoll the state once the ERI file has been loaded.
   1420                 if (DBG) log("ERI file has been loaded, repolling.");
   1421                 pollState();
   1422                 break;
   1423 
   1424             case EVENT_OTA_PROVISION_STATUS_CHANGE:
   1425                 ar = (AsyncResult)msg.obj;
   1426                 if (ar.exception == null) {
   1427                     ints = (int[]) ar.result;
   1428                     int otaStatus = ints[0];
   1429                     if (otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
   1430                             || otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
   1431                         if (DBG) log("EVENT_OTA_PROVISION_STATUS_CHANGE: Complete, Reload MDN");
   1432                         mCi.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
   1433                     }
   1434                 }
   1435                 break;
   1436 
   1437             case EVENT_CDMA_PRL_VERSION_CHANGED:
   1438                 ar = (AsyncResult)msg.obj;
   1439                 if (ar.exception == null) {
   1440                     ints = (int[]) ar.result;
   1441                     mPrlVersion = Integer.toString(ints[0]);
   1442                 }
   1443                 break;
   1444 
   1445             case EVENT_RADIO_POWER_FROM_CARRIER:
   1446                 ar = (AsyncResult) msg.obj;
   1447                 if (ar.exception == null) {
   1448                     boolean enable = (boolean) ar.result;
   1449                     if (DBG) log("EVENT_RADIO_POWER_FROM_CARRIER: " + enable);
   1450                     setRadioPowerFromCarrier(enable);
   1451                 }
   1452                 break;
   1453 
   1454             case EVENT_PHYSICAL_CHANNEL_CONFIG:
   1455                 ar = (AsyncResult) msg.obj;
   1456                 if (ar.exception == null) {
   1457                     List<PhysicalChannelConfig> list = (List<PhysicalChannelConfig>) ar.result;
   1458                     if (VDBG) {
   1459                         log("EVENT_PHYSICAL_CHANNEL_CONFIG: size=" + list.size() + " list="
   1460                                 + list);
   1461                     }
   1462                     mPhone.notifyPhysicalChannelConfiguration(list);
   1463                     mLastPhysicalChannelConfigList = list;
   1464 
   1465                     // only notify if bandwidths changed
   1466                     if (RatRatcheter.updateBandwidths(getBandwidthsFromConfigs(list), mSS)) {
   1467                         mPhone.notifyServiceStateChanged(mSS);
   1468                     }
   1469                 }
   1470                 break;
   1471 
   1472             default:
   1473                 log("Unhandled message with number: " + msg.what);
   1474                 break;
   1475         }
   1476     }
   1477 
   1478     private int[] getBandwidthsFromConfigs(List<PhysicalChannelConfig> list) {
   1479         return list.stream()
   1480                 .map(PhysicalChannelConfig::getCellBandwidthDownlink)
   1481                 .mapToInt(Integer::intValue)
   1482                 .toArray();
   1483     }
   1484 
   1485     protected boolean isSidsAllZeros() {
   1486         if (mHomeSystemId != null) {
   1487             for (int i=0; i < mHomeSystemId.length; i++) {
   1488                 if (mHomeSystemId[i] != 0) {
   1489                     return false;
   1490                 }
   1491             }
   1492         }
   1493         return true;
   1494     }
   1495 
   1496     /**
   1497      * Check whether a specified system ID that matches one of the home system IDs.
   1498      */
   1499     private boolean isHomeSid(int sid) {
   1500         if (mHomeSystemId != null) {
   1501             for (int i=0; i < mHomeSystemId.length; i++) {
   1502                 if (sid == mHomeSystemId[i]) {
   1503                     return true;
   1504                 }
   1505             }
   1506         }
   1507         return false;
   1508     }
   1509 
   1510     public String getMdnNumber() {
   1511         return mMdn;
   1512     }
   1513 
   1514     public String getCdmaMin() {
   1515         return mMin;
   1516     }
   1517 
   1518     /** Returns null if NV is not yet ready */
   1519     public String getPrlVersion() {
   1520         return mPrlVersion;
   1521     }
   1522 
   1523     /**
   1524      * Returns IMSI as MCC + MNC + MIN
   1525      */
   1526     public String getImsi() {
   1527         // TODO: When RUIM is enabled, IMSI will come from RUIM not build-time props.
   1528         String operatorNumeric = ((TelephonyManager) mPhone.getContext().
   1529                 getSystemService(Context.TELEPHONY_SERVICE)).
   1530                 getSimOperatorNumericForPhone(mPhone.getPhoneId());
   1531 
   1532         if (!TextUtils.isEmpty(operatorNumeric) && getCdmaMin() != null) {
   1533             return (operatorNumeric + getCdmaMin());
   1534         } else {
   1535             return null;
   1536         }
   1537     }
   1538 
   1539     /**
   1540      * Check if subscription data has been assigned to mMin
   1541      *
   1542      * return true if MIN info is ready; false otherwise.
   1543      */
   1544     public boolean isMinInfoReady() {
   1545         return mIsMinInfoReady;
   1546     }
   1547 
   1548     /**
   1549      * Returns OTASP_UNKNOWN, OTASP_UNINITIALIZED, OTASP_NEEDED or OTASP_NOT_NEEDED
   1550      */
   1551     public int getOtasp() {
   1552         int provisioningState;
   1553         // if sim is not loaded, return otasp uninitialized
   1554         if(!mPhone.getIccRecordsLoaded()) {
   1555             if(DBG) log("getOtasp: otasp uninitialized due to sim not loaded");
   1556             return TelephonyManager.OTASP_UNINITIALIZED;
   1557         }
   1558         // if voice tech is Gsm, return otasp not needed
   1559         if(mPhone.isPhoneTypeGsm()) {
   1560             if(DBG) log("getOtasp: otasp not needed for GSM");
   1561             return TelephonyManager.OTASP_NOT_NEEDED;
   1562         }
   1563         // for ruim, min is null means require otasp.
   1564         if (mIsSubscriptionFromRuim && mMin == null) {
   1565             return TelephonyManager.OTASP_NEEDED;
   1566         }
   1567         if (mMin == null || (mMin.length() < 6)) {
   1568             if (DBG) log("getOtasp: bad mMin='" + mMin + "'");
   1569             provisioningState = TelephonyManager.OTASP_UNKNOWN;
   1570         } else {
   1571             if ((mMin.equals(UNACTIVATED_MIN_VALUE)
   1572                     || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
   1573                     || SystemProperties.getBoolean("test_cdma_setup", false)) {
   1574                 provisioningState = TelephonyManager.OTASP_NEEDED;
   1575             } else {
   1576                 provisioningState = TelephonyManager.OTASP_NOT_NEEDED;
   1577             }
   1578         }
   1579         if (DBG) log("getOtasp: state=" + provisioningState);
   1580         return provisioningState;
   1581     }
   1582 
   1583     protected void parseSidNid (String sidStr, String nidStr) {
   1584         if (sidStr != null) {
   1585             String[] sid = sidStr.split(",");
   1586             mHomeSystemId = new int[sid.length];
   1587             for (int i = 0; i < sid.length; i++) {
   1588                 try {
   1589                     mHomeSystemId[i] = Integer.parseInt(sid[i]);
   1590                 } catch (NumberFormatException ex) {
   1591                     loge("error parsing system id: " + ex);
   1592                 }
   1593             }
   1594         }
   1595         if (DBG) log("CDMA_SUBSCRIPTION: SID=" + sidStr);
   1596 
   1597         if (nidStr != null) {
   1598             String[] nid = nidStr.split(",");
   1599             mHomeNetworkId = new int[nid.length];
   1600             for (int i = 0; i < nid.length; i++) {
   1601                 try {
   1602                     mHomeNetworkId[i] = Integer.parseInt(nid[i]);
   1603                 } catch (NumberFormatException ex) {
   1604                     loge("CDMA_SUBSCRIPTION: error parsing network id: " + ex);
   1605                 }
   1606             }
   1607         }
   1608         if (DBG) log("CDMA_SUBSCRIPTION: NID=" + nidStr);
   1609     }
   1610 
   1611     protected void updateOtaspState() {
   1612         int otaspMode = getOtasp();
   1613         int oldOtaspMode = mCurrentOtaspMode;
   1614         mCurrentOtaspMode = otaspMode;
   1615 
   1616         if (oldOtaspMode != mCurrentOtaspMode) {
   1617             if (DBG) {
   1618                 log("updateOtaspState: call notifyOtaspChanged old otaspMode=" +
   1619                         oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
   1620             }
   1621             mPhone.notifyOtaspChanged(mCurrentOtaspMode);
   1622         }
   1623     }
   1624 
   1625     protected Phone getPhone() {
   1626         return mPhone;
   1627     }
   1628 
   1629     protected void handlePollStateResult(int what, AsyncResult ar) {
   1630         // Ignore stale requests from last poll
   1631         if (ar.userObj != mPollingContext) return;
   1632 
   1633         if (ar.exception != null) {
   1634             CommandException.Error err=null;
   1635 
   1636             if (ar.exception instanceof IllegalStateException) {
   1637                 log("handlePollStateResult exception " + ar.exception);
   1638             }
   1639 
   1640             if (ar.exception instanceof CommandException) {
   1641                 err = ((CommandException)(ar.exception)).getCommandError();
   1642             }
   1643 
   1644             if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
   1645                 // Radio has crashed or turned off
   1646                 cancelPollState();
   1647                 return;
   1648             }
   1649 
   1650             if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
   1651                 loge("RIL implementation has returned an error where it must succeed" +
   1652                         ar.exception);
   1653             }
   1654         } else try {
   1655             handlePollStateResultMessage(what, ar);
   1656         } catch (RuntimeException ex) {
   1657             loge("Exception while polling service state. Probably malformed RIL response." + ex);
   1658         }
   1659 
   1660         mPollingContext[0]--;
   1661 
   1662         if (mPollingContext[0] == 0) {
   1663             if (mPhone.isPhoneTypeGsm()) {
   1664                 updateRoamingState();
   1665                 mNewSS.setEmergencyOnly(mEmergencyOnly);
   1666             } else {
   1667                 boolean namMatch = false;
   1668                 if (!isSidsAllZeros() && isHomeSid(mNewSS.getCdmaSystemId())) {
   1669                     namMatch = true;
   1670                 }
   1671 
   1672                 // Setting SS Roaming (general)
   1673                 if (mIsSubscriptionFromRuim) {
   1674                     boolean isRoamingBetweenOperators = isRoamingBetweenOperators(
   1675                             mNewSS.getVoiceRoaming(), mNewSS);
   1676                     if (isRoamingBetweenOperators != mNewSS.getVoiceRoaming()) {
   1677                         log("isRoamingBetweenOperators=" + isRoamingBetweenOperators
   1678                                 + ". Override CDMA voice roaming to " + isRoamingBetweenOperators);
   1679                         mNewSS.setVoiceRoaming(isRoamingBetweenOperators);
   1680                     }
   1681                 }
   1682                 /**
   1683                  * For CDMA, voice and data should have the same roaming status.
   1684                  * If voice is not in service, use TSB58 roaming indicator to set
   1685                  * data roaming status. If TSB58 roaming indicator is not in the
   1686                  * carrier-specified list of ERIs for home system then set roaming.
   1687                  */
   1688                 final int dataRat = mNewSS.getRilDataRadioTechnology();
   1689                 if (ServiceState.isCdma(dataRat)) {
   1690                     final boolean isVoiceInService =
   1691                             (mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
   1692                     if (isVoiceInService) {
   1693                         boolean isVoiceRoaming = mNewSS.getVoiceRoaming();
   1694                         if (mNewSS.getDataRoaming() != isVoiceRoaming) {
   1695                             log("Data roaming != Voice roaming. Override data roaming to "
   1696                                     + isVoiceRoaming);
   1697                             mNewSS.setDataRoaming(isVoiceRoaming);
   1698                         }
   1699                     } else {
   1700                         /**
   1701                          * As per VoiceRegStateResult from radio types.hal the TSB58
   1702                          * Roaming Indicator shall be sent if device is registered
   1703                          * on a CDMA or EVDO system.
   1704                          */
   1705                         boolean isRoamIndForHomeSystem = isRoamIndForHomeSystem(
   1706                                 Integer.toString(mRoamingIndicator));
   1707                         if (mNewSS.getDataRoaming() == isRoamIndForHomeSystem) {
   1708                             log("isRoamIndForHomeSystem=" + isRoamIndForHomeSystem
   1709                                     + ", override data roaming to " + !isRoamIndForHomeSystem);
   1710                             mNewSS.setDataRoaming(!isRoamIndForHomeSystem);
   1711                         }
   1712                     }
   1713                 }
   1714 
   1715                 // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
   1716                 mNewSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
   1717                 mNewSS.setCdmaRoamingIndicator(mRoamingIndicator);
   1718                 boolean isPrlLoaded = true;
   1719                 if (TextUtils.isEmpty(mPrlVersion)) {
   1720                     isPrlLoaded = false;
   1721                 }
   1722                 if (!isPrlLoaded || (mNewSS.getRilVoiceRadioTechnology()
   1723                         == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)) {
   1724                     log("Turn off roaming indicator if !isPrlLoaded or voice RAT is unknown");
   1725                     mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
   1726                 } else if (!isSidsAllZeros()) {
   1727                     if (!namMatch && !mIsInPrl) {
   1728                         // Use default
   1729                         mNewSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator);
   1730                     } else if (namMatch && !mIsInPrl) {
   1731                         // TODO this will be removed when we handle roaming on LTE on CDMA+LTE phones
   1732                         if (ServiceState.isLte(mNewSS.getRilVoiceRadioTechnology())) {
   1733                             log("Turn off roaming indicator as voice is LTE");
   1734                             mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
   1735                         } else {
   1736                             mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
   1737                         }
   1738                     } else if (!namMatch && mIsInPrl) {
   1739                         // Use the one from PRL/ERI
   1740                         mNewSS.setCdmaRoamingIndicator(mRoamingIndicator);
   1741                     } else {
   1742                         // It means namMatch && mIsInPrl
   1743                         if ((mRoamingIndicator <= 2)) {
   1744                             mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
   1745                         } else {
   1746                             // Use the one from PRL/ERI
   1747                             mNewSS.setCdmaRoamingIndicator(mRoamingIndicator);
   1748                         }
   1749                     }
   1750                 }
   1751 
   1752                 int roamingIndicator = mNewSS.getCdmaRoamingIndicator();
   1753                 mNewSS.setCdmaEriIconIndex(mPhone.mEriManager.getCdmaEriIconIndex(roamingIndicator,
   1754                         mDefaultRoamingIndicator));
   1755                 mNewSS.setCdmaEriIconMode(mPhone.mEriManager.getCdmaEriIconMode(roamingIndicator,
   1756                         mDefaultRoamingIndicator));
   1757 
   1758                 // NOTE: Some operator may require overriding mCdmaRoaming
   1759                 // (set by the modem), depending on the mRoamingIndicator.
   1760 
   1761                 if (DBG) {
   1762                     log("Set CDMA Roaming Indicator to: " + mNewSS.getCdmaRoamingIndicator()
   1763                             + ". voiceRoaming = " + mNewSS.getVoiceRoaming()
   1764                             + ". dataRoaming = " + mNewSS.getDataRoaming()
   1765                             + ", isPrlLoaded = " + isPrlLoaded
   1766                             + ". namMatch = " + namMatch + " , mIsInPrl = " + mIsInPrl
   1767                             + ", mRoamingIndicator = " + mRoamingIndicator
   1768                             + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
   1769                 }
   1770             }
   1771             pollStateDone();
   1772         }
   1773 
   1774     }
   1775 
   1776     /**
   1777      * Set roaming state when cdmaRoaming is true and ons is different from spn
   1778      * @param cdmaRoaming TS 27.007 7.2 CREG registered roaming
   1779      * @param s ServiceState hold current ons
   1780      * @return true for roaming state set
   1781      */
   1782     private boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
   1783         return cdmaRoaming && !isSameOperatorNameFromSimAndSS(s);
   1784     }
   1785 
   1786     void handlePollStateResultMessage(int what, AsyncResult ar) {
   1787         int ints[];
   1788         switch (what) {
   1789             case EVENT_POLL_STATE_REGISTRATION: {
   1790                 NetworkRegistrationState networkRegState = (NetworkRegistrationState) ar.result;
   1791                 VoiceSpecificRegistrationStates voiceSpecificStates =
   1792                         networkRegState.getVoiceSpecificStates();
   1793 
   1794                 int registrationState = networkRegState.getRegState();
   1795                 int cssIndicator = voiceSpecificStates.cssSupported ? 1 : 0;
   1796                 int newVoiceRat = ServiceState.networkTypeToRilRadioTechnology(
   1797                         networkRegState.getAccessNetworkTechnology());
   1798 
   1799                 mNewSS.setVoiceRegState(regCodeToServiceState(registrationState));
   1800                 mNewSS.setCssIndicator(cssIndicator);
   1801                 mNewSS.setRilVoiceRadioTechnology(newVoiceRat);
   1802                 mNewSS.addNetworkRegistrationState(networkRegState);
   1803                 setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
   1804 
   1805                 //Denial reason if registrationState = 3
   1806                 int reasonForDenial = networkRegState.getReasonForDenial();
   1807                 if (mPhone.isPhoneTypeGsm()) {
   1808 
   1809                     mGsmRoaming = regCodeIsRoaming(registrationState);
   1810                     mNewRejectCode = reasonForDenial;
   1811 
   1812                     boolean isVoiceCapable = mPhone.getContext().getResources()
   1813                             .getBoolean(com.android.internal.R.bool.config_voice_capable);
   1814                     mEmergencyOnly = networkRegState.isEmergencyEnabled();
   1815                 } else {
   1816                     int roamingIndicator = voiceSpecificStates.roamingIndicator;
   1817 
   1818                     //Indicates if current system is in PR
   1819                     int systemIsInPrl = voiceSpecificStates.systemIsInPrl;
   1820 
   1821                     //Is default roaming indicator from PRL
   1822                     int defaultRoamingIndicator = voiceSpecificStates.defaultRoamingIndicator;
   1823 
   1824                     mRegistrationState = registrationState;
   1825                     // When registration state is roaming and TSB58
   1826                     // roaming indicator is not in the carrier-specified
   1827                     // list of ERIs for home system, mCdmaRoaming is true.
   1828                     boolean cdmaRoaming =
   1829                             regCodeIsRoaming(registrationState)
   1830                                     && !isRoamIndForHomeSystem(
   1831                                             Integer.toString(roamingIndicator));
   1832                     mNewSS.setVoiceRoaming(cdmaRoaming);
   1833                     mRoamingIndicator = roamingIndicator;
   1834                     mIsInPrl = (systemIsInPrl == 0) ? false : true;
   1835                     mDefaultRoamingIndicator = defaultRoamingIndicator;
   1836 
   1837                     int systemId = 0;
   1838                     int networkId = 0;
   1839                     CellIdentity cellIdentity = networkRegState.getCellIdentity();
   1840                     if (cellIdentity != null && cellIdentity.getType() == CellInfoType.CDMA) {
   1841                         systemId = ((CellIdentityCdma) cellIdentity).getSystemId();
   1842                         networkId = ((CellIdentityCdma) cellIdentity).getNetworkId();
   1843                     }
   1844                     mNewSS.setCdmaSystemAndNetworkId(systemId, networkId);
   1845 
   1846                     if (reasonForDenial == 0) {
   1847                         mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
   1848                     } else if (reasonForDenial == 1) {
   1849                         mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
   1850                     } else {
   1851                         mRegistrationDeniedReason = "";
   1852                     }
   1853 
   1854                     if (mRegistrationState == 3) {
   1855                         if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
   1856                     }
   1857                 }
   1858 
   1859                 processCellLocationInfo(mNewCellLoc, networkRegState.getCellIdentity());
   1860 
   1861                 if (DBG) {
   1862                     log("handlPollVoiceRegResultMessage: regState=" + registrationState
   1863                             + " radioTechnology=" + newVoiceRat);
   1864                 }
   1865                 break;
   1866             }
   1867 
   1868             case EVENT_POLL_STATE_GPRS: {
   1869                 NetworkRegistrationState networkRegState = (NetworkRegistrationState) ar.result;
   1870                 DataSpecificRegistrationStates dataSpecificStates =
   1871                         networkRegState.getDataSpecificStates();
   1872                 int registrationState = networkRegState.getRegState();
   1873                 int serviceState = regCodeToServiceState(registrationState);
   1874                 int newDataRat = ServiceState.networkTypeToRilRadioTechnology(
   1875                         networkRegState.getAccessNetworkTechnology());
   1876                 mNewSS.setDataRegState(serviceState);
   1877                 mNewSS.setRilDataRadioTechnology(newDataRat);
   1878                 mNewSS.addNetworkRegistrationState(networkRegState);
   1879 
   1880                 // When we receive OOS reset the PhyChanConfig list so that non-return-to-idle
   1881                 // implementers of PhyChanConfig unsol will not carry forward a CA report
   1882                 // (2 or more cells) to a new cell if they camp for emergency service only.
   1883                 if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
   1884                     mLastPhysicalChannelConfigList = null;
   1885                 }
   1886                 setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
   1887 
   1888                 if (mPhone.isPhoneTypeGsm()) {
   1889 
   1890                     mNewReasonDataDenied = networkRegState.getReasonForDenial();
   1891                     mNewMaxDataCalls = dataSpecificStates.maxDataCalls;
   1892                     mDataRoaming = regCodeIsRoaming(registrationState);
   1893                     // Save the data roaming state reported by modem registration before resource
   1894                     // overlay or carrier config possibly overrides it.
   1895                     mNewSS.setDataRoamingFromRegistration(mDataRoaming);
   1896 
   1897                     if (DBG) {
   1898                         log("handlPollStateResultMessage: GsmSST dataServiceState=" + serviceState
   1899                                 + " regState=" + registrationState
   1900                                 + " dataRadioTechnology=" + newDataRat);
   1901                     }
   1902                 } else if (mPhone.isPhoneTypeCdma()) {
   1903 
   1904                     boolean isDataRoaming = regCodeIsRoaming(registrationState);
   1905                     mNewSS.setDataRoaming(isDataRoaming);
   1906                     // Save the data roaming state reported by modem registration before resource
   1907                     // overlay or carrier config possibly overrides it.
   1908                     mNewSS.setDataRoamingFromRegistration(isDataRoaming);
   1909 
   1910                     if (DBG) {
   1911                         log("handlPollStateResultMessage: cdma dataServiceState=" + serviceState
   1912                                 + " regState=" + registrationState
   1913                                 + " dataRadioTechnology=" + newDataRat);
   1914                     }
   1915                 } else {
   1916 
   1917                     // If the unsolicited signal strength comes just before data RAT family changes
   1918                     // (i.e. from UNKNOWN to LTE, CDMA to LTE, LTE to CDMA), the signal bar might
   1919                     // display the wrong information until the next unsolicited signal strength
   1920                     // information coming from the modem, which might take a long time to come or
   1921                     // even not come at all.  In order to provide the best user experience, we
   1922                     // query the latest signal information so it will show up on the UI on time.
   1923                     int oldDataRAT = mSS.getRilDataRadioTechnology();
   1924                     if (((oldDataRAT == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)
   1925                             && (newDataRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN))
   1926                             || (ServiceState.isCdma(oldDataRAT) && ServiceState.isLte(newDataRat))
   1927                             || (ServiceState.isLte(oldDataRAT)
   1928                             && ServiceState.isCdma(newDataRat))) {
   1929                         mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
   1930                     }
   1931 
   1932                     // voice roaming state in done while handling EVENT_POLL_STATE_REGISTRATION_CDMA
   1933                     boolean isDataRoaming = regCodeIsRoaming(registrationState);
   1934                     mNewSS.setDataRoaming(isDataRoaming);
   1935                     // Save the data roaming state reported by modem registration before resource
   1936                     // overlay or carrier config possibly overrides it.
   1937                     mNewSS.setDataRoamingFromRegistration(isDataRoaming);
   1938                     if (DBG) {
   1939                         log("handlPollStateResultMessage: CdmaLteSST dataServiceState="
   1940                                 + serviceState + " registrationState=" + registrationState
   1941                                 + " dataRadioTechnology=" + newDataRat);
   1942                     }
   1943                 }
   1944 
   1945                 updateServiceStateLteEarfcnBoost(mNewSS,
   1946                         getLteEarfcn(networkRegState.getCellIdentity()));
   1947                 break;
   1948             }
   1949 
   1950             case EVENT_POLL_STATE_OPERATOR: {
   1951                 if (mPhone.isPhoneTypeGsm()) {
   1952                     String opNames[] = (String[]) ar.result;
   1953 
   1954                     if (opNames != null && opNames.length >= 3) {
   1955                         // FIXME: Giving brandOverride higher precedence, is this desired?
   1956                         String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null
   1957                                 ? mUiccController.getUiccCard(getPhoneId())
   1958                                         .getOperatorBrandOverride() : null;
   1959                         if (brandOverride != null) {
   1960                             log("EVENT_POLL_STATE_OPERATOR: use brandOverride=" + brandOverride);
   1961                             mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
   1962                         } else {
   1963                             mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
   1964                         }
   1965                     }
   1966                 } else {
   1967                     String opNames[] = (String[])ar.result;
   1968 
   1969                     if (opNames != null && opNames.length >= 3) {
   1970                         // TODO: Do we care about overriding in this case.
   1971                         // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
   1972                         if ((opNames[2] == null) || (opNames[2].length() < 5)
   1973                                 || ("00000".equals(opNames[2]))) {
   1974                             opNames[2] = SystemProperties.get(
   1975                                     GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
   1976                             if (DBG) {
   1977                                 log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
   1978                                         " is bad. Using SystemProperties '" +
   1979                                         GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
   1980                                         "'= " + opNames[2]);
   1981                             }
   1982                         }
   1983 
   1984                         if (!mIsSubscriptionFromRuim) {
   1985                             // NV device (as opposed to CSIM)
   1986                             mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
   1987                         } else {
   1988                             String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null
   1989                                     ? mUiccController.getUiccCard(getPhoneId())
   1990                                     .getOperatorBrandOverride() : null;
   1991                             if (brandOverride != null) {
   1992                                 mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
   1993                             } else {
   1994                                 mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
   1995                             }
   1996                         }
   1997                     } else {
   1998                         if (DBG) log("EVENT_POLL_STATE_OPERATOR_CDMA: error parsing opNames");
   1999                     }
   2000                 }
   2001                 break;
   2002             }
   2003 
   2004             case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: {
   2005                 ints = (int[])ar.result;
   2006                 mNewSS.setIsManualSelection(ints[0] == 1);
   2007                 if ((ints[0] == 1) && (mPhone.shouldForceAutoNetworkSelect())) {
   2008                         /*
   2009                          * modem is currently in manual selection but manual
   2010                          * selection is not allowed in the current mode so
   2011                          * switch to automatic registration
   2012                          */
   2013                     mPhone.setNetworkSelectionModeAutomatic (null);
   2014                     log(" Forcing Automatic Network Selection, " +
   2015                             "manual selection is not allowed");
   2016                 }
   2017                 break;
   2018             }
   2019 
   2020             default:
   2021                 loge("handlePollStateResultMessage: Unexpected RIL response received: " + what);
   2022         }
   2023     }
   2024 
   2025     private static boolean isValidLteBandwidthKhz(int bandwidth) {
   2026         // Valid bandwidths, see 3gpp 36.101 sec. 5.6
   2027         switch (bandwidth) {
   2028             case 1400:
   2029             case 3000:
   2030             case 5000:
   2031             case 10000:
   2032             case 15000:
   2033             case 20000:
   2034                 return true;
   2035             default:
   2036                 return false;
   2037         }
   2038     }
   2039 
   2040     private void setPhyCellInfoFromCellIdentity(ServiceState ss, CellIdentity cellIdentity) {
   2041         if (cellIdentity == null) {
   2042             if (DBG) {
   2043                 log("Could not set ServiceState channel number. CellIdentity null");
   2044             }
   2045             return;
   2046         }
   2047 
   2048         ss.setChannelNumber(cellIdentity.getChannelNumber());
   2049         if (VDBG) {
   2050             log("Setting channel number: " + cellIdentity.getChannelNumber());
   2051         }
   2052 
   2053         if (cellIdentity instanceof CellIdentityLte) {
   2054             CellIdentityLte cl = (CellIdentityLte) cellIdentity;
   2055             int[] bandwidths = null;
   2056             // Prioritize the PhysicalChannelConfig list because we might already be in carrier
   2057             // aggregation by the time poll state is performed.
   2058             if (!ArrayUtils.isEmpty(mLastPhysicalChannelConfigList)) {
   2059                 bandwidths = getBandwidthsFromConfigs(mLastPhysicalChannelConfigList);
   2060                 for (int bw : bandwidths) {
   2061                     if (!isValidLteBandwidthKhz(bw)) {
   2062                         loge("Invalid LTE Bandwidth in RegistrationState, " + bw);
   2063                         bandwidths = null;
   2064                         break;
   2065                     }
   2066                 }
   2067             }
   2068             // If we don't have a PhysicalChannelConfig[] list, then pull from CellIdentityLte.
   2069             // This is normal if we're in idle mode and the PhysicalChannelConfig[] has already
   2070             // been updated. This is also a fallback in case the PhysicalChannelConfig info
   2071             // is invalid (ie, broken).
   2072             // Also, for vendor implementations that do not report return-to-idle, we should
   2073             // prioritize the bandwidth report in the CellIdentity, because the physical channel
   2074             // config report may be stale in the case where a single carrier was used previously
   2075             // and we transition to camped-for-emergency (since we never have a physical
   2076             // channel active). In the normal case of single-carrier non-return-to-idle, the
   2077             // values *must* be the same, so it doesn't matter which is chosen.
   2078             if (bandwidths == null || bandwidths.length == 1) {
   2079                 final int cbw = cl.getBandwidth();
   2080                 if (isValidLteBandwidthKhz(cbw)) {
   2081                     bandwidths = new int[] {cbw};
   2082                 } else if (cbw == Integer.MAX_VALUE) {
   2083                     // Bandwidth is unreported; c'est la vie. This is not an error because
   2084                     // pre-1.2 HAL implementations do not support bandwidth reporting.
   2085                 } else {
   2086                     loge("Invalid LTE Bandwidth in RegistrationState, " + cbw);
   2087                 }
   2088             }
   2089             if (bandwidths != null) {
   2090                 ss.setCellBandwidths(bandwidths);
   2091             }
   2092         } else {
   2093             if (VDBG) log("Skipping bandwidth update for Non-LTE cell.");
   2094         }
   2095     }
   2096 
   2097     /**
   2098      * Determine whether a roaming indicator is in the carrier-specified list of ERIs for
   2099      * home system
   2100      *
   2101      * @param roamInd roaming indicator in String
   2102      * @return true if the roamInd is in the carrier-specified list of ERIs for home network
   2103      */
   2104     private boolean isRoamIndForHomeSystem(String roamInd) {
   2105         // retrieve the carrier-specified list of ERIs for home system
   2106         String[] homeRoamIndicators = Resources.getSystem()
   2107                 .getStringArray(com.android.internal.R.array.config_cdma_home_system);
   2108         log("isRoamIndForHomeSystem: homeRoamIndicators=" + Arrays.toString(homeRoamIndicators));
   2109 
   2110         if (homeRoamIndicators != null) {
   2111             // searches through the comma-separated list for a match,
   2112             // return true if one is found.
   2113             for (String homeRoamInd : homeRoamIndicators) {
   2114                 if (homeRoamInd.equals(roamInd)) {
   2115                     return true;
   2116                 }
   2117             }
   2118             // no matches found against the list!
   2119             log("isRoamIndForHomeSystem: No match found against list for roamInd=" + roamInd);
   2120             return false;
   2121         }
   2122 
   2123         // no system property found for the roaming indicators for home system
   2124         log("isRoamIndForHomeSystem: No list found");
   2125         return false;
   2126     }
   2127 
   2128     /**
   2129      * Query the carrier configuration to determine if there any network overrides
   2130      * for roaming or not roaming for the current service state.
   2131      */
   2132     protected void updateRoamingState() {
   2133         if (mPhone.isPhoneTypeGsm()) {
   2134             /**
   2135              * Since the roaming state of gsm service (from +CREG) and
   2136              * data service (from +CGREG) could be different, the new SS
   2137              * is set to roaming when either is true.
   2138              *
   2139              * There are exceptions for the above rule.
   2140              * The new SS is not set as roaming while gsm service reports
   2141              * roaming but indeed it is same operator.
   2142              * And the operator is considered non roaming.
   2143              *
   2144              * The test for the operators is to handle special roaming
   2145              * agreements and MVNO's.
   2146              */
   2147             boolean roaming = (mGsmRoaming || mDataRoaming);
   2148 
   2149             if (mGsmRoaming && !isOperatorConsideredRoaming(mNewSS)
   2150                     && (isSameNamedOperators(mNewSS) || isOperatorConsideredNonRoaming(mNewSS))) {
   2151                 log("updateRoamingState: resource override set non roaming.isSameNamedOperators="
   2152                         + isSameNamedOperators(mNewSS) + ",isOperatorConsideredNonRoaming="
   2153                         + isOperatorConsideredNonRoaming(mNewSS));
   2154                 roaming = false;
   2155             }
   2156 
   2157             CarrierConfigManager configLoader = (CarrierConfigManager)
   2158                     mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
   2159 
   2160             if (configLoader != null) {
   2161                 try {
   2162                     PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId());
   2163 
   2164                     if (alwaysOnHomeNetwork(b)) {
   2165                         log("updateRoamingState: carrier config override always on home network");
   2166                         roaming = false;
   2167                     } else if (isNonRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())) {
   2168                         log("updateRoamingState: carrier config override set non roaming:"
   2169                                 + mNewSS.getOperatorNumeric());
   2170                         roaming = false;
   2171                     } else if (isRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())) {
   2172                         log("updateRoamingState: carrier config override set roaming:"
   2173                                 + mNewSS.getOperatorNumeric());
   2174                         roaming = true;
   2175                     }
   2176                 } catch (Exception e) {
   2177                     loge("updateRoamingState: unable to access carrier config service");
   2178                 }
   2179             } else {
   2180                 log("updateRoamingState: no carrier config service available");
   2181             }
   2182 
   2183             mNewSS.setVoiceRoaming(roaming);
   2184             mNewSS.setDataRoaming(roaming);
   2185         } else {
   2186             CarrierConfigManager configLoader = (CarrierConfigManager)
   2187                     mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
   2188             if (configLoader != null) {
   2189                 try {
   2190                     PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId());
   2191                     String systemId = Integer.toString(mNewSS.getCdmaSystemId());
   2192 
   2193                     if (alwaysOnHomeNetwork(b)) {
   2194                         log("updateRoamingState: carrier config override always on home network");
   2195                         setRoamingOff();
   2196                     } else if (isNonRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())
   2197                             || isNonRoamingInCdmaNetwork(b, systemId)) {
   2198                         log("updateRoamingState: carrier config override set non-roaming:"
   2199                                 + mNewSS.getOperatorNumeric() + ", " + systemId);
   2200                         setRoamingOff();
   2201                     } else if (isRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())
   2202                             || isRoamingInCdmaNetwork(b, systemId)) {
   2203                         log("updateRoamingState: carrier config override set roaming:"
   2204                                 + mNewSS.getOperatorNumeric() + ", " + systemId);
   2205                         setRoamingOn();
   2206                     }
   2207                 } catch (Exception e) {
   2208                     loge("updateRoamingState: unable to access carrier config service");
   2209                 }
   2210             } else {
   2211                 log("updateRoamingState: no carrier config service available");
   2212             }
   2213 
   2214             if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
   2215                 mNewSS.setVoiceRoaming(true);
   2216                 mNewSS.setDataRoaming(true);
   2217             }
   2218         }
   2219     }
   2220 
   2221     private void setRoamingOn() {
   2222         mNewSS.setVoiceRoaming(true);
   2223         mNewSS.setDataRoaming(true);
   2224         mNewSS.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_ON);
   2225         mNewSS.setCdmaEriIconMode(EriInfo.ROAMING_ICON_MODE_NORMAL);
   2226     }
   2227 
   2228     private void setRoamingOff() {
   2229         mNewSS.setVoiceRoaming(false);
   2230         mNewSS.setDataRoaming(false);
   2231         mNewSS.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_OFF);
   2232     }
   2233 
   2234     protected void updateSpnDisplay() {
   2235         updateOperatorNameFromEri();
   2236 
   2237         String wfcVoiceSpnFormat = null;
   2238         String wfcDataSpnFormat = null;
   2239         int combinedRegState = getCombinedRegState();
   2240         if (mPhone.getImsPhone() != null && mPhone.getImsPhone().isWifiCallingEnabled()
   2241                 && (combinedRegState == ServiceState.STATE_IN_SERVICE)) {
   2242             // In Wi-Fi Calling mode show SPN or PLMN + WiFi Calling
   2243             //
   2244             // 1) Show SPN + Wi-Fi Calling If SIM has SPN and SPN display condition
   2245             //    is satisfied or SPN override is enabled for this carrier
   2246             //
   2247             // 2) Show PLMN + Wi-Fi Calling if there is no valid SPN in case 1
   2248 
   2249             String[] wfcSpnFormats = mPhone.getContext().getResources().getStringArray(
   2250                     com.android.internal.R.array.wfcSpnFormats);
   2251             int voiceIdx = 0;
   2252             int dataIdx = 0;
   2253             CarrierConfigManager configLoader = (CarrierConfigManager)
   2254                     mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
   2255             if (configLoader != null) {
   2256                 try {
   2257                     PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId());
   2258                     if (b != null) {
   2259                         voiceIdx = b.getInt(CarrierConfigManager.KEY_WFC_SPN_FORMAT_IDX_INT);
   2260                         dataIdx = b.getInt(
   2261                                 CarrierConfigManager.KEY_WFC_DATA_SPN_FORMAT_IDX_INT);
   2262                     }
   2263                 } catch (Exception e) {
   2264                     loge("updateSpnDisplay: carrier config error: " + e);
   2265                 }
   2266             }
   2267 
   2268             wfcVoiceSpnFormat = wfcSpnFormats[voiceIdx];
   2269             wfcDataSpnFormat = wfcSpnFormats[dataIdx];
   2270         }
   2271 
   2272         if (mPhone.isPhoneTypeGsm()) {
   2273             // The values of plmn/showPlmn change in different scenarios.
   2274             // 1) No service but emergency call allowed -> expected
   2275             //    to show "Emergency call only"
   2276             //    EXTRA_SHOW_PLMN = true
   2277             //    EXTRA_PLMN = "Emergency call only"
   2278 
   2279             // 2) No service at all --> expected to show "No service"
   2280             //    EXTRA_SHOW_PLMN = true
   2281             //    EXTRA_PLMN = "No service"
   2282 
   2283             // 3) Normal operation in either home or roaming service
   2284             //    EXTRA_SHOW_PLMN = depending on IccRecords rule
   2285             //    EXTRA_PLMN = plmn
   2286 
   2287             // 4) No service due to power off, aka airplane mode
   2288             //    EXTRA_SHOW_PLMN = false
   2289             //    EXTRA_PLMN = null
   2290 
   2291             IccRecords iccRecords = mIccRecords;
   2292             String plmn = null;
   2293             boolean showPlmn = false;
   2294             int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS) : 0;
   2295             boolean noService = false;
   2296             if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE
   2297                     || combinedRegState == ServiceState.STATE_EMERGENCY_ONLY) {
   2298                 showPlmn = true;
   2299 
   2300                 // Force display no service
   2301                 final boolean forceDisplayNoService = mPhone.getContext().getResources().getBoolean(
   2302                         com.android.internal.R.bool.config_display_no_service_when_sim_unready)
   2303                                 && !mIsSimReady;
   2304                 if (mEmergencyOnly && !forceDisplayNoService) {
   2305                     // No service but emergency call allowed
   2306                     plmn = Resources.getSystem().
   2307                             getText(com.android.internal.R.string.emergency_calls_only).toString();
   2308                 } else {
   2309                     // No service at all
   2310                     plmn = Resources.getSystem().
   2311                             getText(com.android.internal.R.string.lockscreen_carrier_default).toString();
   2312                     noService = true;
   2313                 }
   2314                 if (DBG) log("updateSpnDisplay: radio is on but out " +
   2315                         "of service, set plmn='" + plmn + "'");
   2316             } else if (combinedRegState == ServiceState.STATE_IN_SERVICE) {
   2317                 // In either home or roaming service
   2318                 plmn = mSS.getOperatorAlpha();
   2319                 showPlmn = !TextUtils.isEmpty(plmn) &&
   2320                         ((rule & SIMRecords.SPN_RULE_SHOW_PLMN)
   2321                                 == SIMRecords.SPN_RULE_SHOW_PLMN);
   2322             } else {
   2323                 // Power off state, such as airplane mode, show plmn as "No service"
   2324                 showPlmn = true;
   2325                 plmn = Resources.getSystem().
   2326                         getText(com.android.internal.R.string.lockscreen_carrier_default).toString();
   2327                 if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn="
   2328                         + showPlmn + " plmn=" + plmn);
   2329             }
   2330 
   2331             // The value of spn/showSpn are same in different scenarios.
   2332             //    EXTRA_SHOW_SPN = depending on IccRecords rule and radio/IMS state
   2333             //    EXTRA_SPN = spn
   2334             //    EXTRA_DATA_SPN = dataSpn
   2335             String spn = (iccRecords != null) ? iccRecords.getServiceProviderName() : "";
   2336             String dataSpn = spn;
   2337             boolean showSpn = !noService && !TextUtils.isEmpty(spn)
   2338                     && ((rule & SIMRecords.SPN_RULE_SHOW_SPN)
   2339                     == SIMRecords.SPN_RULE_SHOW_SPN);
   2340 
   2341             if (!TextUtils.isEmpty(spn) && !TextUtils.isEmpty(wfcVoiceSpnFormat) &&
   2342                     !TextUtils.isEmpty(wfcDataSpnFormat)) {
   2343                 // Show SPN + Wi-Fi Calling If SIM has SPN and SPN display condition
   2344                 // is satisfied or SPN override is enabled for this carrier.
   2345 
   2346                 String originalSpn = spn.trim();
   2347                 spn = String.format(wfcVoiceSpnFormat, originalSpn);
   2348                 dataSpn = String.format(wfcDataSpnFormat, originalSpn);
   2349                 showSpn = true;
   2350                 showPlmn = false;
   2351             } else if (!TextUtils.isEmpty(plmn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)) {
   2352                 // Show PLMN + Wi-Fi Calling if there is no valid SPN in the above case
   2353 
   2354                 String originalPlmn = plmn.trim();
   2355                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
   2356             } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF
   2357                     || (showPlmn && TextUtils.equals(spn, plmn))) {
   2358                 // airplane mode or spn equals plmn, do not show spn
   2359                 spn = null;
   2360                 showSpn = false;
   2361             }
   2362 
   2363             int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
   2364             int[] subIds = SubscriptionManager.getSubId(mPhone.getPhoneId());
   2365             if (subIds != null && subIds.length > 0) {
   2366                 subId = subIds[0];
   2367             }
   2368 
   2369             // Update SPN_STRINGS_UPDATED_ACTION IFF any value changes
   2370             if (mSubId != subId ||
   2371                     showPlmn != mCurShowPlmn
   2372                     || showSpn != mCurShowSpn
   2373                     || !TextUtils.equals(spn, mCurSpn)
   2374                     || !TextUtils.equals(dataSpn, mCurDataSpn)
   2375                     || !TextUtils.equals(plmn, mCurPlmn)) {
   2376                 if (DBG) {
   2377                     log(String.format("updateSpnDisplay: changed sending intent rule=" + rule +
   2378                             " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s' dataSpn='%s' " +
   2379                             "subId='%d'", showPlmn, plmn, showSpn, spn, dataSpn, subId));
   2380                 }
   2381                 Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
   2382                 intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn);
   2383                 intent.putExtra(TelephonyIntents.EXTRA_SPN, spn);
   2384                 intent.putExtra(TelephonyIntents.EXTRA_DATA_SPN, dataSpn);
   2385                 intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
   2386                 intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
   2387                 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
   2388                 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   2389 
   2390                 if (!mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(),
   2391                         showPlmn, plmn, showSpn, spn)) {
   2392                     mSpnUpdatePending = true;
   2393                 }
   2394             }
   2395 
   2396             mSubId = subId;
   2397             mCurShowSpn = showSpn;
   2398             mCurShowPlmn = showPlmn;
   2399             mCurSpn = spn;
   2400             mCurDataSpn = dataSpn;
   2401             mCurPlmn = plmn;
   2402         } else {
   2403             // mOperatorAlpha contains the ERI text
   2404             String plmn = mSS.getOperatorAlpha();
   2405             boolean showPlmn = false;
   2406 
   2407             showPlmn = plmn != null;
   2408 
   2409             int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
   2410             int[] subIds = SubscriptionManager.getSubId(mPhone.getPhoneId());
   2411             if (subIds != null && subIds.length > 0) {
   2412                 subId = subIds[0];
   2413             }
   2414 
   2415             if (!TextUtils.isEmpty(plmn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)) {
   2416                 // In Wi-Fi Calling mode show SPN+WiFi
   2417 
   2418                 String originalPlmn = plmn.trim();
   2419                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
   2420             } else if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
   2421                 // todo: temporary hack; should have a better fix. This is to avoid using operator
   2422                 // name from ServiceState (populated in resetServiceStateInIwlanMode()) until
   2423                 // wifi calling is actually enabled
   2424                 log("updateSpnDisplay: overwriting plmn from " + plmn + " to null as radio " +
   2425                         "state is off");
   2426                 plmn = null;
   2427             }
   2428 
   2429             if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE) {
   2430                 plmn = Resources.getSystem().getText(com.android.internal.R.string
   2431                         .lockscreen_carrier_default).toString();
   2432                 if (DBG) {
   2433                     log("updateSpnDisplay: radio is on but out of svc, set plmn='" + plmn + "'");
   2434                 }
   2435             }
   2436 
   2437             if (mSubId != subId || !TextUtils.equals(plmn, mCurPlmn)) {
   2438                 // Allow A blank plmn, "" to set showPlmn to true. Previously, we
   2439                 // would set showPlmn to true only if plmn was not empty, i.e. was not
   2440                 // null and not blank. But this would cause us to incorrectly display
   2441                 // "No Service". Now showPlmn is set to true for any non null string.
   2442                 if (DBG) {
   2443                     log(String.format("updateSpnDisplay: changed sending intent" +
   2444                             " showPlmn='%b' plmn='%s' subId='%d'", showPlmn, plmn, subId));
   2445                 }
   2446                 Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
   2447                 intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, false);
   2448                 intent.putExtra(TelephonyIntents.EXTRA_SPN, "");
   2449                 intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
   2450                 intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
   2451                 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
   2452                 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   2453 
   2454                 if (!mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(),
   2455                         showPlmn, plmn, false, "")) {
   2456                     mSpnUpdatePending = true;
   2457                 }
   2458             }
   2459 
   2460             mSubId = subId;
   2461             mCurShowSpn = false;
   2462             mCurShowPlmn = showPlmn;
   2463             mCurSpn = "";
   2464             mCurPlmn = plmn;
   2465         }
   2466     }
   2467 
   2468     protected void setPowerStateToDesired() {
   2469         if (DBG) {
   2470             String tmpLog = "mDeviceShuttingDown=" + mDeviceShuttingDown +
   2471                     ", mDesiredPowerState=" + mDesiredPowerState +
   2472                     ", getRadioState=" + mCi.getRadioState() +
   2473                     ", mPowerOffDelayNeed=" + mPowerOffDelayNeed +
   2474                     ", mAlarmSwitch=" + mAlarmSwitch +
   2475                     ", mRadioDisabledByCarrier=" + mRadioDisabledByCarrier;
   2476             log(tmpLog);
   2477             mRadioPowerLog.log(tmpLog);
   2478         }
   2479 
   2480         if (mPhone.isPhoneTypeGsm() && mAlarmSwitch) {
   2481             if(DBG) log("mAlarmSwitch == true");
   2482             Context context = mPhone.getContext();
   2483             AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
   2484             am.cancel(mRadioOffIntent);
   2485             mAlarmSwitch = false;
   2486         }
   2487 
   2488         // If we want it on and it's off, turn it on
   2489         if (mDesiredPowerState && !mRadioDisabledByCarrier
   2490                 && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
   2491             mCi.setRadioPower(true, null);
   2492         } else if ((!mDesiredPowerState || mRadioDisabledByCarrier) && mCi.getRadioState().isOn()) {
   2493             // If it's on and available and we want it off gracefully
   2494             if (mPhone.isPhoneTypeGsm() && mPowerOffDelayNeed) {
   2495                 if (mImsRegistrationOnOff && !mAlarmSwitch) {
   2496                     if(DBG) log("mImsRegistrationOnOff == true");
   2497                     Context context = mPhone.getContext();
   2498                     AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
   2499 
   2500                     Intent intent = new Intent(ACTION_RADIO_OFF);
   2501                     mRadioOffIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
   2502 
   2503                     mAlarmSwitch = true;
   2504                     if (DBG) log("Alarm setting");
   2505                     am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
   2506                             SystemClock.elapsedRealtime() + 3000, mRadioOffIntent);
   2507                 } else {
   2508                     DcTracker dcTracker = mPhone.mDcTracker;
   2509                     powerOffRadioSafely(dcTracker);
   2510                 }
   2511             } else {
   2512                 DcTracker dcTracker = mPhone.mDcTracker;
   2513                 powerOffRadioSafely(dcTracker);
   2514             }
   2515         } else if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) {
   2516             mCi.requestShutdown(null);
   2517         }
   2518     }
   2519 
   2520     protected void onUpdateIccAvailability() {
   2521         if (mUiccController == null ) {
   2522             return;
   2523         }
   2524 
   2525         UiccCardApplication newUiccApplication = getUiccCardApplication();
   2526 
   2527         if (mUiccApplcation != newUiccApplication) {
   2528             if (mUiccApplcation != null) {
   2529                 log("Removing stale icc objects.");
   2530                 mUiccApplcation.unregisterForReady(this);
   2531                 if (mIccRecords != null) {
   2532                     mIccRecords.unregisterForRecordsLoaded(this);
   2533                 }
   2534                 mIccRecords = null;
   2535                 mUiccApplcation = null;
   2536             }
   2537             if (newUiccApplication != null) {
   2538                 log("New card found");
   2539                 mUiccApplcation = newUiccApplication;
   2540                 mIccRecords = mUiccApplcation.getIccRecords();
   2541                 if (mPhone.isPhoneTypeGsm()) {
   2542                     mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
   2543                     if (mIccRecords != null) {
   2544                         mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
   2545                     }
   2546                 } else if (mIsSubscriptionFromRuim) {
   2547                     mUiccApplcation.registerForReady(this, EVENT_RUIM_READY, null);
   2548                     if (mIccRecords != null) {
   2549                         mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
   2550                     }
   2551                 }
   2552             }
   2553         }
   2554     }
   2555 
   2556     private void logRoamingChange() {
   2557         mRoamingLog.log(mSS.toString());
   2558     }
   2559 
   2560     private void logAttachChange() {
   2561         mAttachLog.log(mSS.toString());
   2562     }
   2563 
   2564     private void logPhoneTypeChange() {
   2565         mPhoneTypeLog.log(Integer.toString(mPhone.getPhoneType()));
   2566     }
   2567 
   2568     private void logRatChange() {
   2569         mRatLog.log(mSS.toString());
   2570     }
   2571 
   2572     protected final void log(String s) {
   2573         Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s);
   2574     }
   2575 
   2576     protected final void loge(String s) {
   2577         Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s);
   2578     }
   2579 
   2580     /**
   2581      * @return The current GPRS state. IN_SERVICE is the same as "attached"
   2582      * and OUT_OF_SERVICE is the same as detached.
   2583      */
   2584     public int getCurrentDataConnectionState() {
   2585         return mSS.getDataRegState();
   2586     }
   2587 
   2588     /**
   2589      * @return true if phone is camping on a technology (eg UMTS)
   2590      * that could support voice and data simultaneously.
   2591      */
   2592     public boolean isConcurrentVoiceAndDataAllowed() {
   2593         if (mSS.getCssIndicator() == 1) {
   2594             // Checking the Concurrent Service Supported flag first for all phone types.
   2595             return true;
   2596         } else if (mPhone.isPhoneTypeGsm()) {
   2597             return (mSS.getRilDataRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
   2598         } else {
   2599             return false;
   2600         }
   2601     }
   2602 
   2603     /** Called when the service state of ImsPhone is changed. */
   2604     public void onImsServiceStateChanged() {
   2605         sendMessage(obtainMessage(EVENT_IMS_SERVICE_STATE_CHANGED));
   2606     }
   2607 
   2608     public void setImsRegistrationState(boolean registered) {
   2609         log("ImsRegistrationState - registered : " + registered);
   2610 
   2611         if (mImsRegistrationOnOff && !registered) {
   2612             if (mAlarmSwitch) {
   2613                 mImsRegistrationOnOff = registered;
   2614 
   2615                 Context context = mPhone.getContext();
   2616                 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
   2617                 am.cancel(mRadioOffIntent);
   2618                 mAlarmSwitch = false;
   2619 
   2620                 sendMessage(obtainMessage(EVENT_CHANGE_IMS_STATE));
   2621                 return;
   2622             }
   2623         }
   2624         mImsRegistrationOnOff = registered;
   2625     }
   2626 
   2627     public void onImsCapabilityChanged() {
   2628         sendMessage(obtainMessage(EVENT_IMS_CAPABILITY_CHANGED));
   2629     }
   2630 
   2631     public boolean isRadioOn() {
   2632         return mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON;
   2633     }
   2634 
   2635     /**
   2636      * A complete "service state" from our perspective is
   2637      * composed of a handful of separate requests to the radio.
   2638      *
   2639      * We make all of these requests at once, but then abandon them
   2640      * and start over again if the radio notifies us that some
   2641      * event has changed
   2642      */
   2643     public void pollState() {
   2644         pollState(false);
   2645     }
   2646     /**
   2647      * We insist on polling even if the radio says its off.
   2648      * Used when we get a network changed notification
   2649      * but the radio is off - part of iwlan hack
   2650      */
   2651     private void modemTriggeredPollState() {
   2652         pollState(true);
   2653     }
   2654 
   2655     public void pollState(boolean modemTriggered) {
   2656         mPollingContext = new int[1];
   2657         mPollingContext[0] = 0;
   2658 
   2659         log("pollState: modemTriggered=" + modemTriggered);
   2660 
   2661         switch (mCi.getRadioState()) {
   2662             case RADIO_UNAVAILABLE:
   2663                 mNewSS.setStateOutOfService();
   2664                 mNewCellLoc.setStateInvalid();
   2665                 setSignalStrengthDefaultValues();
   2666                 mNitzState.handleNetworkUnavailable();
   2667                 pollStateDone();
   2668                 break;
   2669 
   2670             case RADIO_OFF:
   2671                 mNewSS.setStateOff();
   2672                 mNewCellLoc.setStateInvalid();
   2673                 setSignalStrengthDefaultValues();
   2674                 mNitzState.handleNetworkUnavailable();
   2675                 // don't poll when device is shutting down or the poll was not modemTrigged
   2676                 // (they sent us new radio data) and current network is not IWLAN
   2677                 if (mDeviceShuttingDown ||
   2678                         (!modemTriggered && ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   2679                         != mSS.getRilDataRadioTechnology())) {
   2680                     pollStateDone();
   2681                     break;
   2682                 }
   2683 
   2684             default:
   2685                 // Issue all poll-related commands at once then count down the responses, which
   2686                 // are allowed to arrive out-of-order
   2687                 // TODO: Add WLAN support.
   2688                 mPollingContext[0]++;
   2689                 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));
   2690 
   2691                 mPollingContext[0]++;
   2692                 mRegStateManagers.get(AccessNetworkConstants.TransportType.WWAN)
   2693                         .getNetworkRegistrationState(NetworkRegistrationState.DOMAIN_PS,
   2694                         obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext));
   2695 
   2696                 mPollingContext[0]++;
   2697                 mRegStateManagers.get(AccessNetworkConstants.TransportType.WWAN)
   2698                         .getNetworkRegistrationState(NetworkRegistrationState.DOMAIN_CS,
   2699                         obtainMessage(EVENT_POLL_STATE_REGISTRATION, mPollingContext));
   2700 
   2701                 if (mPhone.isPhoneTypeGsm()) {
   2702                     mPollingContext[0]++;
   2703                     mCi.getNetworkSelectionMode(obtainMessage(
   2704                             EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));
   2705                 }
   2706                 break;
   2707         }
   2708     }
   2709 
   2710     private void pollStateDone() {
   2711         if (!mPhone.isPhoneTypeGsm()) {
   2712             updateRoamingState();
   2713         }
   2714 
   2715         if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
   2716             mNewSS.setVoiceRoaming(true);
   2717             mNewSS.setDataRoaming(true);
   2718         }
   2719         useDataRegStateForDataOnlyDevices();
   2720         resetServiceStateInIwlanMode();
   2721 
   2722         if (Build.IS_DEBUGGABLE && mPhone.mTelephonyTester != null) {
   2723             mPhone.mTelephonyTester.overrideServiceState(mNewSS);
   2724         }
   2725 
   2726         if (DBG) {
   2727             log("Poll ServiceState done: "
   2728                     + " oldSS=[" + mSS + "] newSS=[" + mNewSS + "]"
   2729                     + " oldMaxDataCalls=" + mMaxDataCalls
   2730                     + " mNewMaxDataCalls=" + mNewMaxDataCalls
   2731                     + " oldReasonDataDenied=" + mReasonDataDenied
   2732                     + " mNewReasonDataDenied=" + mNewReasonDataDenied);
   2733         }
   2734 
   2735         boolean hasRegistered =
   2736                 mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
   2737                         && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
   2738 
   2739         boolean hasDeregistered =
   2740                 mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
   2741                         && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
   2742 
   2743         boolean hasDataAttached =
   2744                 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
   2745                         && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
   2746 
   2747         boolean hasDataDetached =
   2748                 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
   2749                         && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
   2750 
   2751         boolean hasDataRegStateChanged =
   2752                 mSS.getDataRegState() != mNewSS.getDataRegState();
   2753 
   2754         boolean hasVoiceRegStateChanged =
   2755                 mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
   2756 
   2757         boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);
   2758 
   2759         // ratchet the new tech up through its rat family but don't drop back down
   2760         // until cell change or device is OOS
   2761         boolean isDataInService = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
   2762 
   2763         if (isDataInService) {
   2764             mRatRatcheter.ratchet(mSS, mNewSS, hasLocationChanged);
   2765         }
   2766 
   2767         boolean hasRilVoiceRadioTechnologyChanged =
   2768                 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
   2769 
   2770         boolean hasRilDataRadioTechnologyChanged =
   2771                 mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology();
   2772 
   2773         boolean hasChanged = !mNewSS.equals(mSS);
   2774 
   2775         boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
   2776 
   2777         boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming();
   2778 
   2779         boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming();
   2780 
   2781         boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming();
   2782 
   2783         boolean hasRejectCauseChanged = mRejectCode != mNewRejectCode;
   2784 
   2785         boolean hasCssIndicatorChanged = (mSS.getCssIndicator() != mNewSS.getCssIndicator());
   2786 
   2787         boolean has4gHandoff = false;
   2788         boolean hasMultiApnSupport = false;
   2789         boolean hasLostMultiApnSupport = false;
   2790         if (mPhone.isPhoneTypeCdmaLte()) {
   2791             has4gHandoff = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
   2792                     && ((ServiceState.isLte(mSS.getRilDataRadioTechnology())
   2793                     && (mNewSS.getRilDataRadioTechnology()
   2794                     == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
   2795                     ||
   2796                     ((mSS.getRilDataRadioTechnology()
   2797                             == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)
   2798                             && ServiceState.isLte(mNewSS.getRilDataRadioTechnology())));
   2799 
   2800             hasMultiApnSupport = ((ServiceState.isLte(mNewSS.getRilDataRadioTechnology())
   2801                     || (mNewSS.getRilDataRadioTechnology()
   2802                     == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
   2803                     &&
   2804                     (!ServiceState.isLte(mSS.getRilDataRadioTechnology())
   2805                             && (mSS.getRilDataRadioTechnology()
   2806                             != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
   2807 
   2808             hasLostMultiApnSupport =
   2809                     ((mNewSS.getRilDataRadioTechnology()
   2810                             >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)
   2811                             && (mNewSS.getRilDataRadioTechnology()
   2812                             <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A));
   2813         }
   2814 
   2815         if (DBG) {
   2816             log("pollStateDone:"
   2817                     + " hasRegistered=" + hasRegistered
   2818                     + " hasDeregistered=" + hasDeregistered
   2819                     + " hasDataAttached=" + hasDataAttached
   2820                     + " hasDataDetached=" + hasDataDetached
   2821                     + " hasDataRegStateChanged=" + hasDataRegStateChanged
   2822                     + " hasRilVoiceRadioTechnologyChanged= " + hasRilVoiceRadioTechnologyChanged
   2823                     + " hasRilDataRadioTechnologyChanged=" + hasRilDataRadioTechnologyChanged
   2824                     + " hasChanged=" + hasChanged
   2825                     + " hasVoiceRoamingOn=" + hasVoiceRoamingOn
   2826                     + " hasVoiceRoamingOff=" + hasVoiceRoamingOff
   2827                     + " hasDataRoamingOn=" + hasDataRoamingOn
   2828                     + " hasDataRoamingOff=" + hasDataRoamingOff
   2829                     + " hasLocationChanged=" + hasLocationChanged
   2830                     + " has4gHandoff = " + has4gHandoff
   2831                     + " hasMultiApnSupport=" + hasMultiApnSupport
   2832                     + " hasLostMultiApnSupport=" + hasLostMultiApnSupport
   2833                     + " hasCssIndicatorChanged=" + hasCssIndicatorChanged);
   2834         }
   2835 
   2836         // Add an event log when connection state changes
   2837         if (hasVoiceRegStateChanged || hasDataRegStateChanged) {
   2838             EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE :
   2839                             EventLogTags.CDMA_SERVICE_STATE_CHANGE,
   2840                     mSS.getVoiceRegState(), mSS.getDataRegState(),
   2841                     mNewSS.getVoiceRegState(), mNewSS.getDataRegState());
   2842         }
   2843 
   2844         if (mPhone.isPhoneTypeGsm()) {
   2845             // Add an event log when network type switched
   2846             // TODO: we may add filtering to reduce the event logged,
   2847             // i.e. check preferred network setting, only switch to 2G, etc
   2848             if (hasRilVoiceRadioTechnologyChanged) {
   2849                 int cid = -1;
   2850                 GsmCellLocation loc = (GsmCellLocation) mNewCellLoc;
   2851                 if (loc != null) cid = loc.getCid();
   2852                 // NOTE: this code was previously located after mSS and mNewSS are swapped, so
   2853                 // existing logs were incorrectly using the new state for "network_from"
   2854                 // and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag
   2855                 // to record the correct states.
   2856                 EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid,
   2857                         mSS.getRilVoiceRadioTechnology(),
   2858                         mNewSS.getRilVoiceRadioTechnology());
   2859                 if (DBG) {
   2860                     log("RAT switched "
   2861                             + ServiceState.rilRadioTechnologyToString(
   2862                             mSS.getRilVoiceRadioTechnology())
   2863                             + " -> "
   2864                             + ServiceState.rilRadioTechnologyToString(
   2865                             mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid);
   2866                 }
   2867             }
   2868 
   2869             if (hasCssIndicatorChanged) {
   2870                 mPhone.notifyDataConnection(Phone.REASON_CSS_INDICATOR_CHANGED);
   2871             }
   2872 
   2873             mReasonDataDenied = mNewReasonDataDenied;
   2874             mMaxDataCalls = mNewMaxDataCalls;
   2875             mRejectCode = mNewRejectCode;
   2876         }
   2877 
   2878         ServiceState oldMergedSS = mPhone.getServiceState();
   2879 
   2880         // swap mSS and mNewSS to put new state in mSS
   2881         ServiceState tss = mSS;
   2882         mSS = mNewSS;
   2883         mNewSS = tss;
   2884         // clean slate for next time
   2885         mNewSS.setStateOutOfService();
   2886 
   2887         // swap mCellLoc and mNewCellLoc to put new state in mCellLoc
   2888         CellLocation tcl = mCellLoc;
   2889         mCellLoc = mNewCellLoc;
   2890         mNewCellLoc = tcl;
   2891 
   2892         if (hasRilVoiceRadioTechnologyChanged) {
   2893             updatePhoneObject();
   2894         }
   2895 
   2896         TelephonyManager tm =
   2897                 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
   2898 
   2899         if (hasRilDataRadioTechnologyChanged) {
   2900             tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology());
   2901             StatsLog.write(StatsLog.MOBILE_RADIO_TECHNOLOGY_CHANGED,
   2902                     ServiceState.rilRadioTechnologyToNetworkType(mSS.getRilDataRadioTechnology()),
   2903                     mPhone.getPhoneId());
   2904 
   2905             if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   2906                     == mSS.getRilDataRadioTechnology()) {
   2907                 log("pollStateDone: IWLAN enabled");
   2908             }
   2909         }
   2910 
   2911         if (hasRegistered) {
   2912             mNetworkAttachedRegistrants.notifyRegistrants();
   2913             mNitzState.handleNetworkAvailable();
   2914         }
   2915 
   2916         if (hasDeregistered) {
   2917             mNetworkDetachedRegistrants.notifyRegistrants();
   2918             mNitzState.handleNetworkUnavailable();
   2919         }
   2920 
   2921         if (hasRejectCauseChanged) {
   2922             setNotification(CS_REJECT_CAUSE_ENABLED);
   2923         }
   2924 
   2925         if (hasChanged) {
   2926             updateSpnDisplay();
   2927 
   2928             tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlpha());
   2929 
   2930             String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId());
   2931             String prevCountryIsoCode = tm.getNetworkCountryIso(mPhone.getPhoneId());
   2932             String operatorNumeric = mSS.getOperatorNumeric();
   2933 
   2934             if (!mPhone.isPhoneTypeGsm()) {
   2935                 // try to fix the invalid Operator Numeric
   2936                 if (isInvalidOperatorNumeric(operatorNumeric)) {
   2937                     int sid = mSS.getCdmaSystemId();
   2938                     operatorNumeric = fixUnknownMcc(operatorNumeric, sid);
   2939                 }
   2940             }
   2941 
   2942             tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric);
   2943 
   2944             if (isInvalidOperatorNumeric(operatorNumeric)) {
   2945                 if (DBG) log("operatorNumeric " + operatorNumeric + " is invalid");
   2946                 // Passing empty string is important for the first update. The initial value of
   2947                 // operator numeric in locale tracker is null. The async update will allow getting
   2948                 // cell info from the modem instead of using the cached one.
   2949                 mLocaleTracker.updateOperatorNumericAsync("");
   2950                 mNitzState.handleNetworkUnavailable();
   2951             } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
   2952                 // If the device is on IWLAN, modems manufacture a ServiceState with the MCC/MNC of
   2953                 // the SIM as if we were talking to towers. Telephony code then uses that with
   2954                 // mccTable to suggest a timezone. We shouldn't do that if the MCC/MNC is from IWLAN
   2955 
   2956                 // Update IDD.
   2957                 if (!mPhone.isPhoneTypeGsm()) {
   2958                     setOperatorIdd(operatorNumeric);
   2959                 }
   2960 
   2961                 mLocaleTracker.updateOperatorNumericSync(operatorNumeric);
   2962                 String countryIsoCode = mLocaleTracker.getCurrentCountry();
   2963 
   2964                 // Update Time Zone.
   2965                 boolean iccCardExists = iccCardExists();
   2966                 boolean networkIsoChanged =
   2967                         networkCountryIsoChanged(countryIsoCode, prevCountryIsoCode);
   2968 
   2969                 // Determine countryChanged: networkIso is only reliable if there's an ICC card.
   2970                 boolean countryChanged = iccCardExists && networkIsoChanged;
   2971                 if (DBG) {
   2972                     long ctm = System.currentTimeMillis();
   2973                     log("Before handleNetworkCountryCodeKnown:"
   2974                             + " countryChanged=" + countryChanged
   2975                             + " iccCardExist=" + iccCardExists
   2976                             + " countryIsoChanged=" + networkIsoChanged
   2977                             + " operatorNumeric=" + operatorNumeric
   2978                             + " prevOperatorNumeric=" + prevOperatorNumeric
   2979                             + " countryIsoCode=" + countryIsoCode
   2980                             + " prevCountryIsoCode=" + prevCountryIsoCode
   2981                             + " ltod=" + TimeUtils.logTimeOfDay(ctm));
   2982                 }
   2983                 mNitzState.handleNetworkCountryCodeSet(countryChanged);
   2984             }
   2985 
   2986             tm.setNetworkRoamingForPhone(mPhone.getPhoneId(),
   2987                     mPhone.isPhoneTypeGsm() ? mSS.getVoiceRoaming() :
   2988                             (mSS.getVoiceRoaming() || mSS.getDataRoaming()));
   2989 
   2990             setRoamingType(mSS);
   2991             log("Broadcasting ServiceState : " + mSS);
   2992             // notify using PhoneStateListener and the legacy intent ACTION_SERVICE_STATE_CHANGED
   2993             // notify service state changed only if the merged service state is changed.
   2994             if (!oldMergedSS.equals(mPhone.getServiceState())) {
   2995                 mPhone.notifyServiceStateChanged(mPhone.getServiceState());
   2996             }
   2997 
   2998             // insert into ServiceStateProvider. This will trigger apps to wake through JobScheduler
   2999             mPhone.getContext().getContentResolver()
   3000                     .insert(getUriForSubscriptionId(mPhone.getSubId()),
   3001                             getContentValuesForServiceState(mSS));
   3002 
   3003             TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS);
   3004         }
   3005 
   3006         if (hasDataAttached || has4gHandoff || hasDataDetached || hasRegistered
   3007                 || hasDeregistered) {
   3008             logAttachChange();
   3009         }
   3010 
   3011         if (hasDataAttached || has4gHandoff) {
   3012             mAttachedRegistrants.notifyRegistrants();
   3013         }
   3014 
   3015         if (hasDataDetached) {
   3016             mDetachedRegistrants.notifyRegistrants();
   3017         }
   3018 
   3019         if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) {
   3020             logRatChange();
   3021         }
   3022 
   3023         if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
   3024             notifyDataRegStateRilRadioTechnologyChanged();
   3025 
   3026             if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   3027                     == mSS.getRilDataRadioTechnology()) {
   3028                 mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE);
   3029             } else {
   3030                 mPhone.notifyDataConnection(null);
   3031             }
   3032         }
   3033 
   3034         if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) {
   3035             logRoamingChange();
   3036         }
   3037 
   3038         if (hasVoiceRoamingOn) {
   3039             mVoiceRoamingOnRegistrants.notifyRegistrants();
   3040         }
   3041 
   3042         if (hasVoiceRoamingOff) {
   3043             mVoiceRoamingOffRegistrants.notifyRegistrants();
   3044         }
   3045 
   3046         if (hasDataRoamingOn) {
   3047             mDataRoamingOnRegistrants.notifyRegistrants();
   3048         }
   3049 
   3050         if (hasDataRoamingOff) {
   3051             mDataRoamingOffRegistrants.notifyRegistrants();
   3052         }
   3053 
   3054         if (hasLocationChanged) {
   3055             mPhone.notifyLocationChanged();
   3056         }
   3057 
   3058         if (mPhone.isPhoneTypeGsm()) {
   3059             if (!isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
   3060                 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
   3061                     mStartedGprsRegCheck = true;
   3062 
   3063                     int check_period = Settings.Global.getInt(
   3064                             mPhone.getContext().getContentResolver(),
   3065                             Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
   3066                             DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
   3067                     sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
   3068                             check_period);
   3069                 }
   3070             } else {
   3071                 mReportedGprsNoReg = false;
   3072             }
   3073         }
   3074     }
   3075 
   3076     private void updateOperatorNameFromEri() {
   3077         if (mPhone.isPhoneTypeCdma()) {
   3078             if ((mCi.getRadioState().isOn()) && (!mIsSubscriptionFromRuim)) {
   3079                 String eriText;
   3080                 // Now the Phone sees the new ServiceState so it can get the new ERI text
   3081                 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
   3082                     eriText = mPhone.getCdmaEriText();
   3083                 } else {
   3084                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for
   3085                     // mRegistrationState 0,2,3 and 4
   3086                     eriText = mPhone.getContext().getText(
   3087                             com.android.internal.R.string.roamingTextSearching).toString();
   3088                 }
   3089                 mSS.setOperatorAlphaLong(eriText);
   3090             }
   3091         } else if (mPhone.isPhoneTypeCdmaLte()) {
   3092             boolean hasBrandOverride = mUiccController.getUiccCard(getPhoneId()) != null &&
   3093                     mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null;
   3094             if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) &&
   3095                     (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology()) ||
   3096                             mPhone.getContext().getResources().getBoolean(com.android.internal.R.
   3097                                     bool.config_LTE_eri_for_network_name))) {
   3098                 // Only when CDMA is in service, ERI will take effect
   3099                 String eriText = mSS.getOperatorAlpha();
   3100                 // Now the Phone sees the new ServiceState so it can get the new ERI text
   3101                 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
   3102                     eriText = mPhone.getCdmaEriText();
   3103                 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) {
   3104                     eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null;
   3105                     if (TextUtils.isEmpty(eriText)) {
   3106                         // Sets operator alpha property by retrieving from
   3107                         // build-time system property
   3108                         eriText = SystemProperties.get("ro.cdma.home.operator.alpha");
   3109                     }
   3110                 } else if (mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) {
   3111                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
   3112                     // for mRegistrationState 0,2,3 and 4
   3113                     eriText = mPhone.getContext()
   3114                             .getText(com.android.internal.R.string.roamingTextSearching).toString();
   3115                 }
   3116                 mSS.setOperatorAlphaLong(eriText);
   3117             }
   3118 
   3119             if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY &&
   3120                     mIccRecords != null && getCombinedRegState() == ServiceState.STATE_IN_SERVICE
   3121                     && !ServiceState.isLte(mSS.getRilVoiceRadioTechnology())) {
   3122                 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
   3123                 // one configured in SIM, use operator name from CSIM record. Note that ERI, SID,
   3124                 // and NID are CDMA only, not applicable to LTE.
   3125                 boolean showSpn =
   3126                         ((RuimRecords) mIccRecords).getCsimSpnDisplayCondition();
   3127                 int iconIndex = mSS.getCdmaEriIconIndex();
   3128 
   3129                 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)
   3130                         && isInHomeSidNid(mSS.getCdmaSystemId(), mSS.getCdmaNetworkId())
   3131                         && mIccRecords != null) {
   3132                     mSS.setOperatorAlphaLong(mIccRecords.getServiceProviderName());
   3133                 }
   3134             }
   3135         }
   3136     }
   3137 
   3138     /**
   3139      * Check whether the specified SID and NID pair appears in the HOME SID/NID list
   3140      * read from NV or SIM.
   3141      *
   3142      * @return true if provided sid/nid pair belongs to operator's home network.
   3143      */
   3144     private boolean isInHomeSidNid(int sid, int nid) {
   3145         // if SID/NID is not available, assume this is home network.
   3146         if (isSidsAllZeros()) return true;
   3147 
   3148         // length of SID/NID shold be same
   3149         if (mHomeSystemId.length != mHomeNetworkId.length) return true;
   3150 
   3151         if (sid == 0) return true;
   3152 
   3153         for (int i = 0; i < mHomeSystemId.length; i++) {
   3154             // Use SID only if NID is a reserved value.
   3155             // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
   3156             if ((mHomeSystemId[i] == sid) &&
   3157                     ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
   3158                             (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
   3159                 return true;
   3160             }
   3161         }
   3162         // SID/NID are not in the list. So device is not in home network
   3163         return false;
   3164     }
   3165 
   3166     protected void setOperatorIdd(String operatorNumeric) {
   3167         // Retrieve the current country information
   3168         // with the MCC got from opeatorNumeric.
   3169         String idd = mHbpcdUtils.getIddByMcc(
   3170                 Integer.parseInt(operatorNumeric.substring(0,3)));
   3171         if (idd != null && !idd.isEmpty()) {
   3172             mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING,
   3173                     idd);
   3174         } else {
   3175             // use default "+", since we don't know the current IDP
   3176             mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, "+");
   3177         }
   3178     }
   3179 
   3180     private boolean isInvalidOperatorNumeric(String operatorNumeric) {
   3181         return operatorNumeric == null || operatorNumeric.length() < 5 ||
   3182                 operatorNumeric.startsWith(INVALID_MCC);
   3183     }
   3184 
   3185     private String fixUnknownMcc(String operatorNumeric, int sid) {
   3186         if (sid <= 0) {
   3187             // no cdma information is available, do nothing
   3188             return operatorNumeric;
   3189         }
   3190 
   3191         // resolve the mcc from sid;
   3192         // if mNitzState.getSavedTimeZoneId() is null, TimeZone would get the default timeZone,
   3193         // and the mNitzState.fixTimeZone() couldn't help, because it depends on operator Numeric;
   3194         // if the sid is conflict and timezone is unavailable, the mcc may be not right.
   3195         boolean isNitzTimeZone;
   3196         TimeZone tzone;
   3197         if (mNitzState.getSavedTimeZoneId() != null) {
   3198             tzone = TimeZone.getTimeZone(mNitzState.getSavedTimeZoneId());
   3199             isNitzTimeZone = true;
   3200         } else {
   3201             NitzData lastNitzData = mNitzState.getCachedNitzData();
   3202             if (lastNitzData == null) {
   3203                 tzone = null;
   3204             } else {
   3205                 tzone = TimeZoneLookupHelper.guessZoneByNitzStatic(lastNitzData);
   3206                 if (ServiceStateTracker.DBG) {
   3207                     log("fixUnknownMcc(): guessNitzTimeZone returned "
   3208                             + (tzone == null ? tzone : tzone.getID()));
   3209                 }
   3210             }
   3211             isNitzTimeZone = false;
   3212         }
   3213 
   3214         int utcOffsetHours = 0;
   3215         if (tzone != null) {
   3216             utcOffsetHours = tzone.getRawOffset() / MS_PER_HOUR;
   3217         }
   3218 
   3219         NitzData nitzData = mNitzState.getCachedNitzData();
   3220         boolean isDst = nitzData != null && nitzData.isDst();
   3221         int mcc = mHbpcdUtils.getMcc(sid, utcOffsetHours, (isDst ? 1 : 0), isNitzTimeZone);
   3222         if (mcc > 0) {
   3223             operatorNumeric = Integer.toString(mcc) + DEFAULT_MNC;
   3224         }
   3225         return operatorNumeric;
   3226     }
   3227 
   3228     /**
   3229      * Check if GPRS got registered while voice is registered.
   3230      *
   3231      * @param dataRegState i.e. CGREG in GSM
   3232      * @param voiceRegState i.e. CREG in GSM
   3233      * @return false if device only register to voice but not gprs
   3234      */
   3235     private boolean isGprsConsistent(int dataRegState, int voiceRegState) {
   3236         return !((voiceRegState == ServiceState.STATE_IN_SERVICE) &&
   3237                 (dataRegState != ServiceState.STATE_IN_SERVICE));
   3238     }
   3239 
   3240     /** convert ServiceState registration code
   3241      * to service state */
   3242     private int regCodeToServiceState(int code) {
   3243         switch (code) {
   3244             case NetworkRegistrationState.REG_STATE_HOME:
   3245             case NetworkRegistrationState.REG_STATE_ROAMING:
   3246                 return ServiceState.STATE_IN_SERVICE;
   3247             default:
   3248                 return ServiceState.STATE_OUT_OF_SERVICE;
   3249         }
   3250     }
   3251 
   3252     /**
   3253      * code is registration state 0-5 from TS 27.007 7.2
   3254      * returns true if registered roam, false otherwise
   3255      */
   3256     private boolean regCodeIsRoaming (int code) {
   3257         return NetworkRegistrationState.REG_STATE_ROAMING == code;
   3258     }
   3259 
   3260     private boolean isSameOperatorNameFromSimAndSS(ServiceState s) {
   3261         String spn = ((TelephonyManager) mPhone.getContext().
   3262                 getSystemService(Context.TELEPHONY_SERVICE)).
   3263                 getSimOperatorNameForPhone(getPhoneId());
   3264 
   3265         // NOTE: in case of RUIM we should completely ignore the ERI data file and
   3266         // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS)
   3267         String onsl = s.getOperatorAlphaLong();
   3268         String onss = s.getOperatorAlphaShort();
   3269 
   3270         boolean equalsOnsl = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onsl);
   3271         boolean equalsOnss = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onss);
   3272 
   3273         return (equalsOnsl || equalsOnss);
   3274     }
   3275 
   3276     /**
   3277      * Set roaming state if operator mcc is the same as sim mcc
   3278      * and ons is not different from spn
   3279      *
   3280      * @param s ServiceState hold current ons
   3281      * @return true if same operator
   3282      */
   3283     private boolean isSameNamedOperators(ServiceState s) {
   3284         return currentMccEqualsSimMcc(s) && isSameOperatorNameFromSimAndSS(s);
   3285     }
   3286 
   3287     /**
   3288      * Compare SIM MCC with Operator MCC
   3289      *
   3290      * @param s ServiceState hold current ons
   3291      * @return true if both are same
   3292      */
   3293     private boolean currentMccEqualsSimMcc(ServiceState s) {
   3294         String simNumeric = ((TelephonyManager) mPhone.getContext().
   3295                 getSystemService(Context.TELEPHONY_SERVICE)).
   3296                 getSimOperatorNumericForPhone(getPhoneId());
   3297         String operatorNumeric = s.getOperatorNumeric();
   3298         boolean equalsMcc = true;
   3299 
   3300         try {
   3301             equalsMcc = simNumeric.substring(0, 3).
   3302                     equals(operatorNumeric.substring(0, 3));
   3303         } catch (Exception e){
   3304         }
   3305         return equalsMcc;
   3306     }
   3307 
   3308     /**
   3309      * Do not set roaming state in case of oprators considered non-roaming.
   3310      *
   3311      * Can use mcc or mcc+mnc as item of
   3312      * {@link CarrierConfigManager#KEY_NON_ROAMING_OPERATOR_STRING_ARRAY}.
   3313      * For example, 302 or 21407. If mcc or mcc+mnc match with operator,
   3314      * don't set roaming state.
   3315      *
   3316      * @param s ServiceState hold current ons
   3317      * @return false for roaming state set
   3318      */
   3319     private boolean isOperatorConsideredNonRoaming(ServiceState s) {
   3320         String operatorNumeric = s.getOperatorNumeric();
   3321         final CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
   3322                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
   3323         String[] numericArray = null;
   3324         if (configManager != null) {
   3325             PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
   3326             if (config != null) {
   3327                 numericArray = config.getStringArray(
   3328                         CarrierConfigManager.KEY_NON_ROAMING_OPERATOR_STRING_ARRAY);
   3329             }
   3330         }
   3331         if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) {
   3332             return false;
   3333         }
   3334 
   3335         for (String numeric : numericArray) {
   3336             if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) {
   3337                 return true;
   3338             }
   3339         }
   3340         return false;
   3341     }
   3342 
   3343     private boolean isOperatorConsideredRoaming(ServiceState s) {
   3344         String operatorNumeric = s.getOperatorNumeric();
   3345         final CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
   3346                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
   3347         String[] numericArray = null;
   3348         if (configManager != null) {
   3349             PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
   3350             if (config != null) {
   3351                 numericArray = config.getStringArray(
   3352                         CarrierConfigManager.KEY_ROAMING_OPERATOR_STRING_ARRAY);
   3353             }
   3354         }
   3355         if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) {
   3356             return false;
   3357         }
   3358 
   3359         for (String numeric : numericArray) {
   3360             if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) {
   3361                 return true;
   3362             }
   3363         }
   3364         return false;
   3365     }
   3366 
   3367     /**
   3368      * Set restricted state based on the OnRestrictedStateChanged notification
   3369      * If any voice or packet restricted state changes, trigger a UI
   3370      * notification and notify registrants when sim is ready.
   3371      *
   3372      * @param ar an int value of RIL_RESTRICTED_STATE_*
   3373      */
   3374     private void onRestrictedStateChanged(AsyncResult ar) {
   3375         RestrictedState newRs = new RestrictedState();
   3376 
   3377         if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
   3378 
   3379         if (ar.exception == null && ar.result != null) {
   3380             int state = (int)ar.result;
   3381 
   3382             newRs.setCsEmergencyRestricted(
   3383                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
   3384                             ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
   3385             //ignore the normal call and data restricted state before SIM READY
   3386             if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY) {
   3387                 newRs.setCsNormalRestricted(
   3388                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
   3389                                 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
   3390                 newRs.setPsRestricted(
   3391                         (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
   3392             }
   3393 
   3394             if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
   3395 
   3396             if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
   3397                 mPsRestrictEnabledRegistrants.notifyRegistrants();
   3398                 setNotification(PS_ENABLED);
   3399             } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
   3400                 mPsRestrictDisabledRegistrants.notifyRegistrants();
   3401                 setNotification(PS_DISABLED);
   3402             }
   3403 
   3404             /**
   3405              * There are two kind of cs restriction, normal and emergency. So
   3406              * there are 4 x 4 combinations in current and new restricted states
   3407              * and we only need to notify when state is changed.
   3408              */
   3409             if (mRestrictedState.isCsRestricted()) {
   3410                 if (!newRs.isAnyCsRestricted()) {
   3411                     // remove all restriction
   3412                     setNotification(CS_DISABLED);
   3413                 } else if (!newRs.isCsNormalRestricted()) {
   3414                     // remove normal restriction
   3415                     setNotification(CS_EMERGENCY_ENABLED);
   3416                 } else if (!newRs.isCsEmergencyRestricted()) {
   3417                     // remove emergency restriction
   3418                     setNotification(CS_NORMAL_ENABLED);
   3419                 }
   3420             } else if (mRestrictedState.isCsEmergencyRestricted() &&
   3421                     !mRestrictedState.isCsNormalRestricted()) {
   3422                 if (!newRs.isAnyCsRestricted()) {
   3423                     // remove all restriction
   3424                     setNotification(CS_DISABLED);
   3425                 } else if (newRs.isCsRestricted()) {
   3426                     // enable all restriction
   3427                     setNotification(CS_ENABLED);
   3428                 } else if (newRs.isCsNormalRestricted()) {
   3429                     // remove emergency restriction and enable normal restriction
   3430                     setNotification(CS_NORMAL_ENABLED);
   3431                 }
   3432             } else if (!mRestrictedState.isCsEmergencyRestricted() &&
   3433                     mRestrictedState.isCsNormalRestricted()) {
   3434                 if (!newRs.isAnyCsRestricted()) {
   3435                     // remove all restriction
   3436                     setNotification(CS_DISABLED);
   3437                 } else if (newRs.isCsRestricted()) {
   3438                     // enable all restriction
   3439                     setNotification(CS_ENABLED);
   3440                 } else if (newRs.isCsEmergencyRestricted()) {
   3441                     // remove normal restriction and enable emergency restriction
   3442                     setNotification(CS_EMERGENCY_ENABLED);
   3443                 }
   3444             } else {
   3445                 if (newRs.isCsRestricted()) {
   3446                     // enable all restriction
   3447                     setNotification(CS_ENABLED);
   3448                 } else if (newRs.isCsEmergencyRestricted()) {
   3449                     // enable emergency restriction
   3450                     setNotification(CS_EMERGENCY_ENABLED);
   3451                 } else if (newRs.isCsNormalRestricted()) {
   3452                     // enable normal restriction
   3453                     setNotification(CS_NORMAL_ENABLED);
   3454                 }
   3455             }
   3456 
   3457             mRestrictedState = newRs;
   3458         }
   3459         log("onRestrictedStateChanged: X rs "+ mRestrictedState);
   3460     }
   3461 
   3462     /**
   3463      * @param workSource calling WorkSource
   3464      * @return the current cell location information. Prefer Gsm location
   3465      * information if available otherwise return LTE location information
   3466      */
   3467     public CellLocation getCellLocation(WorkSource workSource) {
   3468         if (((GsmCellLocation)mCellLoc).getLac() >= 0 &&
   3469                 ((GsmCellLocation)mCellLoc).getCid() >= 0) {
   3470             if (VDBG) log("getCellLocation(): X good mCellLoc=" + mCellLoc);
   3471             return mCellLoc;
   3472         } else {
   3473             List<CellInfo> result = getAllCellInfo(workSource);
   3474             if (result != null) {
   3475                 // A hack to allow tunneling of LTE information via GsmCellLocation
   3476                 // so that older Network Location Providers can return some information
   3477                 // on LTE only networks, see bug 9228974.
   3478                 //
   3479                 // We'll search the return CellInfo array preferring GSM/WCDMA
   3480                 // data, but if there is none we'll tunnel the first LTE information
   3481                 // in the list.
   3482                 //
   3483                 // The tunnel'd LTE information is returned as follows:
   3484                 //   LAC = TAC field
   3485                 //   CID = CI field
   3486                 //   PSC = 0.
   3487                 GsmCellLocation cellLocOther = new GsmCellLocation();
   3488                 for (CellInfo ci : result) {
   3489                     if (ci instanceof CellInfoGsm) {
   3490                         CellInfoGsm cellInfoGsm = (CellInfoGsm)ci;
   3491                         CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity();
   3492                         cellLocOther.setLacAndCid(cellIdentityGsm.getLac(),
   3493                                 cellIdentityGsm.getCid());
   3494                         cellLocOther.setPsc(cellIdentityGsm.getPsc());
   3495                         if (VDBG) log("getCellLocation(): X ret GSM info=" + cellLocOther);
   3496                         return cellLocOther;
   3497                     } else if (ci instanceof CellInfoWcdma) {
   3498                         CellInfoWcdma cellInfoWcdma = (CellInfoWcdma)ci;
   3499                         CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity();
   3500                         cellLocOther.setLacAndCid(cellIdentityWcdma.getLac(),
   3501                                 cellIdentityWcdma.getCid());
   3502                         cellLocOther.setPsc(cellIdentityWcdma.getPsc());
   3503                         if (VDBG) log("getCellLocation(): X ret WCDMA info=" + cellLocOther);
   3504                         return cellLocOther;
   3505                     } else if ((ci instanceof CellInfoLte) &&
   3506                             ((cellLocOther.getLac() < 0) || (cellLocOther.getCid() < 0))) {
   3507                         // We'll return the first good LTE info we get if there is no better answer
   3508                         CellInfoLte cellInfoLte = (CellInfoLte)ci;
   3509                         CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity();
   3510                         if ((cellIdentityLte.getTac() != Integer.MAX_VALUE)
   3511                                 && (cellIdentityLte.getCi() != Integer.MAX_VALUE)) {
   3512                             cellLocOther.setLacAndCid(cellIdentityLte.getTac(),
   3513                                     cellIdentityLte.getCi());
   3514                             cellLocOther.setPsc(0);
   3515                             if (VDBG) {
   3516                                 log("getCellLocation(): possible LTE cellLocOther=" + cellLocOther);
   3517                             }
   3518                         }
   3519                     }
   3520                 }
   3521                 if (VDBG) {
   3522                     log("getCellLocation(): X ret best answer cellLocOther=" + cellLocOther);
   3523                 }
   3524                 return cellLocOther;
   3525             } else {
   3526                 if (VDBG) {
   3527                     log("getCellLocation(): X empty mCellLoc and CellInfo mCellLoc=" + mCellLoc);
   3528                 }
   3529                 return mCellLoc;
   3530             }
   3531         }
   3532     }
   3533 
   3534     /**
   3535      * nitzReceiveTime is time_t that the NITZ time was posted
   3536      */
   3537     private void setTimeFromNITZString(String nitzString, long nitzReceiveTime) {
   3538         long start = SystemClock.elapsedRealtime();
   3539         if (DBG) {
   3540             Rlog.d(LOG_TAG, "NITZ: " + nitzString + "," + nitzReceiveTime
   3541                     + " start=" + start + " delay=" + (start - nitzReceiveTime));
   3542         }
   3543         NitzData newNitzData = NitzData.parse(nitzString);
   3544         if (newNitzData != null) {
   3545             try {
   3546                 TimeStampedValue<NitzData> nitzSignal =
   3547                         new TimeStampedValue<>(newNitzData, nitzReceiveTime);
   3548                 mNitzState.handleNitzReceived(nitzSignal);
   3549             } finally {
   3550                 if (DBG) {
   3551                     long end = SystemClock.elapsedRealtime();
   3552                     Rlog.d(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
   3553                 }
   3554             }
   3555         }
   3556     }
   3557 
   3558     /**
   3559      * Cancels all notifications posted to NotificationManager for this subId. These notifications
   3560      * for restricted state and rejection cause for cs registration are no longer valid after the
   3561      * SIM has been removed.
   3562      */
   3563     private void cancelAllNotifications() {
   3564         if (DBG) log("cancelAllNotifications: mPrevSubId=" + mPrevSubId);
   3565         NotificationManager notificationManager = (NotificationManager)
   3566                 mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
   3567         if (SubscriptionManager.isValidSubscriptionId(mPrevSubId)) {
   3568             notificationManager.cancel(Integer.toString(mPrevSubId), PS_NOTIFICATION);
   3569             notificationManager.cancel(Integer.toString(mPrevSubId), CS_NOTIFICATION);
   3570             notificationManager.cancel(Integer.toString(mPrevSubId), CS_REJECT_CAUSE_NOTIFICATION);
   3571         }
   3572     }
   3573 
   3574     /**
   3575      * Post a notification to NotificationManager for restricted state and
   3576      * rejection cause for cs registration
   3577      *
   3578      * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
   3579      */
   3580     @VisibleForTesting
   3581     public void setNotification(int notifyType) {
   3582         if (DBG) log("setNotification: create notification " + notifyType);
   3583 
   3584         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
   3585             // notifications are posted per-sub-id, so return if current sub-id is invalid
   3586             loge("cannot setNotification on invalid subid mSubId=" + mSubId);
   3587             return;
   3588         }
   3589 
   3590         // Needed because sprout RIL sends these when they shouldn't?
   3591         boolean isSetNotification = mPhone.getContext().getResources().getBoolean(
   3592                 com.android.internal.R.bool.config_user_notification_of_restrictied_mobile_access);
   3593         if (!isSetNotification) {
   3594             if (DBG) log("Ignore all the notifications");
   3595             return;
   3596         }
   3597 
   3598         Context context = mPhone.getContext();
   3599 
   3600         CarrierConfigManager configManager = (CarrierConfigManager)
   3601                 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
   3602         if (configManager != null) {
   3603             PersistableBundle bundle = configManager.getConfig();
   3604             if (bundle != null) {
   3605                 boolean disableVoiceBarringNotification = bundle.getBoolean(
   3606                         CarrierConfigManager.KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
   3607                 if(disableVoiceBarringNotification && (notifyType == CS_ENABLED
   3608                         || notifyType == CS_NORMAL_ENABLED
   3609                         || notifyType == CS_EMERGENCY_ENABLED)) {
   3610                     if (DBG) log("Voice/emergency call barred notification disabled");
   3611                     return;
   3612                 }
   3613             }
   3614         }
   3615 
   3616         CharSequence details = "";
   3617         CharSequence title = "";
   3618         int notificationId = CS_NOTIFICATION;
   3619         int icon = com.android.internal.R.drawable.stat_sys_warning;
   3620 
   3621         final boolean multipleSubscriptions = (((TelephonyManager) mPhone.getContext()
   3622                   .getSystemService(Context.TELEPHONY_SERVICE)).getPhoneCount() > 1);
   3623         final int simNumber = mSubscriptionController.getSlotIndex(mSubId) + 1;
   3624 
   3625         switch (notifyType) {
   3626             case PS_ENABLED:
   3627                 long dataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
   3628                 if (dataSubId != mPhone.getSubId()) {
   3629                     return;
   3630                 }
   3631                 notificationId = PS_NOTIFICATION;
   3632                 title = context.getText(com.android.internal.R.string.RestrictedOnDataTitle);
   3633                 details = multipleSubscriptions
   3634                         ? context.getString(
   3635                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
   3636                                 simNumber) :
   3637                         context.getText(com.android.internal.R.string.RestrictedStateContent);
   3638                 break;
   3639             case PS_DISABLED:
   3640                 notificationId = PS_NOTIFICATION;
   3641                 break;
   3642             case CS_ENABLED:
   3643                 title = context.getText(com.android.internal.R.string.RestrictedOnAllVoiceTitle);
   3644                 details = multipleSubscriptions
   3645                         ? context.getString(
   3646                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
   3647                                 simNumber) :
   3648                         context.getText(com.android.internal.R.string.RestrictedStateContent);
   3649                 break;
   3650             case CS_NORMAL_ENABLED:
   3651                 title = context.getText(com.android.internal.R.string.RestrictedOnNormalTitle);
   3652                 details = multipleSubscriptions
   3653                         ? context.getString(
   3654                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
   3655                                 simNumber) :
   3656                         context.getText(com.android.internal.R.string.RestrictedStateContent);
   3657                 break;
   3658             case CS_EMERGENCY_ENABLED:
   3659                 title = context.getText(com.android.internal.R.string.RestrictedOnEmergencyTitle);
   3660                 details = multipleSubscriptions
   3661                         ? context.getString(
   3662                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
   3663                                 simNumber) :
   3664                         context.getText(com.android.internal.R.string.RestrictedStateContent);
   3665                 break;
   3666             case CS_DISABLED:
   3667                 // do nothing and cancel the notification later
   3668                 break;
   3669             case CS_REJECT_CAUSE_ENABLED:
   3670                 notificationId = CS_REJECT_CAUSE_NOTIFICATION;
   3671                 int resId = selectResourceForRejectCode(mRejectCode, multipleSubscriptions);
   3672                 if (0 == resId) {
   3673                     loge("setNotification: mRejectCode=" + mRejectCode + " is not handled.");
   3674                     return;
   3675                 } else {
   3676                     icon = com.android.internal.R.drawable.stat_notify_mmcc_indication_icn;
   3677                     // if using the single SIM resource, mSubId will be ignored
   3678                     title = context.getString(resId, mSubId);
   3679                     details = null;
   3680                 }
   3681                 break;
   3682         }
   3683 
   3684         if (DBG) {
   3685             log("setNotification, create notification, notifyType: " + notifyType
   3686                     + ", title: " + title + ", details: " + details + ", subId: " + mSubId);
   3687         }
   3688 
   3689         mNotification = new Notification.Builder(context)
   3690                 .setWhen(System.currentTimeMillis())
   3691                 .setAutoCancel(true)
   3692                 .setSmallIcon(icon)
   3693                 .setTicker(title)
   3694                 .setColor(context.getResources().getColor(
   3695                         com.android.internal.R.color.system_notification_accent_color))
   3696                 .setContentTitle(title)
   3697                 .setStyle(new Notification.BigTextStyle().bigText(details))
   3698                 .setContentText(details)
   3699                 .setChannel(NotificationChannelController.CHANNEL_ID_ALERT)
   3700                 .build();
   3701 
   3702         NotificationManager notificationManager = (NotificationManager)
   3703                 context.getSystemService(Context.NOTIFICATION_SERVICE);
   3704 
   3705         if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
   3706             // cancel previous post notification
   3707             notificationManager.cancel(Integer.toString(mSubId), notificationId);
   3708         } else {
   3709             boolean show = false;
   3710             if (mSS.isEmergencyOnly() && notifyType == CS_EMERGENCY_ENABLED) {
   3711                 // if reg state is emergency only, always show restricted emergency notification.
   3712                 show = true;
   3713             } else if (notifyType == CS_REJECT_CAUSE_ENABLED) {
   3714                 // always show notification due to CS reject irrespective of service state.
   3715                 show = true;
   3716             } else if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
   3717                 // for non in service states, we have system UI and signal bar to indicate limited
   3718                 // service. No need to show notification again. This also helps to mitigate the
   3719                 // issue if phone go to OOS and camp to other networks and received restricted ind.
   3720                 show = true;
   3721             }
   3722             // update restricted state notification for this subId
   3723             if (show) {
   3724                 notificationManager.notify(Integer.toString(mSubId), notificationId, mNotification);
   3725             }
   3726         }
   3727     }
   3728 
   3729     /**
   3730      * Selects the resource ID, which depends on rejection cause that is sent by the network when CS
   3731      * registration is rejected.
   3732      *
   3733      * @param rejCode should be compatible with TS 24.008.
   3734      */
   3735     private int selectResourceForRejectCode(int rejCode, boolean multipleSubscriptions) {
   3736         int rejResourceId = 0;
   3737         switch (rejCode) {
   3738             case 1:// Authentication reject
   3739                 rejResourceId = multipleSubscriptions
   3740                         ? com.android.internal.R.string.mmcc_authentication_reject_msim_template :
   3741                         com.android.internal.R.string.mmcc_authentication_reject;
   3742                 break;
   3743             case 2:// IMSI unknown in HLR
   3744                 rejResourceId = multipleSubscriptions
   3745                         ? com.android.internal.R.string.mmcc_imsi_unknown_in_hlr_msim_template :
   3746                         com.android.internal.R.string.mmcc_imsi_unknown_in_hlr;
   3747                 break;
   3748             case 3:// Illegal MS
   3749                 rejResourceId = multipleSubscriptions
   3750                         ? com.android.internal.R.string.mmcc_illegal_ms_msim_template :
   3751                         com.android.internal.R.string.mmcc_illegal_ms;
   3752                 break;
   3753             case 6:// Illegal ME
   3754                 rejResourceId = multipleSubscriptions
   3755                         ? com.android.internal.R.string.mmcc_illegal_me_msim_template :
   3756                         com.android.internal.R.string.mmcc_illegal_me;
   3757                 break;
   3758             default:
   3759                 // The other codes are not defined or not required by operators till now.
   3760                 break;
   3761         }
   3762         return rejResourceId;
   3763     }
   3764 
   3765     private UiccCardApplication getUiccCardApplication() {
   3766         if (mPhone.isPhoneTypeGsm()) {
   3767             return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
   3768                     UiccController.APP_FAM_3GPP);
   3769         } else {
   3770             return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
   3771                     UiccController.APP_FAM_3GPP2);
   3772         }
   3773     }
   3774 
   3775     private void queueNextSignalStrengthPoll() {
   3776         if (mDontPollSignalStrength) {
   3777             // The radio is telling us about signal strength changes
   3778             // we don't have to ask it
   3779             return;
   3780         }
   3781 
   3782         Message msg;
   3783 
   3784         msg = obtainMessage();
   3785         msg.what = EVENT_POLL_SIGNAL_STRENGTH;
   3786 
   3787         long nextTime;
   3788 
   3789         // TODO Don't poll signal strength if screen is off
   3790         sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
   3791     }
   3792 
   3793     private void notifyCdmaSubscriptionInfoReady() {
   3794         if (mCdmaForSubscriptionInfoReadyRegistrants != null) {
   3795             if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()");
   3796             mCdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
   3797         }
   3798     }
   3799 
   3800     /**
   3801      * Registration point for transition into DataConnection attached.
   3802      * @param h handler to notify
   3803      * @param what what code of message when delivered
   3804      * @param obj placed in Message.obj
   3805      */
   3806     public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
   3807         Registrant r = new Registrant(h, what, obj);
   3808         mAttachedRegistrants.add(r);
   3809 
   3810         if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
   3811             r.notifyRegistrant();
   3812         }
   3813     }
   3814     public void unregisterForDataConnectionAttached(Handler h) {
   3815         mAttachedRegistrants.remove(h);
   3816     }
   3817 
   3818     /**
   3819      * Registration point for transition into DataConnection detached.
   3820      * @param h handler to notify
   3821      * @param what what code of message when delivered
   3822      * @param obj placed in Message.obj
   3823      */
   3824     public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
   3825         Registrant r = new Registrant(h, what, obj);
   3826         mDetachedRegistrants.add(r);
   3827 
   3828         if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
   3829             r.notifyRegistrant();
   3830         }
   3831     }
   3832     public void unregisterForDataConnectionDetached(Handler h) {
   3833         mDetachedRegistrants.remove(h);
   3834     }
   3835 
   3836     /**
   3837      * Registration for DataConnection RIL Data Radio Technology changing. The
   3838      * new radio technology will be returned AsyncResult#result as an Integer Object.
   3839      * The AsyncResult will be in the notification Message#obj.
   3840      *
   3841      * @param h handler to notify
   3842      * @param what what code of message when delivered
   3843      * @param obj placed in Message.obj
   3844      */
   3845     public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) {
   3846         Registrant r = new Registrant(h, what, obj);
   3847         mDataRegStateOrRatChangedRegistrants.add(r);
   3848         notifyDataRegStateRilRadioTechnologyChanged();
   3849     }
   3850     public void unregisterForDataRegStateOrRatChanged(Handler h) {
   3851         mDataRegStateOrRatChangedRegistrants.remove(h);
   3852     }
   3853 
   3854     /**
   3855      * Registration point for transition into network attached.
   3856      * @param h handler to notify
   3857      * @param what what code of message when delivered
   3858      * @param obj in Message.obj
   3859      */
   3860     public void registerForNetworkAttached(Handler h, int what, Object obj) {
   3861         Registrant r = new Registrant(h, what, obj);
   3862 
   3863         mNetworkAttachedRegistrants.add(r);
   3864         if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
   3865             r.notifyRegistrant();
   3866         }
   3867     }
   3868 
   3869     public void unregisterForNetworkAttached(Handler h) {
   3870         mNetworkAttachedRegistrants.remove(h);
   3871     }
   3872 
   3873     /**
   3874      * Registration point for transition into network detached.
   3875      * @param h handler to notify
   3876      * @param what what code of message when delivered
   3877      * @param obj in Message.obj
   3878      */
   3879     public void registerForNetworkDetached(Handler h, int what, Object obj) {
   3880         Registrant r = new Registrant(h, what, obj);
   3881 
   3882         mNetworkDetachedRegistrants.add(r);
   3883         if (mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) {
   3884             r.notifyRegistrant();
   3885         }
   3886     }
   3887 
   3888     public void unregisterForNetworkDetached(Handler h) {
   3889         mNetworkDetachedRegistrants.remove(h);
   3890     }
   3891 
   3892     /**
   3893      * Registration point for transition into packet service restricted zone.
   3894      * @param h handler to notify
   3895      * @param what what code of message when delivered
   3896      * @param obj placed in Message.obj
   3897      */
   3898     public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
   3899         Registrant r = new Registrant(h, what, obj);
   3900         mPsRestrictEnabledRegistrants.add(r);
   3901 
   3902         if (mRestrictedState.isPsRestricted()) {
   3903             r.notifyRegistrant();
   3904         }
   3905     }
   3906 
   3907     public void unregisterForPsRestrictedEnabled(Handler h) {
   3908         mPsRestrictEnabledRegistrants.remove(h);
   3909     }
   3910 
   3911     /**
   3912      * Registration point for transition out of packet service restricted zone.
   3913      * @param h handler to notify
   3914      * @param what what code of message when delivered
   3915      * @param obj placed in Message.obj
   3916      */
   3917     public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
   3918         Registrant r = new Registrant(h, what, obj);
   3919         mPsRestrictDisabledRegistrants.add(r);
   3920 
   3921         if (mRestrictedState.isPsRestricted()) {
   3922             r.notifyRegistrant();
   3923         }
   3924     }
   3925 
   3926     public void unregisterForPsRestrictedDisabled(Handler h) {
   3927         mPsRestrictDisabledRegistrants.remove(h);
   3928     }
   3929 
   3930     /**
   3931      * Clean up existing voice and data connection then turn off radio power.
   3932      *
   3933      * Hang up the existing voice calls to decrease call drop rate.
   3934      */
   3935     public void powerOffRadioSafely(DcTracker dcTracker) {
   3936         synchronized (this) {
   3937             if (!mPendingRadioPowerOffAfterDataOff) {
   3938                 int dds = SubscriptionManager.getDefaultDataSubscriptionId();
   3939                 // To minimize race conditions we call cleanUpAllConnections on
   3940                 // both if else paths instead of before this isDisconnected test.
   3941                 if (dcTracker.isDisconnected()
   3942                         && (dds == mPhone.getSubId()
   3943                         || (dds != mPhone.getSubId()
   3944                         && ProxyController.getInstance().isDataDisconnected(dds)))) {
   3945                     // To minimize race conditions we do this after isDisconnected
   3946                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
   3947                     if (DBG) log("Data disconnected, turn off radio right away.");
   3948                     hangupAndPowerOff();
   3949                 } else {
   3950                     // hang up all active voice calls first
   3951                     if (mPhone.isPhoneTypeGsm() && mPhone.isInCall()) {
   3952                         mPhone.mCT.mRingingCall.hangupIfAlive();
   3953                         mPhone.mCT.mBackgroundCall.hangupIfAlive();
   3954                         mPhone.mCT.mForegroundCall.hangupIfAlive();
   3955                     }
   3956                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
   3957                     if (dds != mPhone.getSubId()
   3958                             && !ProxyController.getInstance().isDataDisconnected(dds)) {
   3959                         if (DBG) log("Data is active on DDS.  Wait for all data disconnect");
   3960                         // Data is not disconnected on DDS. Wait for the data disconnect complete
   3961                         // before sending the RADIO_POWER off.
   3962                         ProxyController.getInstance().registerForAllDataDisconnected(dds, this,
   3963                                 EVENT_ALL_DATA_DISCONNECTED, null);
   3964                         mPendingRadioPowerOffAfterDataOff = true;
   3965                     }
   3966                     Message msg = Message.obtain(this);
   3967                     msg.what = EVENT_SET_RADIO_POWER_OFF;
   3968                     msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
   3969                     if (sendMessageDelayed(msg, 30000)) {
   3970                         if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
   3971                         mPendingRadioPowerOffAfterDataOff = true;
   3972                     } else {
   3973                         log("Cannot send delayed Msg, turn off radio right away.");
   3974                         hangupAndPowerOff();
   3975                         mPendingRadioPowerOffAfterDataOff = false;
   3976                     }
   3977                 }
   3978             }
   3979         }
   3980     }
   3981 
   3982     /**
   3983      * process the pending request to turn radio off after data is disconnected
   3984      *
   3985      * return true if there is pending request to process; false otherwise.
   3986      */
   3987     public boolean processPendingRadioPowerOffAfterDataOff() {
   3988         synchronized(this) {
   3989             if (mPendingRadioPowerOffAfterDataOff) {
   3990                 if (DBG) log("Process pending request to turn radio off.");
   3991                 mPendingRadioPowerOffAfterDataOffTag += 1;
   3992                 hangupAndPowerOff();
   3993                 mPendingRadioPowerOffAfterDataOff = false;
   3994                 return true;
   3995             }
   3996             return false;
   3997         }
   3998     }
   3999 
   4000     /**
   4001      * Checks if the provided earfcn falls withing the range of earfcns.
   4002      *
   4003      * return true if earfcn falls within the provided range; false otherwise.
   4004      */
   4005     private boolean containsEarfcnInEarfcnRange(ArrayList<Pair<Integer, Integer>> earfcnPairList,
   4006             int earfcn) {
   4007         if (earfcnPairList != null) {
   4008             for (Pair<Integer, Integer> earfcnPair : earfcnPairList) {
   4009                 if ((earfcn >= earfcnPair.first) && (earfcn <= earfcnPair.second)) {
   4010                     return true;
   4011                 }
   4012             }
   4013         }
   4014 
   4015         return false;
   4016     }
   4017 
   4018     /**
   4019      * Convert the earfcnStringArray to list of pairs.
   4020      *
   4021      * Format of the earfcnsList is expected to be {"erafcn1_start-earfcn1_end",
   4022      * "earfcn2_start-earfcn2_end" ... }
   4023      */
   4024     ArrayList<Pair<Integer, Integer>> convertEarfcnStringArrayToPairList(String[] earfcnsList) {
   4025         ArrayList<Pair<Integer, Integer>> earfcnPairList = new ArrayList<Pair<Integer, Integer>>();
   4026 
   4027         if (earfcnsList != null) {
   4028             int earfcnStart;
   4029             int earfcnEnd;
   4030             for (int i = 0; i < earfcnsList.length; i++) {
   4031                 try {
   4032                     String[] earfcns = earfcnsList[i].split("-");
   4033                     if (earfcns.length != 2) {
   4034                         if (VDBG) {
   4035                             log("Invalid earfcn range format");
   4036                         }
   4037                         return null;
   4038                     }
   4039 
   4040                     earfcnStart = Integer.parseInt(earfcns[0]);
   4041                     earfcnEnd = Integer.parseInt(earfcns[1]);
   4042 
   4043                     if (earfcnStart > earfcnEnd) {
   4044                         if (VDBG) {
   4045                             log("Invalid earfcn range format");
   4046                         }
   4047                         return null;
   4048                     }
   4049 
   4050                     earfcnPairList.add(new Pair<Integer, Integer>(earfcnStart, earfcnEnd));
   4051                 } catch (PatternSyntaxException pse) {
   4052                     if (VDBG) {
   4053                         log("Invalid earfcn range format");
   4054                     }
   4055                     return null;
   4056                 } catch (NumberFormatException nfe) {
   4057                     if (VDBG) {
   4058                         log("Invalid earfcn number format");
   4059                     }
   4060                     return null;
   4061                 }
   4062             }
   4063         }
   4064 
   4065         return earfcnPairList;
   4066     }
   4067 
   4068     private void onCarrierConfigChanged() {
   4069         CarrierConfigManager configManager = (CarrierConfigManager)
   4070                 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
   4071         PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
   4072 
   4073         if (config != null) {
   4074             updateLteEarfcnLists(config);
   4075             updateReportingCriteria(config);
   4076         }
   4077     }
   4078 
   4079     private void updateLteEarfcnLists(PersistableBundle config) {
   4080         synchronized (mLteRsrpBoostLock) {
   4081             mLteRsrpBoost = config.getInt(CarrierConfigManager.KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
   4082             String[] earfcnsStringArrayForRsrpBoost = config.getStringArray(
   4083                     CarrierConfigManager.KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY);
   4084             mEarfcnPairListForRsrpBoost = convertEarfcnStringArrayToPairList(
   4085                     earfcnsStringArrayForRsrpBoost);
   4086         }
   4087     }
   4088 
   4089     private void updateReportingCriteria(PersistableBundle config) {
   4090         mPhone.setSignalStrengthReportingCriteria(
   4091                 config.getIntArray(CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY),
   4092                 AccessNetworkType.EUTRAN);
   4093         mPhone.setSignalStrengthReportingCriteria(
   4094                 config.getIntArray(CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY),
   4095                 AccessNetworkType.UTRAN);
   4096     }
   4097 
   4098     private void updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn) {
   4099         synchronized (mLteRsrpBoostLock) {
   4100             if ((lteEarfcn != INVALID_LTE_EARFCN)
   4101                     && containsEarfcnInEarfcnRange(mEarfcnPairListForRsrpBoost, lteEarfcn)) {
   4102                 serviceState.setLteEarfcnRsrpBoost(mLteRsrpBoost);
   4103             } else {
   4104                 serviceState.setLteEarfcnRsrpBoost(0);
   4105             }
   4106         }
   4107     }
   4108 
   4109     /**
   4110      * send signal-strength-changed notification if changed Called both for
   4111      * solicited and unsolicited signal strength updates
   4112      *
   4113      * @return true if the signal strength changed and a notification was sent.
   4114      */
   4115     protected boolean onSignalStrengthResult(AsyncResult ar) {
   4116         boolean isGsm = false;
   4117         int dataRat = mSS.getRilDataRadioTechnology();
   4118         int voiceRat = mSS.getRilVoiceRadioTechnology();
   4119 
   4120         // Override isGsm based on currently camped data and voice RATs
   4121         // Set isGsm to true if the RAT belongs to GSM family and not IWLAN
   4122         if ((dataRat != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   4123                 && ServiceState.isGsm(dataRat))
   4124                 || (voiceRat != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   4125                 && ServiceState.isGsm(voiceRat))) {
   4126             isGsm = true;
   4127         }
   4128 
   4129         // This signal is used for both voice and data radio signal so parse
   4130         // all fields
   4131 
   4132         if ((ar.exception == null) && (ar.result != null)) {
   4133             mSignalStrength = (SignalStrength) ar.result;
   4134             mSignalStrength.validateInput();
   4135             if (dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
   4136                     && voiceRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
   4137                 mSignalStrength.fixType();
   4138             } else {
   4139                 mSignalStrength.setGsm(isGsm);
   4140             }
   4141             mSignalStrength.setLteRsrpBoost(mSS.getLteEarfcnRsrpBoost());
   4142 
   4143             PersistableBundle config = getCarrierConfig();
   4144             mSignalStrength.setUseOnlyRsrpForLteLevel(config.getBoolean(
   4145                     CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL));
   4146             mSignalStrength.setLteRsrpThresholds(config.getIntArray(
   4147                     CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY));
   4148             mSignalStrength.setWcdmaDefaultSignalMeasurement(config.getString(
   4149                     CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING));
   4150             mSignalStrength.setWcdmaRscpThresholds(config.getIntArray(
   4151                     CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY));
   4152         } else {
   4153             log("onSignalStrengthResult() Exception from RIL : " + ar.exception);
   4154             mSignalStrength = new SignalStrength(isGsm);
   4155         }
   4156 
   4157         boolean ssChanged = notifySignalStrength();
   4158 
   4159         return ssChanged;
   4160     }
   4161 
   4162     /**
   4163      * Hang up all voice call and turn off radio. Implemented by derived class.
   4164      */
   4165     protected void hangupAndPowerOff() {
   4166         // hang up all active voice calls
   4167         if (!mPhone.isPhoneTypeGsm() || mPhone.isInCall()) {
   4168             mPhone.mCT.mRingingCall.hangupIfAlive();
   4169             mPhone.mCT.mBackgroundCall.hangupIfAlive();
   4170             mPhone.mCT.mForegroundCall.hangupIfAlive();
   4171         }
   4172 
   4173         mCi.setRadioPower(false, obtainMessage(EVENT_RADIO_POWER_OFF_DONE));
   4174 
   4175     }
   4176 
   4177     /** Cancel a pending (if any) pollState() operation */
   4178     protected void cancelPollState() {
   4179         // This will effectively cancel the rest of the poll requests.
   4180         mPollingContext = new int[1];
   4181     }
   4182 
   4183     /**
   4184      * Return true if the network operator's country code changed.
   4185      */
   4186     private boolean networkCountryIsoChanged(String newCountryIsoCode, String prevCountryIsoCode) {
   4187         // Return false if the new ISO code isn't valid as we don't know where we are.
   4188         // Return true if the previous ISO code wasn't valid, or if it was and the new one differs.
   4189 
   4190         // If newCountryIsoCode is invalid then we'll return false
   4191         if (TextUtils.isEmpty(newCountryIsoCode)) {
   4192             if (DBG) {
   4193                 log("countryIsoChanged: no new country ISO code");
   4194             }
   4195             return false;
   4196         }
   4197 
   4198         if (TextUtils.isEmpty(prevCountryIsoCode)) {
   4199             if (DBG) {
   4200                 log("countryIsoChanged: no previous country ISO code");
   4201             }
   4202             return true;
   4203         }
   4204         return !newCountryIsoCode.equals(prevCountryIsoCode);
   4205     }
   4206 
   4207     // Determine if the Icc card exists
   4208     private boolean iccCardExists() {
   4209         boolean iccCardExist = false;
   4210         if (mUiccApplcation != null) {
   4211             iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN;
   4212         }
   4213         return iccCardExist;
   4214     }
   4215 
   4216     public String getSystemProperty(String property, String defValue) {
   4217         return TelephonyManager.getTelephonyProperty(mPhone.getPhoneId(), property, defValue);
   4218     }
   4219 
   4220     /**
   4221      * @return all available cell information or null if none.
   4222      */
   4223     public List<CellInfo> getAllCellInfo(WorkSource workSource) {
   4224         CellInfoResult result = new CellInfoResult();
   4225         if (VDBG) log("SST.getAllCellInfo(): E");
   4226         int ver = mCi.getRilVersion();
   4227         if (ver >= 8) {
   4228             if (isCallerOnDifferentThread()) {
   4229                 if ((SystemClock.elapsedRealtime() - mLastCellInfoListTime)
   4230                         > LAST_CELL_INFO_LIST_MAX_AGE_MS) {
   4231                     Message msg = obtainMessage(EVENT_GET_CELL_INFO_LIST, result);
   4232                     synchronized(result.lockObj) {
   4233                         result.list = null;
   4234                         mCi.getCellInfoList(msg, workSource);
   4235                         try {
   4236                             result.lockObj.wait(5000);
   4237                         } catch (InterruptedException e) {
   4238                             e.printStackTrace();
   4239                         }
   4240                     }
   4241                 } else {
   4242                     if (DBG) log("SST.getAllCellInfo(): return last, back to back calls");
   4243                     result.list = mLastCellInfoList;
   4244                 }
   4245             } else {
   4246                 if (DBG) log("SST.getAllCellInfo(): return last, same thread can't block");
   4247                 result.list = mLastCellInfoList;
   4248             }
   4249         } else {
   4250             if (DBG) log("SST.getAllCellInfo(): not implemented");
   4251             result.list = null;
   4252         }
   4253         synchronized(result.lockObj) {
   4254             if (result.list != null) {
   4255                 if (VDBG) log("SST.getAllCellInfo(): X size=" + result.list.size()
   4256                         + " list=" + result.list);
   4257                 return result.list;
   4258             } else {
   4259                 if (DBG) log("SST.getAllCellInfo(): X size=0 list=null");
   4260                 return null;
   4261             }
   4262         }
   4263     }
   4264 
   4265     /**
   4266      * @return signal strength
   4267      */
   4268     public SignalStrength getSignalStrength() {
   4269         return mSignalStrength;
   4270     }
   4271 
   4272     /**
   4273      * Registration point for subscription info ready
   4274      * @param h handler to notify
   4275      * @param what what code of message when delivered
   4276      * @param obj placed in Message.obj
   4277      */
   4278     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
   4279         Registrant r = new Registrant(h, what, obj);
   4280         mCdmaForSubscriptionInfoReadyRegistrants.add(r);
   4281 
   4282         if (isMinInfoReady()) {
   4283             r.notifyRegistrant();
   4284         }
   4285     }
   4286 
   4287     public void unregisterForSubscriptionInfoReady(Handler h) {
   4288         mCdmaForSubscriptionInfoReadyRegistrants.remove(h);
   4289     }
   4290 
   4291     /**
   4292      * Save current source of cdma subscription
   4293      * @param source - 1 for NV, 0 for RUIM
   4294      */
   4295     private void saveCdmaSubscriptionSource(int source) {
   4296         log("Storing cdma subscription source: " + source);
   4297         Settings.Global.putInt(mPhone.getContext().getContentResolver(),
   4298                 Settings.Global.CDMA_SUBSCRIPTION_MODE,
   4299                 source);
   4300         log("Read from settings: " + Settings.Global.getInt(mPhone.getContext().getContentResolver(),
   4301                 Settings.Global.CDMA_SUBSCRIPTION_MODE, -1));
   4302     }
   4303 
   4304     private void getSubscriptionInfoAndStartPollingThreads() {
   4305         mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
   4306 
   4307         // Get Registration Information
   4308         pollState();
   4309     }
   4310 
   4311     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
   4312         log("Subscription Source : " + newSubscriptionSource);
   4313         mIsSubscriptionFromRuim =
   4314                 (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
   4315         log("isFromRuim: " + mIsSubscriptionFromRuim);
   4316         saveCdmaSubscriptionSource(newSubscriptionSource);
   4317         if (!mIsSubscriptionFromRuim) {
   4318             // NV is ready when subscription source is NV
   4319             sendMessage(obtainMessage(EVENT_NV_READY));
   4320         }
   4321     }
   4322 
   4323     private void dumpEarfcnPairList(PrintWriter pw) {
   4324         pw.print(" mEarfcnPairListForRsrpBoost={");
   4325         if (mEarfcnPairListForRsrpBoost != null) {
   4326             int i = mEarfcnPairListForRsrpBoost.size();
   4327             for (Pair<Integer, Integer> earfcnPair : mEarfcnPairListForRsrpBoost) {
   4328                 pw.print("(");
   4329                 pw.print(earfcnPair.first);
   4330                 pw.print(",");
   4331                 pw.print(earfcnPair.second);
   4332                 pw.print(")");
   4333                 if ((--i) != 0) {
   4334                     pw.print(",");
   4335                 }
   4336             }
   4337         }
   4338         pw.println("}");
   4339     }
   4340 
   4341     private void dumpCellInfoList(PrintWriter pw) {
   4342         pw.print(" mLastCellInfoList={");
   4343         if(mLastCellInfoList != null) {
   4344             boolean first = true;
   4345             for(CellInfo info : mLastCellInfoList) {
   4346                if(first == false) {
   4347                    pw.print(",");
   4348                }
   4349                first = false;
   4350                pw.print(info.toString());
   4351             }
   4352         }
   4353         pw.println("}");
   4354     }
   4355 
   4356     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   4357         pw.println("ServiceStateTracker:");
   4358         pw.println(" mSubId=" + mSubId);
   4359         pw.println(" mSS=" + mSS);
   4360         pw.println(" mNewSS=" + mNewSS);
   4361         pw.println(" mVoiceCapable=" + mVoiceCapable);
   4362         pw.println(" mRestrictedState=" + mRestrictedState);
   4363         pw.println(" mPollingContext=" + mPollingContext + " - " +
   4364                 (mPollingContext != null ? mPollingContext[0] : ""));
   4365         pw.println(" mDesiredPowerState=" + mDesiredPowerState);
   4366         pw.println(" mDontPollSignalStrength=" + mDontPollSignalStrength);
   4367         pw.println(" mSignalStrength=" + mSignalStrength);
   4368         pw.println(" mLastSignalStrength=" + mLastSignalStrength);
   4369         pw.println(" mRestrictedState=" + mRestrictedState);
   4370         pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff);
   4371         pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag);
   4372         pw.println(" mCellLoc=" + Rlog.pii(VDBG, mCellLoc));
   4373         pw.println(" mNewCellLoc=" + Rlog.pii(VDBG, mNewCellLoc));
   4374         pw.println(" mLastCellInfoListTime=" + mLastCellInfoListTime);
   4375         dumpCellInfoList(pw);
   4376         pw.flush();
   4377         pw.println(" mPreferredNetworkType=" + mPreferredNetworkType);
   4378         pw.println(" mMaxDataCalls=" + mMaxDataCalls);
   4379         pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
   4380         pw.println(" mReasonDataDenied=" + mReasonDataDenied);
   4381         pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied);
   4382         pw.println(" mGsmRoaming=" + mGsmRoaming);
   4383         pw.println(" mDataRoaming=" + mDataRoaming);
   4384         pw.println(" mEmergencyOnly=" + mEmergencyOnly);
   4385         pw.flush();
   4386         mNitzState.dumpState(pw);
   4387         pw.flush();
   4388         pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
   4389         pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
   4390         pw.println(" mNotification=" + mNotification);
   4391         pw.println(" mCurSpn=" + mCurSpn);
   4392         pw.println(" mCurDataSpn=" + mCurDataSpn);
   4393         pw.println(" mCurShowSpn=" + mCurShowSpn);
   4394         pw.println(" mCurPlmn=" + mCurPlmn);
   4395         pw.println(" mCurShowPlmn=" + mCurShowPlmn);
   4396         pw.flush();
   4397         pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode);
   4398         pw.println(" mRoamingIndicator=" + mRoamingIndicator);
   4399         pw.println(" mIsInPrl=" + mIsInPrl);
   4400         pw.println(" mDefaultRoamingIndicator=" + mDefaultRoamingIndicator);
   4401         pw.println(" mRegistrationState=" + mRegistrationState);
   4402         pw.println(" mMdn=" + mMdn);
   4403         pw.println(" mHomeSystemId=" + mHomeSystemId);
   4404         pw.println(" mHomeNetworkId=" + mHomeNetworkId);
   4405         pw.println(" mMin=" + mMin);
   4406         pw.println(" mPrlVersion=" + mPrlVersion);
   4407         pw.println(" mIsMinInfoReady=" + mIsMinInfoReady);
   4408         pw.println(" mIsEriTextLoaded=" + mIsEriTextLoaded);
   4409         pw.println(" mIsSubscriptionFromRuim=" + mIsSubscriptionFromRuim);
   4410         pw.println(" mCdmaSSM=" + mCdmaSSM);
   4411         pw.println(" mRegistrationDeniedReason=" + mRegistrationDeniedReason);
   4412         pw.println(" mCurrentCarrier=" + mCurrentCarrier);
   4413         pw.flush();
   4414         pw.println(" mImsRegistered=" + mImsRegistered);
   4415         pw.println(" mImsRegistrationOnOff=" + mImsRegistrationOnOff);
   4416         pw.println(" mAlarmSwitch=" + mAlarmSwitch);
   4417         pw.println(" mRadioDisabledByCarrier" + mRadioDisabledByCarrier);
   4418         pw.println(" mPowerOffDelayNeed=" + mPowerOffDelayNeed);
   4419         pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown);
   4420         pw.println(" mSpnUpdatePending=" + mSpnUpdatePending);
   4421         pw.println(" mLteRsrpBoost=" + mLteRsrpBoost);
   4422         dumpEarfcnPairList(pw);
   4423 
   4424         mLocaleTracker.dump(fd, pw, args);
   4425 
   4426         pw.println(" Roaming Log:");
   4427         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
   4428         ipw.increaseIndent();
   4429         mRoamingLog.dump(fd, ipw, args);
   4430         ipw.decreaseIndent();
   4431 
   4432         ipw.println(" Attach Log:");
   4433         ipw.increaseIndent();
   4434         mAttachLog.dump(fd, ipw, args);
   4435         ipw.decreaseIndent();
   4436 
   4437         ipw.println(" Phone Change Log:");
   4438         ipw.increaseIndent();
   4439         mPhoneTypeLog.dump(fd, ipw, args);
   4440         ipw.decreaseIndent();
   4441 
   4442         ipw.println(" Rat Change Log:");
   4443         ipw.increaseIndent();
   4444         mRatLog.dump(fd, ipw, args);
   4445         ipw.decreaseIndent();
   4446 
   4447         ipw.println(" Radio power Log:");
   4448         ipw.increaseIndent();
   4449         mRadioPowerLog.dump(fd, ipw, args);
   4450 
   4451         mNitzState.dumpLogs(fd, ipw, args);
   4452     }
   4453 
   4454     public boolean isImsRegistered() {
   4455         return mImsRegistered;
   4456     }
   4457     /**
   4458      * Verifies the current thread is the same as the thread originally
   4459      * used in the initialization of this instance. Throws RuntimeException
   4460      * if not.
   4461      *
   4462      * @exception RuntimeException if the current thread is not
   4463      * the thread that originally obtained this Phone instance.
   4464      */
   4465     protected void checkCorrectThread() {
   4466         if (Thread.currentThread() != getLooper().getThread()) {
   4467             throw new RuntimeException(
   4468                     "ServiceStateTracker must be used from within one thread");
   4469         }
   4470     }
   4471 
   4472     protected boolean isCallerOnDifferentThread() {
   4473         boolean value = Thread.currentThread() != getLooper().getThread();
   4474         if (VDBG) log("isCallerOnDifferentThread: " + value);
   4475         return value;
   4476     }
   4477 
   4478     protected void updateCarrierMccMncConfiguration(String newOp, String oldOp, Context context) {
   4479         // if we have a change in operator, notify wifi (even to/from none)
   4480         if (((newOp == null) && (TextUtils.isEmpty(oldOp) == false)) ||
   4481                 ((newOp != null) && (newOp.equals(oldOp) == false))) {
   4482             log("update mccmnc=" + newOp + " fromServiceState=true");
   4483             MccTable.updateMccMncConfiguration(context, newOp, true);
   4484         }
   4485     }
   4486 
   4487     /**
   4488      * Check ISO country by MCC to see if phone is roaming in same registered country
   4489      */
   4490     protected boolean inSameCountry(String operatorNumeric) {
   4491         if (TextUtils.isEmpty(operatorNumeric) || (operatorNumeric.length() < 5)) {
   4492             // Not a valid network
   4493             return false;
   4494         }
   4495         final String homeNumeric = getHomeOperatorNumeric();
   4496         if (TextUtils.isEmpty(homeNumeric) || (homeNumeric.length() < 5)) {
   4497             // Not a valid SIM MCC
   4498             return false;
   4499         }
   4500         boolean inSameCountry = true;
   4501         final String networkMCC = operatorNumeric.substring(0, 3);
   4502         final String homeMCC = homeNumeric.substring(0, 3);
   4503         final String networkCountry = MccTable.countryCodeForMcc(Integer.parseInt(networkMCC));
   4504         final String homeCountry = MccTable.countryCodeForMcc(Integer.parseInt(homeMCC));
   4505         if (networkCountry.isEmpty() || homeCountry.isEmpty()) {
   4506             // Not a valid country
   4507             return false;
   4508         }
   4509         inSameCountry = homeCountry.equals(networkCountry);
   4510         if (inSameCountry) {
   4511             return inSameCountry;
   4512         }
   4513         // special same country cases
   4514         if ("us".equals(homeCountry) && "vi".equals(networkCountry)) {
   4515             inSameCountry = true;
   4516         } else if ("vi".equals(homeCountry) && "us".equals(networkCountry)) {
   4517             inSameCountry = true;
   4518         }
   4519         return inSameCountry;
   4520     }
   4521 
   4522     /**
   4523      * Set both voice and data roaming type,
   4524      * judging from the ISO country of SIM VS network.
   4525      */
   4526     protected void setRoamingType(ServiceState currentServiceState) {
   4527         final boolean isVoiceInService =
   4528                 (currentServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE);
   4529         if (isVoiceInService) {
   4530             if (currentServiceState.getVoiceRoaming()) {
   4531                 if (mPhone.isPhoneTypeGsm()) {
   4532                     // check roaming type by MCC
   4533                     if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) {
   4534                         currentServiceState.setVoiceRoamingType(
   4535                                 ServiceState.ROAMING_TYPE_DOMESTIC);
   4536                     } else {
   4537                         currentServiceState.setVoiceRoamingType(
   4538                                 ServiceState.ROAMING_TYPE_INTERNATIONAL);
   4539                     }
   4540                 } else {
   4541                     // some carrier defines international roaming by indicator
   4542                     int[] intRoamingIndicators = mPhone.getContext().getResources().getIntArray(
   4543                             com.android.internal.R.array.config_cdma_international_roaming_indicators);
   4544                     if ((intRoamingIndicators != null) && (intRoamingIndicators.length > 0)) {
   4545                         // It's domestic roaming at least now
   4546                         currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC);
   4547                         int curRoamingIndicator = currentServiceState.getCdmaRoamingIndicator();
   4548                         for (int i = 0; i < intRoamingIndicators.length; i++) {
   4549                             if (curRoamingIndicator == intRoamingIndicators[i]) {
   4550                                 currentServiceState.setVoiceRoamingType(
   4551                                         ServiceState.ROAMING_TYPE_INTERNATIONAL);
   4552                                 break;
   4553                             }
   4554                         }
   4555                     } else {
   4556                         // check roaming type by MCC
   4557                         if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) {
   4558                             currentServiceState.setVoiceRoamingType(
   4559                                     ServiceState.ROAMING_TYPE_DOMESTIC);
   4560                         } else {
   4561                             currentServiceState.setVoiceRoamingType(
   4562                                     ServiceState.ROAMING_TYPE_INTERNATIONAL);
   4563                         }
   4564                     }
   4565                 }
   4566             } else {
   4567                 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
   4568             }
   4569         }
   4570         final boolean isDataInService =
   4571                 (currentServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE);
   4572         final int dataRegType = currentServiceState.getRilDataRadioTechnology();
   4573         if (isDataInService) {
   4574             if (!currentServiceState.getDataRoaming()) {
   4575                 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
   4576             } else {
   4577                 if (mPhone.isPhoneTypeGsm()) {
   4578                     if (ServiceState.isGsm(dataRegType)) {
   4579                         if (isVoiceInService) {
   4580                             // GSM data should have the same state as voice
   4581                             currentServiceState.setDataRoamingType(currentServiceState
   4582                                     .getVoiceRoamingType());
   4583                         } else {
   4584                             // we can not decide GSM data roaming type without voice
   4585                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
   4586                         }
   4587                     } else {
   4588                         // we can not decide 3gpp2 roaming state here
   4589                         currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
   4590                     }
   4591                 } else {
   4592                     if (ServiceState.isCdma(dataRegType)) {
   4593                         if (isVoiceInService) {
   4594                             // CDMA data should have the same state as voice
   4595                             currentServiceState.setDataRoamingType(currentServiceState
   4596                                     .getVoiceRoamingType());
   4597                         } else {
   4598                             // we can not decide CDMA data roaming type without voice
   4599                             // set it as same as last time
   4600                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
   4601                         }
   4602                     } else {
   4603                         // take it as 3GPP roaming
   4604                         if (inSameCountry(currentServiceState.getDataOperatorNumeric())) {
   4605                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC);
   4606                         } else {
   4607                             currentServiceState.setDataRoamingType(
   4608                                     ServiceState.ROAMING_TYPE_INTERNATIONAL);
   4609                         }
   4610                     }
   4611                 }
   4612             }
   4613         }
   4614     }
   4615 
   4616     private void setSignalStrengthDefaultValues() {
   4617         mSignalStrength = new SignalStrength(true);
   4618     }
   4619 
   4620     protected String getHomeOperatorNumeric() {
   4621         String numeric = ((TelephonyManager) mPhone.getContext().
   4622                 getSystemService(Context.TELEPHONY_SERVICE)).
   4623                 getSimOperatorNumericForPhone(mPhone.getPhoneId());
   4624         if (!mPhone.isPhoneTypeGsm() && TextUtils.isEmpty(numeric)) {
   4625             numeric = SystemProperties.get(GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "");
   4626         }
   4627         return numeric;
   4628     }
   4629 
   4630     protected int getPhoneId() {
   4631         return mPhone.getPhoneId();
   4632     }
   4633 
   4634     /* Reset Service state when IWLAN is enabled as polling in airplane mode
   4635      * causes state to go to OUT_OF_SERVICE state instead of STATE_OFF
   4636      */
   4637     protected void resetServiceStateInIwlanMode() {
   4638         if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
   4639             boolean resetIwlanRatVal = false;
   4640             log("set service state as POWER_OFF");
   4641             if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
   4642                         == mNewSS.getRilDataRadioTechnology()) {
   4643                 log("pollStateDone: mNewSS = " + mNewSS);
   4644                 log("pollStateDone: reset iwlan RAT value");
   4645                 resetIwlanRatVal = true;
   4646             }
   4647             // operator info should be kept in SS
   4648             String operator = mNewSS.getOperatorAlphaLong();
   4649             mNewSS.setStateOff();
   4650             if (resetIwlanRatVal) {
   4651                 mNewSS.setRilDataRadioTechnology(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN);
   4652                 mNewSS.setDataRegState(ServiceState.STATE_IN_SERVICE);
   4653                 mNewSS.setOperatorAlphaLong(operator);
   4654                 log("pollStateDone: mNewSS = " + mNewSS);
   4655             }
   4656         }
   4657     }
   4658 
   4659     /**
   4660      * Check if device is non-roaming and always on home network.
   4661      *
   4662      * @param b carrier config bundle obtained from CarrierConfigManager
   4663      * @return true if network is always on home network, false otherwise
   4664      * @see CarrierConfigManager
   4665      */
   4666     protected final boolean alwaysOnHomeNetwork(BaseBundle b) {
   4667         return b.getBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL);
   4668     }
   4669 
   4670     /**
   4671      * Check if the network identifier has membership in the set of
   4672      * network identifiers stored in the carrier config bundle.
   4673      *
   4674      * @param b carrier config bundle obtained from CarrierConfigManager
   4675      * @param network The network identifier to check network existence in bundle
   4676      * @param key The key to index into the bundle presenting a string array of
   4677      *            networks to check membership
   4678      * @return true if network has membership in bundle networks, false otherwise
   4679      * @see CarrierConfigManager
   4680      */
   4681     private boolean isInNetwork(BaseBundle b, String network, String key) {
   4682         String[] networks = b.getStringArray(key);
   4683 
   4684         if (networks != null && Arrays.asList(networks).contains(network)) {
   4685             return true;
   4686         }
   4687         return false;
   4688     }
   4689 
   4690     protected final boolean isRoamingInGsmNetwork(BaseBundle b, String network) {
   4691         return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY);
   4692     }
   4693 
   4694     protected final boolean isNonRoamingInGsmNetwork(BaseBundle b, String network) {
   4695         return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY);
   4696     }
   4697 
   4698     protected final boolean isRoamingInCdmaNetwork(BaseBundle b, String network) {
   4699         return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY);
   4700     }
   4701 
   4702     protected final boolean isNonRoamingInCdmaNetwork(BaseBundle b, String network) {
   4703         return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY);
   4704     }
   4705 
   4706     /** Check if the device is shutting down. */
   4707     public boolean isDeviceShuttingDown() {
   4708         return mDeviceShuttingDown;
   4709     }
   4710 
   4711     /**
   4712      * Consider dataRegState if voiceRegState is OOS to determine SPN to be displayed
   4713      */
   4714     protected int getCombinedRegState() {
   4715         int regState = mSS.getVoiceRegState();
   4716         int dataRegState = mSS.getDataRegState();
   4717         if ((regState == ServiceState.STATE_OUT_OF_SERVICE
   4718                 || regState == ServiceState.STATE_POWER_OFF)
   4719                 && (dataRegState == ServiceState.STATE_IN_SERVICE)) {
   4720             log("getCombinedRegState: return STATE_IN_SERVICE as Data is in service");
   4721             regState = dataRegState;
   4722         }
   4723         return regState;
   4724     }
   4725 
   4726     /**
   4727      * Gets the carrier configuration values for a particular subscription.
   4728      *
   4729      * @return A {@link PersistableBundle} containing the config for the given subId,
   4730      *         or default values for an invalid subId.
   4731      */
   4732     private PersistableBundle getCarrierConfig() {
   4733         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
   4734                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
   4735         if (configManager != null) {
   4736             // If an invalid subId is used, this bundle will contain default values.
   4737             PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
   4738             if (config != null) {
   4739                 return config;
   4740             }
   4741         }
   4742         // Return static default defined in CarrierConfigManager.
   4743         return CarrierConfigManager.getDefaultConfig();
   4744     }
   4745 
   4746     public LocaleTracker getLocaleTracker() {
   4747         return mLocaleTracker;
   4748     }
   4749 }
   4750