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