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

Commit 07701d7a authored by Neil Fuller's avatar Neil Fuller Committed by Android (Google) Code Review
Browse files

Merge "Time Detection improvements"

parents 05608001 25b55a71
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,