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

Commit 75d0c86d authored by Neil Fuller's avatar Neil Fuller
Browse files

Time Detection improvements

This change mostly modifies time detection logic to be
clearer, safer around wake locks. It adds / de-dupes
logging for improved debugging.

It also modifies mNitzUpdatedTime:

mNitzUpdatedTime was added to GsmServiceStateTracker in
commit a27421a306c49fbe9b3823b30f7ab1cd58b28854
and is used to track whether NITZ has been used. The original
purpose was to determine whether it was appropriate to try
to set the time zone using the network MCC (it's not if NITZ
has been received). The logic around this seems generally
bogus and the flag state was not maintained historically in
various paths (e.g. fixTimeZone()). This change renames
the field to reflect actual usage and moves it to be with
the Time Zone detection code. Later changes will improve the
time zone detection logic.

Bug: 63743683
Test: atest FrameworksTelephonyTests
Change-Id: Ic0925b1096eb20e35fb284100b54e82fc980839f
Merged-In: Ic0925b1096eb20e35fb284100b54e82fc980839f
(cherry picked from commit 25b55a71)
parent f4bc554b
Loading
Loading
Loading
Loading
+176 −107
Original line number Diff line number Diff line
@@ -98,6 +98,13 @@ public class NitzStateMachine {
            return ignoreNitz != null && ignoreNitz.equals("yes");
        }

        /**
         * Returns the same value as {@link System#currentTimeMillis()}.
         */
        public long currentTimeMillis() {
            return System.currentTimeMillis();
        }

        /**
         * Returns the same value as {@link SystemClock#elapsedRealtime()}.
         */
@@ -110,6 +117,31 @@ public class NitzStateMachine {
        }
    }

    /** A pair containing a value and an associated time stamp. */
    private static class TimeStampedValue<T> {
        /** The value. */
        final T mValue;

        /**
         * The value of {@link SystemClock#elapsedRealtime} or equivalent when value was
         * determined.
         */
        final long mElapsedRealtime;

        TimeStampedValue(T value, long elapsedRealtime) {
            this.mValue = value;
            this.mElapsedRealtime = elapsedRealtime;
        }

        @Override
        public String toString() {
            return "TimeStampedValue{"
                    + "mValue=" + mValue
                    + ", mElapsedRealtime=" + mElapsedRealtime
                    + '}';
        }
    }

    private static final String LOG_TAG = ServiceStateTracker.LOG_TAG;
    private static final boolean DBG = ServiceStateTracker.DBG;

