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

Commit 1fadd88b authored by Neil Fuller's avatar Neil Fuller
Browse files

Move empty time suggestion logic to the server

Move empty time suggestion logic to the time detector service.
Currently there is no support for "withdrawing" a time suggestion in the
service. This change moves the stubbing to the server. Currently the
service just uses the latest suggestion it has received regardless of
origin. This presents a possible issue on multi-phone devices because
the device could alternate between two times as NITZ signals come in.

In future, when the service tracks the origin of the suggestions and
tries to be "sticky", this will allow the service to switch from one
origin to another if an origin becomes "unsure". e.g. if we kept using
the last signal from the phone with the lowest ID, and stopped receiving
NITZ updates to that phone, we would keep using the last suggestion
"forever". By withdrawing the suggestion from a phone when leaving the
network the service can switch to existing signals received from another
device.

Bug: 140712361
Test: atest com.android.internal.telephony.NitzStateMachineImplTest
Test: atest com.android.internal.telephony.nitz
Change-Id: I2fea29a582b8bf56adce931a12189864fbd23a13
parent 7c03f28f
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -327,9 +327,8 @@ public final class NitzStateMachineImpl implements NitzStateMachine {
        mSavedTimeZoneId = null;
        mTimeZoneLog.log("handleNetworkUnavailable: NITZ state cleared.");

        // Avoid doing country-only detection work unnecessarily: if the mLatestNitzSignal was
        // already null we have nothing to do as it will have been done last time the
        // mLatestNitzSignal was cleared.
        // Avoid doing work unnecessarily: if the mLatestNitzSignal was already null we have nothing
        // to do as it will have been done last time the mLatestNitzSignal was cleared.
        if (oldNitzSignal == null) {
            return;
        }
@@ -342,6 +341,7 @@ public final class NitzStateMachineImpl implements NitzStateMachine {
        if (!TextUtils.isEmpty(isoCountryCode)) {
            updateTimeZoneFromNetworkCountryCode(isoCountryCode);
        }
        sendEmptyTimeSuggestion("handleNetworkUnavailable");
    }

    @Override
@@ -386,14 +386,29 @@ public final class NitzStateMachineImpl implements NitzStateMachine {
        mTimeLog.log("handleAirplaneModeChanged(" + on + "): Time state cleared.");

        mCountryIsoCode = null;

        TimestampedValue<NitzData> oldNitzSignal = mLatestNitzSignal;
        mLatestNitzSignal = null;
        mNitzTimeZoneDetectionSuccessful = false;
        mSavedTimeZoneId = null;

        if (oldNitzSignal == null) {
            // No work to do - terminate early.
            return;
        }

        mTimeZoneLog.log("handleAirplaneModeChanged(" + on + "): Time zone state cleared.");
        sendEmptyTimeSuggestion("handleAirplaneModeChanged(" + on + ")");
    }

    private void sendEmptyTimeSuggestion(String reason) {
        PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
        timeSuggestion.addDebugInfo("Empty suggestion, reason=" + reason);
        mTimeServiceHelper.suggestDeviceTime(timeSuggestion);
    }

    private void updateTimeFromNitz() {
        TimestampedValue<NitzData> nitzSignal = mLatestNitzSignal;
        TimestampedValue<NitzData> nitzSignal = Objects.requireNonNull(mLatestNitzSignal);
        try {
            boolean ignoreNitz = mDeviceState.getIgnoreNitz();
            if (ignoreNitz) {
@@ -469,8 +484,8 @@ public final class NitzStateMachineImpl implements NitzStateMachine {
                Rlog.d(LOG_TAG, logMsg);
            }
            mTimeLog.log(logMsg);
            PhoneTimeSuggestion phoneTimeSuggestion =
                    new PhoneTimeSuggestion(mPhone.getPhoneId(), newNitzTime);
            PhoneTimeSuggestion phoneTimeSuggestion = new PhoneTimeSuggestion(mPhone.getPhoneId());
            phoneTimeSuggestion.setUtcTime(newNitzTime);
            phoneTimeSuggestion.addDebugInfo(logMsg);
            mTimeServiceHelper.suggestDeviceTime(phoneTimeSuggestion);

+12 −14
Original line number Diff line number Diff line
@@ -310,22 +310,20 @@ public final class NewNitzStateMachineImpl implements NitzStateMachine {
            @NonNull String reason) {
        try {
            Objects.requireNonNull(reason);
            if (nitzSignal == null) {
                // Do nothing to withdraw previous suggestions: the service currently does not
                // support withdrawing suggestions.
                return;
            }

            Objects.requireNonNull(nitzSignal.getValue());

            PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhoneId);
            if (nitzSignal == null) {
                timeSuggestion.addDebugInfo("Clearing time zone suggestion"
                        + " reason=" + reason);
            } else {
                TimestampedValue<Long> newNitzTime = new TimestampedValue<>(
                        nitzSignal.getReferenceTimeMillis(),
                        nitzSignal.getValue().getCurrentTimeInMillis());
            PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(mPhoneId, newNitzTime);
            timeSuggestion.addDebugInfo("doTimeDetection: NITZ signal used"
                timeSuggestion.setUtcTime(newNitzTime);
                timeSuggestion.addDebugInfo("Sending new time zone suggestion"
                        + " nitzSignal=" + nitzSignal
                    + ", newNitzTime=" + newNitzTime
                        + ", reason=" + reason);
            }
            mNewTimeServiceHelper.suggestDeviceTime(timeSuggestion);
        } catch (RuntimeException ex) {
            Rlog.e(LOG_TAG, "doTimeDetection: Exception thrown"
+6 −5
Original line number Diff line number Diff line
@@ -62,13 +62,14 @@ public final class NewTimeServiceHelperImpl implements NewTimeServiceHelper {

    @Override
    public void suggestDeviceTime(@NonNull PhoneTimeSuggestion phoneTimeSuggestion) {
        mTimeLog.log("Suggesting system clock update: " + phoneTimeSuggestion);
        mTimeLog.log("Sending time suggestion: " + phoneTimeSuggestion);

        // 3 nullness assertions in 1 line
        Objects.requireNonNull(phoneTimeSuggestion.getUtcTime().getValue());
        Objects.requireNonNull(phoneTimeSuggestion);

        if (phoneTimeSuggestion.getUtcTime() != null) {
            TimestampedValue<Long> utcTime = phoneTimeSuggestion.getUtcTime();
            TelephonyMetrics.getInstance().writeNITZEvent(mPhoneId, utcTime.getValue());
        }
        mTimeDetector.suggestPhoneTime(phoneTimeSuggestion);
    }

+15 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.internal.telephony.NitzStateMachineTestSupport.UNIQUE_
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNIQUE_US_ZONE_SCENARIO2;
import static com.android.internal.telephony.NitzStateMachineTestSupport.UNITED_KINGDOM_SCENARIO;
import static com.android.internal.telephony.NitzStateMachineTestSupport.US_COUNTRY_DEFAULT_ZONE_ID;
import static com.android.internal.telephony.NitzStateMachineTestSupport.createEmptyTimeSuggestion;
import static com.android.internal.telephony.NitzStateMachineTestSupport.createTimeSuggestionFromNitzSignal;

import static org.junit.Assert.assertEquals;
@@ -892,8 +893,9 @@ public class NitzStateMachineImplTest extends TelephonyTest {
        assertNull(mNitzStateMachine.getSavedTimeZoneId());

        // Verify there's no time zone opinion by toggling auto time zone off and on.
        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
        script.toggleTimeZoneDetectionEnabled(false)
                .verifyNothingWasSetAndReset()
                .verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion)
                .toggleTimeZoneDetectionEnabled(true)
                .verifyNothingWasSetAndReset();

@@ -989,8 +991,10 @@ public class NitzStateMachineImplTest extends TelephonyTest {

        // Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state and stop
        // having an opinion about time zone.
        script.networkUnavailable()
                .verifyNothingWasSetAndReset();
        script.networkUnavailable();

        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
        script.verifyOnlyTimeWasSuggestedAndReset(emptyTimeSuggestion);

        // Simulate the passage of time and update the device realtime clock.
        scenario.incrementTime(timeStepMillis);
@@ -1091,8 +1095,10 @@ public class NitzStateMachineImplTest extends TelephonyTest {
        // Simulate losing the network. The NitzStateMachineImpl must lose all NITZ state but should
        // retain country knowledge and so remain opinionated about time zone ID because the country
        // is sufficient to detect time zone in the UK.
        script.networkUnavailable()
                .verifyOnlyTimeZoneWasSetAndReset(scenario.getTimeZoneId());
        script.networkUnavailable();

        PhoneTimeSuggestion emptyTimeSuggestion = createEmptyTimeSuggestion(mPhone.getPhoneId());
        script.verifyTimeSuggestedAndZoneSetAndReset(emptyTimeSuggestion, scenario.getTimeZoneId());

        // Simulate the passage of time and update the device realtime clock.
        scenario.incrementTime(timeStepMillis);
@@ -1372,9 +1378,11 @@ public class NitzStateMachineImplTest extends TelephonyTest {
        @Override
        public void suggestDeviceTime(PhoneTimeSuggestion phoneTimeSuggestion) {
            suggestedTime.set(phoneTimeSuggestion);
            if (phoneTimeSuggestion.getUtcTime() != null) {
                // The fake time service just uses the latest suggestion.
                mFakeDeviceState.currentTimeMillis = phoneTimeSuggestion.getUtcTime().getValue();
            }
        }

        void commitState() {
            deviceTimeZone.commitLatest();
+16 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.icu.util.TimeZone;
import android.util.TimestampedValue;

import com.android.internal.telephony.NitzStateMachine.DeviceState;
import com.android.internal.telephony.nitz.service.PhoneTimeZoneSuggestion;

/**
 * An assortment of methods and classes for testing {@link NitzStateMachine} implementations.
@@ -270,10 +271,23 @@ public final class NitzStateMachineTestSupport {
        return cal.getTimeInMillis();
    }

    public static PhoneTimeZoneSuggestion createEmptyTimeZoneSuggestion(int phoneId) {
        PhoneTimeZoneSuggestion timeZoneSuggestion = new PhoneTimeZoneSuggestion(phoneId);
        timeZoneSuggestion.addDebugInfo("Test");
        return timeZoneSuggestion;
    }

    public static PhoneTimeSuggestion createEmptyTimeSuggestion(int phoneId) {
        PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
        timeSuggestion.addDebugInfo("Test");
        return timeSuggestion;
    }

    public static PhoneTimeSuggestion createTimeSuggestionFromNitzSignal(
            int phoneId, TimestampedValue<NitzData> nitzSignal) {
        PhoneTimeSuggestion timeSuggestion =
                new PhoneTimeSuggestion(phoneId, createTimeSignalFromNitzSignal(nitzSignal));
        PhoneTimeSuggestion timeSuggestion = new PhoneTimeSuggestion(phoneId);
        timeSuggestion.setUtcTime(createTimeSignalFromNitzSignal(nitzSignal));
        timeSuggestion.addDebugInfo("Test");
        return timeSuggestion;
    }

Loading