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

Commit ebec38b9 authored by Almaz Mingaleev's avatar Almaz Mingaleev Committed by Gerrit Code Review
Browse files

Merge "Prepare to make time detection more configurable"

parents 23b7c01b 10158975
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
    /** Internal method for handling the auto time setting being changed. */
    @VisibleForTesting
    public void handleAutoTimeDetectionChanged() {
        mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged);
        mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged);
    }

    @Override
+61 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.timedetector;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.timedetector.ManualTimeSuggestion;
@@ -24,6 +25,8 @@ import android.app.timedetector.TelephonyTimeSuggestion;
import android.os.TimestampedValue;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * The interface for the class that implements the time detection algorithm used by the
@@ -37,22 +40,41 @@ import java.io.PrintWriter;
 */
public interface TimeDetectorStrategy {

    /** Process the suggested time from telephony sources. */
    @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
    @Retention(RetentionPolicy.SOURCE)
    @interface Origin {}

    /** Used when a time value originated from a telephony signal. */
    @Origin
    int ORIGIN_TELEPHONY = 1;

    /** Used when a time value originated from a user / manual settings. */
    @Origin
    int ORIGIN_MANUAL = 2;

    /** Used when a time value originated from a network signal. */
    @Origin
    int ORIGIN_NETWORK = 3;

    /** Processes the suggested time from telephony sources. */
    void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);

    /**
     * Process the suggested manually entered time. Returns {@code false} if the suggestion was
     * Processes the suggested manually entered time. Returns {@code false} if the suggestion was
     * invalid, or the device configuration prevented the suggestion being used, {@code true} if the
     * suggestion was accepted. A suggestion that is valid but does not change the time because it
     * matches the current device time is considered accepted.
     */
    boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion);

    /** Process the suggested time from network sources. */
    /** Processes the suggested time from network sources. */
    void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);

    /** Handle the auto-time setting being toggled on or off. */
    void handleAutoTimeDetectionChanged();
    /**
     * Handles the auto-time configuration changing For example, when the auto-time setting is
     * toggled on or off.
     */
    void handleAutoTimeConfigChanged();

    /** Dump debug information. */
    void dump(@NonNull PrintWriter pw, @Nullable String[] args);
@@ -67,4 +89,38 @@ public interface TimeDetectorStrategy {
        return (referenceClockMillisNow - timeValue.getReferenceTimeMillis())
                + timeValue.getValue();
    }

    /**
     * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config
     * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized.
     */
    static String originToString(@Origin int origin) {
        switch (origin) {
            case ORIGIN_MANUAL:
                return "manual";
            case ORIGIN_NETWORK:
                return "network";
            case ORIGIN_TELEPHONY:
                return "telephony";
            default:
                throw new IllegalArgumentException("origin=" + origin);
        }
    }

    /**
     * Converts a human readable config string to one of the {@code ORIGIN_} constants.
     * Throws an {@link IllegalArgumentException} if the value is unrecognized.
     */
    static @Origin int stringToOrigin(String originString) {
        switch (originString) {
            case "manual":
                return ORIGIN_MANUAL;
            case "network":
                return ORIGIN_NETWORK;
            case "telephony":
                return ORIGIN_TELEPHONY;
            default:
                throw new IllegalArgumentException("originString=" + originString);
        }
    }
}
+17 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.timedetector;

import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;

import android.annotation.NonNull;
import android.app.AlarmManager;
import android.content.ContentResolver;
@@ -58,6 +60,7 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
    @NonNull private final ContentResolver mContentResolver;
    @NonNull private final PowerManager.WakeLock mWakeLock;
    @NonNull private final AlarmManager mAlarmManager;
    @NonNull private final int[] mOriginPriorities;

    public TimeDetectorStrategyCallbackImpl(@NonNull Context context) {
        mContext = Objects.requireNonNull(context);
@@ -72,6 +75,15 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
        mSystemClockUpdateThresholdMillis =
                SystemProperties.getInt("ro.sys.time_detector_update_diff",
                        SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);

        // TODO(b/172230856): Obtain these values from configuration.
        String[] originStrings = { "telephony", "network" };
        int[] origins = new int[originStrings.length];
        for (int i = 0; i < originStrings.length; i++) {
            int origin = stringToOrigin(originStrings[i]);
            origins[i] = origin;
        }
        mOriginPriorities = origins;
    }

    @Override
