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