in com/android/internal/telephony/ServiceStateTracker.java [2642:3009]
private void pollStateDone() {
if (!mPhone.isPhoneTypeGsm()) {
updateRoamingState();
}
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
mNewSS.setVoiceRoaming(true);
mNewSS.setDataRoaming(true);
}
useDataRegStateForDataOnlyDevices();
resetServiceStateInIwlanMode();
if (DBG) {
log("Poll ServiceState done: "
+ " oldSS=[" + mSS + "] newSS=[" + mNewSS + "]"
+ " oldMaxDataCalls=" + mMaxDataCalls
+ " mNewMaxDataCalls=" + mNewMaxDataCalls
+ " oldReasonDataDenied=" + mReasonDataDenied
+ " mNewReasonDataDenied=" + mNewReasonDataDenied);
}
boolean hasRegistered =
mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasDeregistered =
mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
&& mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasDataAttached =
mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
&& mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasDataDetached =
mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
&& mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasDataRegStateChanged =
mSS.getDataRegState() != mNewSS.getDataRegState();
boolean hasVoiceRegStateChanged =
mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);
// ratchet the new tech up through it's rat family but don't drop back down
// until cell change
if (!hasLocationChanged) {
mRatRatcheter.ratchetRat(mSS, mNewSS);
}
boolean hasRilVoiceRadioTechnologyChanged =
mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
boolean hasRilDataRadioTechnologyChanged =
mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology();
boolean hasChanged = !mNewSS.equals(mSS);
boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming();
boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming();
boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming();
boolean hasRejectCauseChanged = mRejectCode != mNewRejectCode;
boolean has4gHandoff = false;
boolean hasMultiApnSupport = false;
boolean hasLostMultiApnSupport = false;
if (mPhone.isPhoneTypeCdmaLte()) {
has4gHandoff = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
&& ((ServiceState.isLte(mSS.getRilDataRadioTechnology())
&& (mNewSS.getRilDataRadioTechnology()
== ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
||
((mSS.getRilDataRadioTechnology()
== ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)
&& ServiceState.isLte(mNewSS.getRilDataRadioTechnology())));
hasMultiApnSupport = ((ServiceState.isLte(mNewSS.getRilDataRadioTechnology())
|| (mNewSS.getRilDataRadioTechnology()
== ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
&&
(!ServiceState.isLte(mSS.getRilDataRadioTechnology())
&& (mSS.getRilDataRadioTechnology()
!= ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
hasLostMultiApnSupport =
((mNewSS.getRilDataRadioTechnology()
>= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)
&& (mNewSS.getRilDataRadioTechnology()
<= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A));
}
if (DBG) {
log("pollStateDone:"
+ " hasRegistered=" + hasRegistered
+ " hasDeregistered=" + hasDeregistered
+ " hasDataAttached=" + hasDataAttached
+ " hasDataDetached=" + hasDataDetached
+ " hasDataRegStateChanged=" + hasDataRegStateChanged
+ " hasRilVoiceRadioTechnologyChanged= " + hasRilVoiceRadioTechnologyChanged
+ " hasRilDataRadioTechnologyChanged=" + hasRilDataRadioTechnologyChanged
+ " hasChanged=" + hasChanged
+ " hasVoiceRoamingOn=" + hasVoiceRoamingOn
+ " hasVoiceRoamingOff=" + hasVoiceRoamingOff
+ " hasDataRoamingOn=" + hasDataRoamingOn
+ " hasDataRoamingOff=" + hasDataRoamingOff
+ " hasLocationChanged=" + hasLocationChanged
+ " has4gHandoff = " + has4gHandoff
+ " hasMultiApnSupport=" + hasMultiApnSupport
+ " hasLostMultiApnSupport=" + hasLostMultiApnSupport);
}
// Add an event log when connection state changes
if (hasVoiceRegStateChanged || hasDataRegStateChanged) {
EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE :
EventLogTags.CDMA_SERVICE_STATE_CHANGE,
mSS.getVoiceRegState(), mSS.getDataRegState(),
mNewSS.getVoiceRegState(), mNewSS.getDataRegState());
}
if (mPhone.isPhoneTypeGsm()) {
// Add an event log when network type switched
// TODO: we may add filtering to reduce the event logged,
// i.e. check preferred network setting, only switch to 2G, etc
if (hasRilVoiceRadioTechnologyChanged) {
int cid = -1;
GsmCellLocation loc = (GsmCellLocation) mNewCellLoc;
if (loc != null) cid = loc.getCid();
// NOTE: this code was previously located after mSS and mNewSS are swapped, so
// existing logs were incorrectly using the new state for "network_from"
// and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag
// to record the correct states.
EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid,
mSS.getRilVoiceRadioTechnology(),
mNewSS.getRilVoiceRadioTechnology());
if (DBG) {
log("RAT switched "
+ ServiceState.rilRadioTechnologyToString(
mSS.getRilVoiceRadioTechnology())
+ " -> "
+ ServiceState.rilRadioTechnologyToString(
mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid);
}
}
mReasonDataDenied = mNewReasonDataDenied;
mMaxDataCalls = mNewMaxDataCalls;
mRejectCode = mNewRejectCode;
}
// swap mSS and mNewSS to put new state in mSS
ServiceState tss = mSS;
mSS = mNewSS;
mNewSS = tss;
// clean slate for next time
mNewSS.setStateOutOfService();
// swap mCellLoc and mNewCellLoc to put new state in mCellLoc
CellLocation tcl = mCellLoc;
mCellLoc = mNewCellLoc;
mNewCellLoc = tcl;
if (hasRilVoiceRadioTechnologyChanged) {
updatePhoneObject();
}
TelephonyManager tm =
(TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (hasRilDataRadioTechnologyChanged) {
tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology());
if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
== mSS.getRilDataRadioTechnology()) {
log("pollStateDone: IWLAN enabled");
}
}
if (hasRegistered) {
mNetworkAttachedRegistrants.notifyRegistrants();
if (DBG) {
log("pollStateDone: registering current mNitzUpdatedTime=" + mNitzUpdatedTime
+ " changing to false");
}
mNitzUpdatedTime = false;
}
if (hasDeregistered) {
mNetworkDetachedRegistrants.notifyRegistrants();
}
if (hasRejectCauseChanged) {
setNotification(CS_REJECT_CAUSE_ENABLED);
}
if (hasChanged) {
updateSpnDisplay();
tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlpha());
String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId());
String operatorNumeric = mSS.getOperatorNumeric();
if (!mPhone.isPhoneTypeGsm()) {
// try to fix the invalid Operator Numeric
if (isInvalidOperatorNumeric(operatorNumeric)) {
int sid = mSS.getSystemId();
operatorNumeric = fixUnknownMcc(operatorNumeric, sid);
}
}
tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric);
updateCarrierMccMncConfiguration(operatorNumeric,
prevOperatorNumeric, mPhone.getContext());
if (isInvalidOperatorNumeric(operatorNumeric)) {
if (DBG) log("operatorNumeric " + operatorNumeric + " is invalid");
tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), "");
mGotCountryCode = false;
mNitzUpdatedTime = false;
} else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
// Update time zone, ISO, and IDD.
//
// If the device is on IWLAN, modems manufacture a ServiceState with the MCC/MNC of
// the SIM as if we were talking to towers. Telephony code then uses that with
// mccTable to suggest a timezone. We shouldn't do that if the MCC/MNC is from IWLAN
String iso = "";
String mcc = "";
try {
mcc = operatorNumeric.substring(0, 3);
iso = MccTable.countryCodeForMcc(Integer.parseInt(mcc));
} catch (NumberFormatException | StringIndexOutOfBoundsException ex) {
loge("pollStateDone: countryCodeForMcc error: " + ex);
}
tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), iso);
mGotCountryCode = true;
if (!mNitzUpdatedTime && !mcc.equals("000") && !TextUtils.isEmpty(iso)
&& getAutoTimeZone()) {
// Test both paths if ignore nitz is true
boolean testOneUniqueOffsetPath = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_IGNORE_NITZ, false)
&& ((SystemClock.uptimeMillis() & 1) == 0);
List<String> uniqueZoneIds = TimeUtils.getTimeZoneIdsWithUniqueOffsets(iso);
if ((uniqueZoneIds.size() == 1) || testOneUniqueOffsetPath) {
String zoneId = uniqueZoneIds.get(0);
if (DBG) {
log("pollStateDone: no nitz but one TZ for iso-cc=" + iso
+ " with zone.getID=" + zoneId
+ " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath);
}
mTimeZoneLog.log("pollStateDone: set time zone=" + zoneId
+ " mcc=" + mcc + " iso=" + iso);
setAndBroadcastNetworkSetTimeZone(zoneId);
} else {
if (DBG) {
log("pollStateDone: there are " + uniqueZoneIds.size()
+ " unique offsets for iso-cc='" + iso
+ " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath
+ "', do nothing");
}
}
}
if (!mPhone.isPhoneTypeGsm()) {
setOperatorIdd(operatorNumeric);
}
if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric,
mNeedFixZoneAfterNitz)) {
fixTimeZone(iso);
}
}
tm.setNetworkRoamingForPhone(mPhone.getPhoneId(),
mPhone.isPhoneTypeGsm() ? mSS.getVoiceRoaming() :
(mSS.getVoiceRoaming() || mSS.getDataRoaming()));
setRoamingType(mSS);
log("Broadcasting ServiceState : " + mSS);
// notify using PhoneStateListener and the legacy intent ACTION_SERVICE_STATE_CHANGED
mPhone.notifyServiceStateChanged(mSS);
// insert into ServiceStateProvider. This will trigger apps to wake through JobScheduler
mPhone.getContext().getContentResolver()
.insert(getUriForSubscriptionId(mPhone.getSubId()),
getContentValuesForServiceState(mSS));
TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS);
}
if (hasDataAttached || has4gHandoff || hasDataDetached || hasRegistered
|| hasDeregistered) {
logAttachChange();
}
if (hasDataAttached || has4gHandoff) {
mAttachedRegistrants.notifyRegistrants();
}
if (hasDataDetached) {
mDetachedRegistrants.notifyRegistrants();
}
if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) {
logRatChange();
}
if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) {
notifyDataRegStateRilRadioTechnologyChanged();
if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
== mSS.getRilDataRadioTechnology()) {
mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE);
} else {
mPhone.notifyDataConnection(null);
}
}
if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) {
logRoamingChange();
}
if (hasVoiceRoamingOn) {
mVoiceRoamingOnRegistrants.notifyRegistrants();
}
if (hasVoiceRoamingOff) {
mVoiceRoamingOffRegistrants.notifyRegistrants();
}
if (hasDataRoamingOn) {
mDataRoamingOnRegistrants.notifyRegistrants();
}
if (hasDataRoamingOff) {
mDataRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
mPhone.notifyLocationChanged();
}
if (mPhone.isPhoneTypeGsm()) {
if (!isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) {
if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
mStartedGprsRegCheck = true;
int check_period = Settings.Global.getInt(
mPhone.getContext().getContentResolver(),
Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
check_period);
}
} else {
mReportedGprsNoReg = false;
}
}
}