@@ -93,6 +105,11 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat
        return TIME_LOWER_BOUND;
    }

    @Override
    public int[] getAutoOriginPriorities() {
        return mOriginPriorities;
    }

    @Override
    public void acquireWakeLock() {
        if (mWakeLock.isHeld()) {
+49 −48
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@

package com.android.server.timedetector;

import android.annotation.IntDef;
import static com.android.server.timedetector.TimeDetectorStrategy.originToString;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
@@ -34,9 +35,8 @@ import com.android.server.timezonedetector.ArrayMapWithHistory;
import com.android.server.timezonedetector.ReferenceWithHistory;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
import java.util.Arrays;

/**
 * An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
@@ -64,22 +64,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
    static final long MAX_UTC_TIME_AGE_MILLIS =
            TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS;

    @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Origin {}

    /** Used when a time value originated from a telephony signal. */
    @Origin
    private static final int ORIGIN_TELEPHONY = 1;

    /** Used when a time value originated from a user / manual settings. */
    @Origin
    private static final int ORIGIN_MANUAL = 2;

    /** Used when a time value originated from a network signal. */
    @Origin
    private static final int ORIGIN_NETWORK = 3;

    /**
     * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the
     * actual system clock time before a warning is logged. Used to help identify situations where
@@ -153,6 +137,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        @NonNull
        Instant autoTimeLowerBound();

        /**
         * Returns the order to look at time suggestions when automatically detecting time.
         * See {@code #ORIGIN_} constants
         */
        @Origin int[] getAutoOriginPriorities();

        /** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
        void acquireWakeLock();

@@ -237,12 +227,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
    }

    @Override
    public synchronized void handleAutoTimeDetectionChanged() {
    public synchronized void handleAutoTimeConfigChanged() {
        boolean enabled = mCallback.isAutoTimeDetectionEnabled();
        // When automatic time detection is enabled we update the system clock instantly if we can.
        // Conversely, when automatic time detection is disabled we leave the clock as it is.
        if (enabled) {
            String reason = "Auto time zone detection setting enabled.";
            String reason = "Auto time zone detection config changed.";
            doAutoTimeDetection(reason);
        } else {
            // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what
@@ -365,33 +355,44 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
            return;
        }

        // Android devices currently prioritize any telephony over network signals. There are
        // carrier compliance tests that would need to be changed before we could ignore NITZ or
        // prefer NTP generally. This check is cheap on devices without telephony hardware.
        // Try the different origins one at a time.
        int[] originPriorities = mCallback.getAutoOriginPriorities();
        for (int origin : originPriorities) {
            TimestampedValue<Long> newUtcTime = null;
            String cause = null;
            if (origin == ORIGIN_TELEPHONY) {
                TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
                if (bestTelephonySuggestion != null) {
            final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime();
            String cause = "Found good telephony suggestion."
                    newUtcTime = bestTelephonySuggestion.getUtcTime();
                    cause = "Found good telephony suggestion."
                            + ", bestTelephonySuggestion=" + bestTelephonySuggestion
                            + ", detectionReason=" + detectionReason;
            setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause);
            return;
                }

        // There is no good telephony suggestion, try network.
            } else if (origin == ORIGIN_NETWORK) {
                NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
                if (networkSuggestion != null) {
            final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime();
            String cause = "Found good network suggestion."
                    newUtcTime = networkSuggestion.getUtcTime();
                    cause = "Found good network suggestion."
                            + ", networkSuggestion=" + networkSuggestion
                            + ", detectionReason=" + detectionReason;
            setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause);
                }
            } else {
                Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin
                        + " in " + Arrays.toString(originPriorities)
                        + ": Skipping");
            }

            // Update the system clock if a good suggestion has been found.
            if (newUtcTime != null) {
                setSystemClockIfRequired(origin, newUtcTime, cause);
                return;
            }
        }

        if (DBG) {
            Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion."
                    + " detectionReason=" + detectionReason);
            Slog.d(LOG_TAG, "Could not determine time: No suggestion found in"
                    + " originPriorities=" + Arrays.toString(originPriorities)
                    + ", detectionReason=" + detectionReason);
        }
    }

@@ -525,7 +526,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
            if (!mCallback.isAutoTimeDetectionEnabled()) {
                if (DBG) {
                    Slog.d(LOG_TAG, "Auto time detection is not enabled."
                            + " origin=" + origin
                            + " origin=" + originToString(origin)
                            + ", time=" + time
                            + ", cause=" + cause);
                }
@@ -535,7 +536,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
            if (mCallback.isAutoTimeDetectionEnabled()) {
                if (DBG) {
                    Slog.d(LOG_TAG, "Auto time detection is enabled."
                            + " origin=" + origin
                            + " origin=" + originToString(origin)
                            + ", time=" + time
                            + ", cause=" + cause);
                }
@@ -557,7 +558,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {

    @GuardedBy("this")
    private boolean setSystemClockUnderWakeLock(
            int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) {
            @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) {

        long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis();
        boolean isOriginAutomatic = isOriginAutomatic(origin);
+1 −1
Original line number Diff line number Diff line
@@ -242,7 +242,7 @@ public class TimeDetectorServiceTest {
        }

        @Override
        public void handleAutoTimeDetectionChanged() {
        public void handleAutoTimeConfigChanged() {
            mHandleAutoTimeDetectionChangedCalled = true;
        }

Loading