Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b941c937 authored by Neil Fuller's avatar Neil Fuller
Browse files

Make the NitzStateMachine behavior more regular

Much of the NitzStateMachine behavior was adopted from
an understanding of how ServiceStateTracker behaved, including behavior
that didn't make complete sense.

This commit improves guarantees about when fields are set to
provide clearer post-conditions from the various "handle" methods.

Specifically, after this commit:

mLatestNitzSignal - always holds the most recently received NITZ signal.
mSavedTimeZoneId - always holds the last time zone detected.
mNitzTimeZoneDetectionSuccessful - is always set when NITZ has been used
to set the time zone.

Before this commit the statements above were not always true, depending on
the order in which events were received.

Test: atest FrameworksTelephonyTests:com.android.internal.telephony.NitzStateMachineTest
Test: atest
FrameworksTelephonyTests:com.android.internal.telephony.ServiceStateTrackerTest
Bug: 78217059
Change-Id: Ib935431cf1a0871801635894451a68a3f1702272
parent 827059f8
Loading
Loading
Loading
Loading
+56 −52
Original line number Diff line number Diff line
@@ -117,23 +117,28 @@ public class NitzStateMachine {

    // Time Zone detection state.

    /** We always keep the last NITZ signal received in mLatestNitzSignal. */
    private TimeStampedValue<NitzData> mLatestNitzSignal;

    /**
     * Sometimes we get the NITZ time before we know what country we are in. We keep the time zone
     * information from the NITZ string in mLatestNitzSignal so we can fix the time zone once we
     * know the country.
     * Sometimes we get the NITZ time before we know what country we are in.  We can find the time
     * zone once we know the country by using {@link #mLatestNitzSignal}.
     */
    private boolean mNeedCountryCodeForNitz = false;

    private TimeStampedValue<NitzData> mLatestNitzSignal;
    private boolean mGotCountryCode = false;

    /**
     * The last time zone ID that has been determined. It may not have been set as the device time
     * zone if automatic time zone detection is disabled but may later be used to set the time zone
     * if the user enables automatic time zone detection.
     */
    private String mSavedTimeZoneId;

    /**
     * Boolean is {@code true} if {@link #handleNitzReceived(TimeStampedValue)} has been called and
     * was able to determine a time zone (which may not ultimately have been used due to user
     * settings). Cleared by {@link #handleNetworkAvailable()} and
     * {@link #handleNetworkUnavailable()}. The flag can be used when historic NITZ data may no
     * longer be valid. {@code true} indicates it's not reasonable to try to set the time zone using
     * Boolean is {@code true} if NITZ has been used to determine a time zone (which may not
     * ultimately have been used due to user settings). Cleared by {@link #handleNetworkAvailable()}
     * and {@link #handleNetworkUnavailable()}. The flag can be used when historic NITZ data may no
     * longer be valid. {@code false} indicates it is reasonable to try to set the time zone using
     * less reliable algorithms than NITZ-based detection such as by just using network country
     * code.
     */
@@ -198,9 +203,7 @@ public class NitzStateMachine {
        mGotCountryCode = true;

        String isoCountryCode = mDeviceState.getNetworkCountryIsoForPhone();
        if (!TextUtils.isEmpty(isoCountryCode)
                && !mNitzTimeZoneDetectionSuccessful
                && mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
        if (!TextUtils.isEmpty(isoCountryCode) && !mNitzTimeZoneDetectionSuccessful) {
            updateTimeZoneByNetworkCountryCode(isoCountryCode);
        }

@@ -222,8 +225,8 @@ public class NitzStateMachine {
                // Country code not found.  This is likely a test network.
                // Get a TimeZone based only on the NITZ parameters (best guess).

                // mNeedCountryCodeForNitz is only set to true when mLatestNitzSignal is set so
                // there's no need to check mLatestNitzSignal == null.
                // mNeedCountryCodeForNitz is only set to true after an NITZ signal has been
                // received and so mLatestNitzSign must be non-null.
                OffsetResult lookupResult =
                        mTimeZoneLookupHelper.lookupByNitz(mLatestNitzSignal.mValue);
                if (DBG) {
@@ -329,9 +332,8 @@ public class NitzStateMachine {
                    Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: skip changing zone as"
                            + " isTimeZoneDetectionEnabled() is false");
                }
                if (mNeedCountryCodeForNitz) {
                mSavedTimeZoneId = zoneId;
                }
                mNitzTimeZoneDetectionSuccessful = true;
            } else {
                Rlog.d(LOG_TAG, "handleNetworkCountryCodeSet: lookupResult == null, do nothing");
            }
@@ -382,6 +384,9 @@ public class NitzStateMachine {
     * Handle a new NITZ signal being received.
     */
    public void handleNitzReceived(TimeStampedValue<NitzData> nitzSignal) {
        // Always store the latest NITZ signal received.
        mLatestNitzSignal = nitzSignal;

        handleTimeZoneFromNitz(nitzSignal);
        handleTimeFromNitz(nitzSignal);
    }
@@ -389,21 +394,26 @@ public class NitzStateMachine {
    private void handleTimeZoneFromNitz(TimeStampedValue<NitzData> nitzSignal) {
        try {
            NitzData newNitzData = nitzSignal.mValue;
            String iso = mDeviceState.getNetworkCountryIsoForPhone();
            String isoCountryCode = mDeviceState.getNetworkCountryIsoForPhone();

            boolean needCountryCode;
            String zoneId;
            if (newNitzData.getEmulatorHostTimeZone() != null) {
                zoneId = newNitzData.getEmulatorHostTimeZone().getID();
                needCountryCode = false;
            } else {
                if (!mGotCountryCode) {
                    // We don't have a country code so we won't try to look up the time zone.
                    zoneId = null;
                } else if (!TextUtils.isEmpty(iso)) {
                    OffsetResult lookupResult =
                            mTimeZoneLookupHelper.lookupByNitzCountry(newNitzData, iso);
                    needCountryCode = true;
                } else if (!TextUtils.isEmpty(isoCountryCode)) {
                    OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitzCountry(
                            newNitzData, isoCountryCode);
                    zoneId = lookupResult != null ? lookupResult.zoneId : null;
                    needCountryCode = false;
                } else {
                    // We don't have a valid iso country code.  This is
                    // most likely because we're on a test network that's
                    // using a bogus MCC (eg, "001"), so get a TimeZone
                    // We have a country code but it's empty. This is most likely because we're on a
                    // test network that's using a bogus MCC (eg, "001"), so get a TimeZone
                    // based only on the NITZ parameters.
                    OffsetResult lookupResult = mTimeZoneLookupHelper.lookupByNitz(newNitzData);
                    if (DBG) {
@@ -411,37 +421,37 @@ public class NitzStateMachine {
                                + " lookupResult=" + lookupResult);
                    }
                    zoneId = lookupResult != null ? lookupResult.zoneId : null;
                    needCountryCode = false;
                }
            }

            if ((zoneId == null)
                    || mLatestNitzSignal == null
                    || offsetInfoDiffers(newNitzData, mLatestNitzSignal.mValue)) {
                // We got the time before the country, or the zone has changed
                // so we don't know how to identify the DST rules yet.  Save
                // the information and hope to fix it up later.
            // Set state as needed.
            if (needCountryCode) {
                mNeedCountryCodeForNitz = true;
                mLatestNitzSignal = nitzSignal;
            } else {
                mNeedCountryCodeForNitz = false;
                if (zoneId != null) {
                    if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
                        setAndBroadcastNetworkSetTimeZone(zoneId);
                    }
                    mSavedTimeZoneId = zoneId;
                    mNitzTimeZoneDetectionSuccessful = true;
                }
            }

            String tmpLog = "handleTimeZoneFromNitz: nitzSignal=" + nitzSignal
                    + " zoneId=" + zoneId
                    + " iso=" + iso + " mGotCountryCode=" + mGotCountryCode
                    + " mGotCountryCode=" + mGotCountryCode
                    + " isoCountryCode=" + isoCountryCode
                    + " mNeedCountryCodeForNitz=" + mNeedCountryCodeForNitz
                    + " mNitzTimeZoneDetectionSuccessful=" + mNitzTimeZoneDetectionSuccessful
                    + " mSavedTimeZoneId=" + mSavedTimeZoneId
                    + " isTimeZoneDetectionEnabled()="
                    + mTimeServiceHelper.isTimeZoneDetectionEnabled();
            if (DBG) {
                Rlog.d(LOG_TAG, tmpLog);
            }
            mTimeZoneLog.log(tmpLog);

            if (zoneId != null) {
                if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
                    setAndBroadcastNetworkSetTimeZone(zoneId);
                }
                mNitzTimeZoneDetectionSuccessful = true;
                mSavedTimeZoneId = zoneId;
            }
        } catch (RuntimeException ex) {
            Rlog.e(LOG_TAG, "handleTimeZoneFromNitz: Processing NITZ data"
                    + " nitzSignal=" + nitzSignal
@@ -449,11 +459,6 @@ public class NitzStateMachine {
        }
    }

    private static boolean offsetInfoDiffers(NitzData one, NitzData two) {
        return one.getLocalOffsetMillis() != two.getLocalOffsetMillis()
                || one.isDst() != two.isDst();
    }

    private void handleTimeFromNitz(TimeStampedValue<NitzData> nitzSignal) {
        try {
            boolean ignoreNitz = mDeviceState.getIgnoreNitz();
@@ -595,11 +600,6 @@ public class NitzStateMachine {
        mTimeZoneLog.log(tmpLog);
        if (mSavedTimeZoneId != null) {
            setAndBroadcastNetworkSetTimeZone(mSavedTimeZoneId);
        } else {
            String iso = mDeviceState.getNetworkCountryIsoForPhone();
            if (!TextUtils.isEmpty(iso)) {
                updateTimeZoneByNetworkCountryCode(iso);
            }
        }
    }

@@ -654,7 +654,11 @@ public class NitzStateMachine {
                Rlog.d(LOG_TAG, logMsg);
            }
            mTimeZoneLog.log(logMsg);
            setAndBroadcastNetworkSetTimeZone(lookupResult.zoneId);
            String zoneId = lookupResult.zoneId;
            if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
                setAndBroadcastNetworkSetTimeZone(zoneId);
            }
            mSavedTimeZoneId = zoneId;
        } else {
            if (DBG) {
                Rlog.d(LOG_TAG, "updateTimeZoneByNetworkCountryCode: no good zone for"
+2 −6
Original line number Diff line number Diff line
@@ -375,9 +375,7 @@ public class NitzStateMachineTest extends TelephonyTest {
                .verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());

        // Check NitzStateMachine state.
        // TODO(nfuller): The following line should probably be assertTrue but the logic under test
        // may be buggy. Look at whether it needs to change.
        assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(scenario.getNitzSignal().mValue, mNitzStateMachine.getCachedNitzData());
        assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }
@@ -413,9 +411,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        script.verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId(), 2 /* times */);

        // Check NitzStateMachine state.
        // TODO(nfuller): The following line should probably be assertTrue but the logic under test
        // may be buggy. Look at whether it needs to change.
        assertFalse(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(scenario.getNitzSignal().mValue, mNitzStateMachine.getCachedNitzData());
        assertEquals(scenario.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }