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

Commit 0f61a4ac authored by Almaz Mingaleev's avatar Almaz Mingaleev Committed by Automerger Merge Worker
Browse files

Merge "Prepare to make time detection more configurable" am: ebec38b9

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1513289

Change-Id: Ibd6a844c1c69b55a5ddcb31b8427349b6ed731ca
parents dbe2b4be ebec38b9
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