Loading src/java/com/android/internal/telephony/ServiceStateTracker.java +50 −26 Original line number Diff line number Diff line Loading @@ -120,6 +120,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedList; import java.util.List; Loading @@ -129,6 +131,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; /** * {@hide} Loading Loading @@ -449,7 +452,6 @@ public class ServiceStateTracker extends Handler { protected final GsmCdmaPhone mPhone; private CellIdentity mCellIdentity; private CellIdentity mNewCellIdentity; private static final int MS_PER_HOUR = 60 * 60 * 1000; private final NitzStateMachine mNitzState; Loading Loading @@ -742,7 +744,6 @@ public class ServiceStateTracker extends Handler { mLastNitzData = null; mNitzState.handleNetworkUnavailable(); mCellIdentity = null; mNewCellIdentity = null; mSignalStrengthUpdatedTime = System.currentTimeMillis(); //cancel any pending pollstate request on voice tech switching Loading Loading @@ -2181,8 +2182,6 @@ public class ServiceStateTracker extends Handler { } } mNewCellIdentity = networkRegState.getCellIdentity(); if (DBG) { log("handlePollStateResultMessage: CS cellular. " + networkRegState); } Loading Loading @@ -3083,7 +3082,6 @@ public class ServiceStateTracker extends Handler { switch (mCi.getRadioState()) { case TelephonyManager.RADIO_POWER_UNAVAILABLE: mNewSS.setStateOutOfService(); mNewCellIdentity = null; setSignalStrengthDefaultValues(); mLastNitzData = null; mNitzState.handleNetworkUnavailable(); Loading @@ -3092,7 +3090,6 @@ public class ServiceStateTracker extends Handler { case TelephonyManager.RADIO_POWER_OFF: mNewSS.setStateOff(); mNewCellIdentity = null; setSignalStrengthDefaultValues(); mLastNitzData = null; mNitzState.handleNetworkUnavailable(); Loading Loading @@ -3139,6 +3136,35 @@ public class ServiceStateTracker extends Handler { } } /** * Get the highest-priority CellIdentity for a provided ServiceState. * * Choose a CellIdentity for ServiceState using the following rules: * 1) WWAN only (WLAN is excluded) * 2) Registered > Camped * 3) CS > PS * * @param ss a Non-Null ServiceState object * * @return a list of CellIdentity objects in *decreasing* order of preference. */ @VisibleForTesting public static @NonNull List<CellIdentity> getPrioritizedCellIdentities( @NonNull final ServiceState ss) { final List<NetworkRegistrationInfo> regInfos = ss.getNetworkRegistrationInfoList(); if (regInfos.isEmpty()) return Collections.emptyList(); return regInfos.stream() .filter(nri -> nri.getCellIdentity() != null) .filter(nri -> nri.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .sorted(Comparator .comparing(NetworkRegistrationInfo::isRegistered) .thenComparing((nri) -> nri.getDomain() & NetworkRegistrationInfo.DOMAIN_CS) .reversed()) .map(nri -> nri.getCellIdentity()) .distinct() .collect(Collectors.toList()); } private void pollStateDone() { if (!mPhone.isPhoneTypeGsm()) { updateRoamingState(); Loading Loading @@ -3248,8 +3274,13 @@ public class ServiceStateTracker extends Handler { mNewSS.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkType.EUTRAN)); boolean hasLocationChanged = (mCellIdentity == null ? mNewCellIdentity != null : !mCellIdentity.isSameCell(mNewCellIdentity)); final List<CellIdentity> prioritizedCids = getPrioritizedCellIdentities(mNewSS); final CellIdentity primaryCellIdentity = prioritizedCids.isEmpty() ? null : prioritizedCids.get(0); boolean hasLocationChanged = mCellIdentity == null ? primaryCellIdentity != null : !mCellIdentity.isSameCell(primaryCellIdentity); // ratchet the new tech up through its rat family but don't drop back down // until cell change or device is OOS Loading Loading @@ -3335,7 +3366,7 @@ public class ServiceStateTracker extends Handler { // 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 = getCidFromCellIdentity(mNewCellIdentity); int cid = getCidFromCellIdentity(primaryCellIdentity); // 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 Loading Loading @@ -3371,10 +3402,7 @@ public class ServiceStateTracker extends Handler { // clean slate for next time mNewSS.setStateOutOfService(); // swap mCellIdentity and mNewCellIdentity to put new state in mCellIdentity CellIdentity tempCellId = mCellIdentity; mCellIdentity = mNewCellIdentity; mNewCellIdentity = tempCellId; mCellIdentity = primaryCellIdentity; if (hasRilVoiceRadioTechnologyChanged) { updatePhoneObject(); Loading Loading @@ -3433,10 +3461,13 @@ public class ServiceStateTracker extends Handler { // incomplete. // CellIdentity can return a null MCC and MNC in CDMA String localeOperator = operatorNumeric; if (isInvalidOperatorNumeric(operatorNumeric) && (mCellIdentity != null) && mCellIdentity.getMccString() != null && mCellIdentity.getMncString() != null) { localeOperator = mCellIdentity.getMccString() + mCellIdentity.getMncString(); if (isInvalidOperatorNumeric(operatorNumeric)) { for (CellIdentity cid : prioritizedCids) { if (!TextUtils.isEmpty(cid.getPlmn())) { localeOperator = cid.getPlmn(); break; } } } if (isInvalidOperatorNumeric(localeOperator)) { Loading @@ -3445,16 +3476,10 @@ public class ServiceStateTracker extends Handler { // operator numeric in locale tracker is null. The async update will allow getting // cell info from the modem instead of using the cached one. mLocaleTracker.updateOperatorNumeric(""); } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) { // 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 // Update IDD. } else { if (!mPhone.isPhoneTypeGsm()) { setOperatorIdd(localeOperator); } mLocaleTracker.updateOperatorNumeric(localeOperator); } Loading Loading @@ -3770,7 +3795,7 @@ public class ServiceStateTracker extends Handler { } // Retrieve the current country information // with the MCC got from opeatorNumeric. // with the MCC got from operatorNumeric. String idd = mHbpcdUtils.getIddByMcc( Integer.parseInt(operatorNumeric.substring(0,3))); if (idd != null && !idd.isEmpty()) { Loading Loading @@ -5138,7 +5163,6 @@ public class ServiceStateTracker extends Handler { pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff); pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag); pw.println(" mCellIdentity=" + Rlog.pii(VDBG, mCellIdentity)); pw.println(" mNewCellIdentity=" + Rlog.pii(VDBG, mNewCellIdentity)); pw.println(" mLastCellInfoReqTime=" + mLastCellInfoReqTime); dumpCellInfoList(pw); pw.flush(); Loading tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java +73 −0 Original line number Diff line number Diff line Loading @@ -2605,4 +2605,77 @@ public class ServiceStateTrackerTest extends TelephonyTest { List<Intent> intents = intentArgumentCaptor.getAllValues(); return intents.get(intents.size() - 1).getExtras(); } private static NetworkRegistrationInfo makeNetworkRegistrationInfo( int domain, int transport, CellIdentity ci, boolean isRegistered) { return new NetworkRegistrationInfo.Builder() .setDomain(domain) .setTransportType(transport) .setCellIdentity(ci) .setRegistrationState(isRegistered ? NetworkRegistrationInfo.REGISTRATION_STATE_HOME : NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING) .build(); } @Test public void testCellIdentitySort() { final CellIdentityLte cellIdentityLte = new CellIdentityLte(1, 1, 5, 1, new int[] {1, 2}, 5000, "001", "01", "test", "tst", Collections.emptyList(), null); final CellIdentityGsm cellIdentityGsm = new CellIdentityGsm( 2, 3, 900, 5, "001", "01", "test", "tst", Collections.emptyList()); ServiceState ss = new ServiceState(); List<CellIdentity> cids; // Test that PS WWAN is reported if available ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityLte, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 1); assertEquals(cids.get(0), cellIdentityLte); // Test that CS is prioritized over PS ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityGsm, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that WLAN is ignored ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, cellIdentityGsm, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that null CellIdentities are ignored ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that registered networks are prioritized over unregistered ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityLte, true)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityLte); assertEquals(cids.get(1), cellIdentityGsm); } } Loading
src/java/com/android/internal/telephony/ServiceStateTracker.java +50 −26 Original line number Diff line number Diff line Loading @@ -120,6 +120,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedList; import java.util.List; Loading @@ -129,6 +131,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; /** * {@hide} Loading Loading @@ -449,7 +452,6 @@ public class ServiceStateTracker extends Handler { protected final GsmCdmaPhone mPhone; private CellIdentity mCellIdentity; private CellIdentity mNewCellIdentity; private static final int MS_PER_HOUR = 60 * 60 * 1000; private final NitzStateMachine mNitzState; Loading Loading @@ -742,7 +744,6 @@ public class ServiceStateTracker extends Handler { mLastNitzData = null; mNitzState.handleNetworkUnavailable(); mCellIdentity = null; mNewCellIdentity = null; mSignalStrengthUpdatedTime = System.currentTimeMillis(); //cancel any pending pollstate request on voice tech switching Loading Loading @@ -2181,8 +2182,6 @@ public class ServiceStateTracker extends Handler { } } mNewCellIdentity = networkRegState.getCellIdentity(); if (DBG) { log("handlePollStateResultMessage: CS cellular. " + networkRegState); } Loading Loading @@ -3083,7 +3082,6 @@ public class ServiceStateTracker extends Handler { switch (mCi.getRadioState()) { case TelephonyManager.RADIO_POWER_UNAVAILABLE: mNewSS.setStateOutOfService(); mNewCellIdentity = null; setSignalStrengthDefaultValues(); mLastNitzData = null; mNitzState.handleNetworkUnavailable(); Loading @@ -3092,7 +3090,6 @@ public class ServiceStateTracker extends Handler { case TelephonyManager.RADIO_POWER_OFF: mNewSS.setStateOff(); mNewCellIdentity = null; setSignalStrengthDefaultValues(); mLastNitzData = null; mNitzState.handleNetworkUnavailable(); Loading Loading @@ -3139,6 +3136,35 @@ public class ServiceStateTracker extends Handler { } } /** * Get the highest-priority CellIdentity for a provided ServiceState. * * Choose a CellIdentity for ServiceState using the following rules: * 1) WWAN only (WLAN is excluded) * 2) Registered > Camped * 3) CS > PS * * @param ss a Non-Null ServiceState object * * @return a list of CellIdentity objects in *decreasing* order of preference. */ @VisibleForTesting public static @NonNull List<CellIdentity> getPrioritizedCellIdentities( @NonNull final ServiceState ss) { final List<NetworkRegistrationInfo> regInfos = ss.getNetworkRegistrationInfoList(); if (regInfos.isEmpty()) return Collections.emptyList(); return regInfos.stream() .filter(nri -> nri.getCellIdentity() != null) .filter(nri -> nri.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .sorted(Comparator .comparing(NetworkRegistrationInfo::isRegistered) .thenComparing((nri) -> nri.getDomain() & NetworkRegistrationInfo.DOMAIN_CS) .reversed()) .map(nri -> nri.getCellIdentity()) .distinct() .collect(Collectors.toList()); } private void pollStateDone() { if (!mPhone.isPhoneTypeGsm()) { updateRoamingState(); Loading Loading @@ -3248,8 +3274,13 @@ public class ServiceStateTracker extends Handler { mNewSS.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkType.EUTRAN)); boolean hasLocationChanged = (mCellIdentity == null ? mNewCellIdentity != null : !mCellIdentity.isSameCell(mNewCellIdentity)); final List<CellIdentity> prioritizedCids = getPrioritizedCellIdentities(mNewSS); final CellIdentity primaryCellIdentity = prioritizedCids.isEmpty() ? null : prioritizedCids.get(0); boolean hasLocationChanged = mCellIdentity == null ? primaryCellIdentity != null : !mCellIdentity.isSameCell(primaryCellIdentity); // ratchet the new tech up through its rat family but don't drop back down // until cell change or device is OOS Loading Loading @@ -3335,7 +3366,7 @@ public class ServiceStateTracker extends Handler { // 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 = getCidFromCellIdentity(mNewCellIdentity); int cid = getCidFromCellIdentity(primaryCellIdentity); // 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 Loading Loading @@ -3371,10 +3402,7 @@ public class ServiceStateTracker extends Handler { // clean slate for next time mNewSS.setStateOutOfService(); // swap mCellIdentity and mNewCellIdentity to put new state in mCellIdentity CellIdentity tempCellId = mCellIdentity; mCellIdentity = mNewCellIdentity; mNewCellIdentity = tempCellId; mCellIdentity = primaryCellIdentity; if (hasRilVoiceRadioTechnologyChanged) { updatePhoneObject(); Loading Loading @@ -3433,10 +3461,13 @@ public class ServiceStateTracker extends Handler { // incomplete. // CellIdentity can return a null MCC and MNC in CDMA String localeOperator = operatorNumeric; if (isInvalidOperatorNumeric(operatorNumeric) && (mCellIdentity != null) && mCellIdentity.getMccString() != null && mCellIdentity.getMncString() != null) { localeOperator = mCellIdentity.getMccString() + mCellIdentity.getMncString(); if (isInvalidOperatorNumeric(operatorNumeric)) { for (CellIdentity cid : prioritizedCids) { if (!TextUtils.isEmpty(cid.getPlmn())) { localeOperator = cid.getPlmn(); break; } } } if (isInvalidOperatorNumeric(localeOperator)) { Loading @@ -3445,16 +3476,10 @@ public class ServiceStateTracker extends Handler { // operator numeric in locale tracker is null. The async update will allow getting // cell info from the modem instead of using the cached one. mLocaleTracker.updateOperatorNumeric(""); } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) { // 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 // Update IDD. } else { if (!mPhone.isPhoneTypeGsm()) { setOperatorIdd(localeOperator); } mLocaleTracker.updateOperatorNumeric(localeOperator); } Loading Loading @@ -3770,7 +3795,7 @@ public class ServiceStateTracker extends Handler { } // Retrieve the current country information // with the MCC got from opeatorNumeric. // with the MCC got from operatorNumeric. String idd = mHbpcdUtils.getIddByMcc( Integer.parseInt(operatorNumeric.substring(0,3))); if (idd != null && !idd.isEmpty()) { Loading Loading @@ -5138,7 +5163,6 @@ public class ServiceStateTracker extends Handler { pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff); pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag); pw.println(" mCellIdentity=" + Rlog.pii(VDBG, mCellIdentity)); pw.println(" mNewCellIdentity=" + Rlog.pii(VDBG, mNewCellIdentity)); pw.println(" mLastCellInfoReqTime=" + mLastCellInfoReqTime); dumpCellInfoList(pw); pw.flush(); Loading
tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java +73 −0 Original line number Diff line number Diff line Loading @@ -2605,4 +2605,77 @@ public class ServiceStateTrackerTest extends TelephonyTest { List<Intent> intents = intentArgumentCaptor.getAllValues(); return intents.get(intents.size() - 1).getExtras(); } private static NetworkRegistrationInfo makeNetworkRegistrationInfo( int domain, int transport, CellIdentity ci, boolean isRegistered) { return new NetworkRegistrationInfo.Builder() .setDomain(domain) .setTransportType(transport) .setCellIdentity(ci) .setRegistrationState(isRegistered ? NetworkRegistrationInfo.REGISTRATION_STATE_HOME : NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING) .build(); } @Test public void testCellIdentitySort() { final CellIdentityLte cellIdentityLte = new CellIdentityLte(1, 1, 5, 1, new int[] {1, 2}, 5000, "001", "01", "test", "tst", Collections.emptyList(), null); final CellIdentityGsm cellIdentityGsm = new CellIdentityGsm( 2, 3, 900, 5, "001", "01", "test", "tst", Collections.emptyList()); ServiceState ss = new ServiceState(); List<CellIdentity> cids; // Test that PS WWAN is reported if available ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityLte, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 1); assertEquals(cids.get(0), cellIdentityLte); // Test that CS is prioritized over PS ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityGsm, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that WLAN is ignored ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, cellIdentityGsm, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that null CellIdentities are ignored ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null, false)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityGsm); assertEquals(cids.get(1), cellIdentityLte); // Test that registered networks are prioritized over unregistered ss.addNetworkRegistrationInfo(makeNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN, cellIdentityLte, true)); cids = ServiceStateTracker.getPrioritizedCellIdentities(ss); assertEquals(cids.size(), 2); assertEquals(cids.get(0), cellIdentityLte); assertEquals(cids.get(1), cellIdentityGsm); } }