@@ -142,8 +174,16 @@ public class NitzStateMachine {
            "tg", // Togo
    };

    private final LocalLog mTimeLog = new LocalLog(15);
    private final LocalLog mTimeZoneLog = new LocalLog(15);
    // Time detection state.

    /**
     * The last NITZ-sourced time considered. If auto time detection was off at the time this may
     * not have been used to set the device time, but it can be used if auto time detection is
     * re-enabled.
     */
    private TimeStampedValue<Long> mSavedNitzTime;

    // Time Zone detection state.

    /**
     * Sometimes we get the NITZ time before we know what country we
@@ -155,19 +195,26 @@ public class NitzStateMachine {
    private NitzData mNitzData;
    private boolean mGotCountryCode = false;
    private String mSavedTimeZoneId;
    private long mSavedTime;
    private long mSavedAtTime;

    /** Wake lock used while setting time of day. */
    private PowerManager.WakeLock mWakeLock;
    private static final String WAKELOCK_TAG = "NitzStateMachine";

    /** Boolean is true if setTimeFromNITZ was called */
    private boolean mNitzUpdatedTime = false;
    /**
     * Boolean is {@code true} if {@link #setTimeZoneFromNitz(NitzData, long)} 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 #clearNitzTimeZoneDetectionSuccessful()},
     * 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 less reliable algorithms than
     * NITZ-based detection such as by just using network country code.
     */
    private boolean mNitzTimeZoneDetectionSuccessful = false;

    // Miscellaneous dependencies and helpers not related to detection state.
    private final LocalLog mTimeLog = new LocalLog(15);
    private final LocalLog mTimeZoneLog = new LocalLog(15);
    private final GsmCdmaPhone mPhone;
    private final DeviceState mDeviceState;
    private final TimeServiceHelper mTimeServiceHelper;
    /** Wake lock used while setting time of day. */
    private final PowerManager.WakeLock mWakeLock;
    private static final String WAKELOCK_TAG = "NitzStateMachine";

    public NitzStateMachine(GsmCdmaPhone phone) {
        this(phone,
@@ -251,7 +298,11 @@ public class NitzStateMachine {
            // a zero UTC offset) the device will retain the existing time zone setting and not try
            // to derive one from the isoCountryCode.
            if (mNeedFixZoneAfterNitz) {
                long ctm = System.currentTimeMillis();
                try {
                    // Acquire the wakelock as we're reading the system clock here.
                    mWakeLock.acquire();

                    long ctm = mDeviceState.currentTimeMillis();
                    long tzOffset = zone.getOffset(ctm);
                    if (DBG) {
                        Rlog.d(LOG_TAG, "fixTimeZone: tzOffset=" + tzOffset
@@ -259,17 +310,19 @@ public class NitzStateMachine {
                    }
                    if (mTimeServiceHelper.isTimeDetectionEnabled()) {
                        long adj = ctm - tzOffset;
                    if (DBG) {
                        Rlog.d(LOG_TAG, "fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj));
                    }
                    setAndBroadcastNetworkSetTime(adj);
                        String msg = "fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj);
                        setAndBroadcastNetworkSetTime(msg, adj);
                    } else {
                        // Adjust the saved NITZ time to account for tzOffset.
                    mSavedTime = mSavedTime - tzOffset;
                        mSavedNitzTime = new TimeStampedValue<>(
                                mSavedNitzTime.mValue - tzOffset, mSavedNitzTime.mElapsedRealtime);
                        if (DBG) {
                        Rlog.d(LOG_TAG, "fixTimeZone: adj mSavedTime=" + mSavedTime);
                            Rlog.d(LOG_TAG, "fixTimeZone: adj mSavedTime=" + mSavedNitzTime);
                        }
                    }
                } finally {
                    mWakeLock.release();
                }
            }
            if (DBG) {
                Rlog.d(LOG_TAG, "fixTimeZone: using default TimeZone");
@@ -327,7 +380,10 @@ public class NitzStateMachine {
     */
    public void setTimeAndTimeZoneFromNitz(NitzData newNitzData, long nitzReceiveTime) {
        setTimeZoneFromNitz(newNitzData, nitzReceiveTime);
        setTimeFromNitz(newNitzData, nitzReceiveTime);

        TimeStampedValue<NitzData> nitzSignal =
                new TimeStampedValue<>(newNitzData, nitzReceiveTime);
        setTimeFromNitz(nitzSignal);
    }

    private void setTimeZoneFromNitz(NitzData newNitzData, long nitzReceiveTime) {
@@ -395,6 +451,7 @@ public class NitzStateMachine {
                if (mTimeServiceHelper.isTimeZoneDetectionEnabled()) {
                    setAndBroadcastNetworkSetTimeZone(zone.getID());
                }
                mNitzTimeZoneDetectionSuccessful = true;
                saveNitzTimeZone(zone.getID());
            }
        } catch (RuntimeException ex) {
@@ -402,84 +459,84 @@ public class NitzStateMachine {
        }
    }

    private void setTimeFromNitz(NitzData newNitzData, long nitzReceiveTime) {
    private void setTimeFromNitz(TimeStampedValue<NitzData> nitzTimeSignal) {
        try {
            boolean ignoreNitz = mDeviceState.getIgnoreNitz();
            if (ignoreNitz) {
                Rlog.d(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
                Rlog.d(LOG_TAG,
                        "setTimeFromNitz: Not setting clock because gsm.ignore-nitz is set");
                return;
            }

            try {
                // Acquire the wake lock as we are reading the elapsed realtime clock and system
                // clock.
                mWakeLock.acquire();

                long millisSinceNitzReceived = mDeviceState.elapsedRealtime() - nitzReceiveTime;
                if (millisSinceNitzReceived < 0) {
                    // Sanity check: something is wrong
                    if (DBG) {
                        Rlog.d(LOG_TAG, "NITZ: not setting time, clock has rolled "
                                + "backwards since NITZ time was received, "
                                + newNitzData);
                    }
                    return;
                }

                if (millisSinceNitzReceived > Integer.MAX_VALUE) {
                    // If the time is this far off, something is wrong > 24 days!
                // Validate the nitzTimeSignal to reject obviously bogus elapsedRealtime values.
                long elapsedRealtime = mDeviceState.elapsedRealtime();
                long millisSinceNitzReceived = elapsedRealtime - nitzTimeSignal.mElapsedRealtime;
                if (millisSinceNitzReceived < 0 || millisSinceNitzReceived > Integer.MAX_VALUE) {
                    if (DBG) {
                        Rlog.d(LOG_TAG, "NITZ: not setting time, processing has taken "
                                + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
                                + " days");
                        Rlog.d(LOG_TAG, "setTimeFromNitz: not setting time, unexpected"
                                + " elapsedRealtime=" + elapsedRealtime
                                + " nitzTimeSignal=" + nitzTimeSignal);
                    }
                    return;
                }

                // Adjust the NITZ time by the delay since it was received.
                long adjustedCurrentTimeMillis = newNitzData.getCurrentTimeInMillis();
                adjustedCurrentTimeMillis += millisSinceNitzReceived;
                // Adjust the NITZ time by the delay since it was received to get the time now.
                long adjustedCurrentTimeMillis =
                        nitzTimeSignal.mValue.getCurrentTimeInMillis() + millisSinceNitzReceived;
                long gained = adjustedCurrentTimeMillis - mDeviceState.currentTimeMillis();

                if (mTimeServiceHelper.isTimeDetectionEnabled()) {
                    String tmpLog = "NITZ: newNitaData=" + newNitzData
                            + " nitzReceiveTime=" + nitzReceiveTime
                            + " Setting time of day to " + adjustedCurrentTimeMillis
                            + " NITZ receive delay(ms): " + millisSinceNitzReceived
                            + " gained(ms): "
                            + (adjustedCurrentTimeMillis - System.currentTimeMillis());
                    if (DBG) {
                        Rlog.d(LOG_TAG, tmpLog);
                    }
                    mTimeLog.log(tmpLog);
                    // Update system time automatically
                    long gained = adjustedCurrentTimeMillis - System.currentTimeMillis();
                    long timeSinceLastUpdate =
                            mDeviceState.elapsedRealtime() - mSavedAtTime;
                    String logMsg = "(setTimeFromNitz)"
                            + " nitzTimeSignal=" + nitzTimeSignal
                            + " adjustedCurrentTimeMillis=" + adjustedCurrentTimeMillis
                            + " millisSinceNitzReceived= " + millisSinceNitzReceived
                            + " gained=" + gained;

                    if (mSavedNitzTime == null) {
                        logMsg += ": First update received.";
                        setAndBroadcastNetworkSetTime(logMsg, adjustedCurrentTimeMillis);
                    } else {
                        long elapsedRealtimeSinceLastSaved =
                                mDeviceState.elapsedRealtime() - mSavedNitzTime.mElapsedRealtime;
                        int nitzUpdateSpacing = mDeviceState.getNitzUpdateSpacingMillis();
                        int nitzUpdateDiff = mDeviceState.getNitzUpdateDiffMillis();
                    if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
                            || (Math.abs(gained) > nitzUpdateDiff)) {
                        if (DBG) {
                            Rlog.d(LOG_TAG, "NITZ: Auto updating time of day to "
                                    + adjustedCurrentTimeMillis
                                    + " NITZ receive delay=" + millisSinceNitzReceived
                                    + "ms gained=" + gained + "ms from " + newNitzData);
                        }

                        setAndBroadcastNetworkSetTime(adjustedCurrentTimeMillis);
                        if (elapsedRealtimeSinceLastSaved > nitzUpdateSpacing
                                || Math.abs(gained) > nitzUpdateDiff) {
                            // Either it has been a while since we received an update, or the gain
                            // is sufficiently large that we want to act on it.
                            logMsg += ": New update received.";
                            setAndBroadcastNetworkSetTime(logMsg, adjustedCurrentTimeMillis);
                        } else {
                            if (DBG) {
                            Rlog.d(LOG_TAG, "NITZ: ignore, a previous update was "
                                    + timeSinceLastUpdate + "ms ago and gained="
                                    + gained + "ms");
                                Rlog.d(LOG_TAG, logMsg + ": Update throttled.");
                            }

                            // Return early. This means that we don't reset the
                            // mSavedNitzTime for next time and that we may act on more
                            // NITZ time signals overall but should end up with a system clock that
                            // tracks NITZ more closely than if we saved throttled values (which
                            // would reset mSavedNitzTime.elapsedRealtime used to calculate time
                            // since the last NITZ signal was received).
                            return;
                        }
                    }
                saveNitzTime(adjustedCurrentTimeMillis);
                }

                // Save the last NITZ time signal used so we can return to it later
                // if auto-time detection is toggled.
                mSavedNitzTime = new TimeStampedValue<>(
                        adjustedCurrentTimeMillis, nitzTimeSignal.mElapsedRealtime);
            } finally {
                mWakeLock.release();
            }
        } catch (RuntimeException ex) {
            Rlog.e(LOG_TAG, "NITZ: Processing NITZ data " + newNitzData + " ex=" + ex);
            Rlog.e(LOG_TAG, "setTimeFromNitz: Processing NITZ data " + nitzTimeSignal
                    + " ex=" + ex);
        }
    }

@@ -487,12 +544,6 @@ public class NitzStateMachine {
        mSavedTimeZoneId = zoneId;
    }

    private void saveNitzTime(long time) {
        mSavedTime = time;
        mSavedAtTime = mDeviceState.elapsedRealtime();
        mNitzUpdatedTime = true;
    }

    private void setAndBroadcastNetworkSetTimeZone(String zoneId) {
        if (DBG) {
            Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId);
@@ -505,24 +556,38 @@ public class NitzStateMachine {
        }
    }

    private void setAndBroadcastNetworkSetTime(long time) {
    private void setAndBroadcastNetworkSetTime(String msg, long time) {
        if (!mWakeLock.isHeld()) {
            Rlog.w(LOG_TAG, "Wake lock not held while setting device time (msg=" + msg + ")");
        }

        msg = "setAndBroadcastNetworkSetTime: [setting time to time=" + time + "]:" + msg;
        if (DBG) {
            Rlog.d(LOG_TAG, "setAndBroadcastNetworkSetTime: time=" + time + "ms");
            Rlog.d(LOG_TAG, msg);
        }
        mTimeLog.log(msg);
        mTimeServiceHelper.setDeviceTime(time);
        TelephonyMetrics.getInstance().writeNITZEvent(mPhone.getPhoneId(), time);
    }

    private void revertToNitzTime() {
        if (DBG) {
            Rlog.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedTime
                    + " mSavedAtTime=" + mSavedAtTime);
            Rlog.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedNitzTime);
        }
        if (mSavedNitzTime != null) {
            try {
                // Acquire the wakelock as we're reading the elapsed realtime clock here.
                mWakeLock.acquire();

                long elapsedRealtime = mDeviceState.elapsedRealtime();
                String msg = "Reverting to NITZ time, elapsedRealtime=" + elapsedRealtime
                        + " mSavedNitzTime=" + mSavedNitzTime;
                long adjustedCurrentTimeMillis =
                        mSavedNitzTime.mValue + (elapsedRealtime - mSavedNitzTime.mElapsedRealtime);
                setAndBroadcastNetworkSetTime(msg, adjustedCurrentTimeMillis);
            } finally {
                mWakeLock.release();
            }
        if (mSavedTime != 0 && mSavedAtTime != 0) {
            long currTime = mDeviceState.elapsedRealtime();
            mTimeLog.log("Reverting to NITZ time, currTime=" + currTime
                    + " mSavedAtTime=" + mSavedAtTime + " mSavedTime=" + mSavedTime);
            setAndBroadcastNetworkSetTime(mSavedTime + (currTime - mSavedAtTime));
        }
    }

@@ -546,14 +611,18 @@ public class NitzStateMachine {
     * Dumps the current in-memory state to the supplied PrintWriter.
     */
    public void dumpState(PrintWriter pw) {
        // Time Detection State
        pw.println(" mSavedTime=" + mSavedNitzTime);

        // Time Zone Detection State
        pw.println(" mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz);
        pw.println(" mNitzData=" + mNitzData);
        pw.println(" mGotCountryCode=" + mGotCountryCode);
        pw.println(" mSavedTimeZone=" + mSavedTimeZoneId);
        pw.println(" mSavedTime=" + mSavedTime);
        pw.println(" mSavedAtTime=" + mSavedAtTime);
        pw.println(" mNitzTimeZoneDetectionSuccessful=" + mNitzTimeZoneDetectionSuccessful);

        // Miscellaneous
        pw.println(" mWakeLock=" + mWakeLock);
        pw.println(" mNitzUpdatedTime=" + mNitzUpdatedTime);
        pw.flush();
    }

@@ -600,17 +669,17 @@ public class NitzStateMachine {
    }

    /**
     * Clear the mNitzUpdatedTime flag.
     * Clear the mNitzTimeZoneDetectionSuccessful flag.
     */
    public void clearNitzUpdatedTime() {
        mNitzUpdatedTime = false;
    public void clearNitzTimeZoneDetectionSuccessful() {
        mNitzTimeZoneDetectionSuccessful = false;
    }

    /**
     * Get the mNitzUpdatedTime flag value.
     * Get the mNitzTimeZoneDetectionSuccessful flag value.
     */
    public boolean getNitzUpdatedTime() {
        return mNitzUpdatedTime;
    public boolean getNitzTimeZoneDetectionSuccessful() {
        return mNitzTimeZoneDetectionSuccessful;
    }

    /**
@@ -621,10 +690,11 @@ public class NitzStateMachine {
    }

    /**
     * Returns true if mNitzUpdatedTime and automatic time zone detection is enabled.
     * Returns true if !mNitzTimeZoneDetectionSuccessful and automatic time zone detection is
     * enabled.
     */
    public boolean shouldUpdateTimeZoneUsingCountryCode() {
        return !mNitzUpdatedTime && mTimeServiceHelper.isTimeZoneDetectionEnabled();
        return !mNitzTimeZoneDetectionSuccessful && mTimeServiceHelper.isTimeZoneDetectionEnabled();
    }

    /**
@@ -648,5 +718,4 @@ public class NitzStateMachine {
    public boolean fixTimeZoneCallNeeded() {
        return mNeedFixZoneAfterNitz;
    }

}
+9 −8
Original line number Diff line number Diff line
@@ -559,7 +559,7 @@ public class ServiceStateTracker extends Handler {
        mMin = null;
        mPrlVersion = null;
        mIsMinInfoReady = false;
        mNitzState.clearNitzUpdatedTime();
        mNitzState.clearNitzTimeZoneDetectionSuccessful();

        //cancel any pending pollstate request on voice tech switching
        cancelPollState();
@@ -2548,7 +2548,7 @@ public class ServiceStateTracker extends Handler {
                mNewCellLoc.setStateInvalid();
                setSignalStrengthDefaultValues();
                mNitzState.setNetworkCountryIsoAvailable(false);
                mNitzState.clearNitzUpdatedTime();
                mNitzState.clearNitzTimeZoneDetectionSuccessful();
                pollStateDone();
                break;

@@ -2557,7 +2557,7 @@ public class ServiceStateTracker extends Handler {
                mNewCellLoc.setStateInvalid();
                setSignalStrengthDefaultValues();
                mNitzState.setNetworkCountryIsoAvailable(false);
                mNitzState.clearNitzUpdatedTime();
                mNitzState.clearNitzTimeZoneDetectionSuccessful();
                // don't poll when device is shutting down or the poll was not modemTrigged
                // (they sent us new radio data) and current network is not IWLAN
                if (mDeviceShuttingDown ||
@@ -2790,11 +2790,12 @@ public class ServiceStateTracker extends Handler {
            mNetworkAttachedRegistrants.notifyRegistrants();

            if (DBG) {
                log("pollStateDone: hasRegistered, current mNitzState.getNitzUpdatedTime()="
                        + mNitzState.getNitzUpdatedTime()
                        + ". Calling mNitzState.clearNitzUpdatedTime()");
                log("pollStateDone: hasRegistered,"
                        + " current mNitzState.getNitzTimeZoneDetectionSuccessful()="
                        + mNitzState.getNitzTimeZoneDetectionSuccessful()
                        + ". Calling mNitzState.clearNitzTimeZoneDetectionSuccessful()");
            }
            mNitzState.clearNitzUpdatedTime();
            mNitzState.clearNitzTimeZoneDetectionSuccessful();
        }

        if (hasDeregistered) {
@@ -2828,7 +2829,7 @@ public class ServiceStateTracker extends Handler {
                if (DBG) log("operatorNumeric " + operatorNumeric + " is invalid");
                tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), "");
                mNitzState.setNetworkCountryIsoAvailable(false);
                mNitzState.clearNitzUpdatedTime();
                mNitzState.clearNitzTimeZoneDetectionSuccessful();
            } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) {
                // Update time zone, ISO, and IDD.
                //
+9 −4
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        when(mDeviceState.getNitzUpdateDiffMillis()).thenReturn(2000);
        when(mDeviceState.getNitzUpdateSpacingMillis()).thenReturn(1000 * 60 * 10);
        when(mDeviceState.elapsedRealtime()).thenReturn(123456789L);
        when(mDeviceState.currentTimeMillis()).thenReturn(987654321L);

        mNitzStateMachine = new NitzStateMachine(mPhone, mTimeServiceHelper, mDeviceState);

@@ -70,6 +71,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        verify(mDeviceState, atLeast(0)).getNitzUpdateDiffMillis();
        verify(mDeviceState, atLeast(0)).getNitzUpdateSpacingMillis();
        verify(mDeviceState, atLeast(0)).elapsedRealtime();
        verify(mDeviceState, atLeast(0)).currentTimeMillis();
        verify(mDeviceState, atLeast(0)).getNetworkCountryIsoForPhone();
        verifyNoMoreInteractions(mDeviceState);

@@ -110,7 +112,8 @@ public class NitzStateMachineTest extends TelephonyTest {
        verifyTimeServiceTimeZoneWasSet(usNitzSignal.getTimeZoneId());
        verifyTimeServiceTimeWasSet(expectedAdjustedCurrentTimeMillis);

        assertTrue(mNitzStateMachine.getNitzUpdatedTime());

        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(usNitzSignal.getNitzData(), mNitzStateMachine.getCachedNitzData());
        assertEquals(usNitzSignal.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }
@@ -143,7 +146,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        verifyTimeServiceTimeZoneWasNotSet();
        verifyTimeServiceTimeWasSet(expectedAdjustedCurrentTimeMillis);

        assertTrue(mNitzStateMachine.getNitzUpdatedTime());
        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(usNitzSignal.getNitzData(), mNitzStateMachine.getCachedNitzData());
        assertEquals(usNitzSignal.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }
@@ -172,7 +175,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        verifyTimeServiceTimeZoneWasSet(usNitzSignal.getTimeZoneId());
        verifyTimeServiceTimeWasNotSet();

        assertTrue(mNitzStateMachine.getNitzUpdatedTime());
        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(usNitzSignal.getNitzData(), mNitzStateMachine.getCachedNitzData());
        assertEquals(usNitzSignal.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }
@@ -201,7 +204,7 @@ public class NitzStateMachineTest extends TelephonyTest {
        verifyTimeServiceTimeZoneWasNotSet();
        verifyTimeServiceTimeWasNotSet();

        assertTrue(mNitzStateMachine.getNitzUpdatedTime());
        assertTrue(mNitzStateMachine.getNitzTimeZoneDetectionSuccessful());
        assertEquals(usNitzSignal.getNitzData(), mNitzStateMachine.getCachedNitzData());
        assertEquals(usNitzSignal.getTimeZoneId(), mNitzStateMachine.getSavedTimeZoneId());
    }
@@ -227,6 +230,8 @@ public class NitzStateMachineTest extends TelephonyTest {
    private void incrementSimulatedDeviceClock(int incMillis) {
        long currentElapsedRealtime = mDeviceState.elapsedRealtime();
        when(mDeviceState.elapsedRealtime()).thenReturn(currentElapsedRealtime + incMillis);
        long currentTimeMillis = mDeviceState.currentTimeMillis();
        when(mDeviceState.elapsedRealtime()).thenReturn(currentTimeMillis + incMillis);
    }

    private static long createTime(TimeZone timeZone, int year, int monthOfYear, int dayOfMonth,