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

Commit f9b1bad8 authored by Neil Fuller's avatar Neil Fuller
Browse files

Move other time config to ConfigurationInternal

Move other time detector config to ConfigurationInternal. This means
that all configuration, regardless of origin (settings, static config
xml, server flags, mixed) are accessed via ConfigurationInternal, not
from Environment, simplifying listening, enabling them to be more
dynamic in future, etc.

Bug: 172891783
Bug: 229740080
Test: atest com.android.server.timedetector android.app.time
Change-Id: I625e4fcfd6dd63ab4ebfb181611f977e8ad83f31
parent 7573cc80
Loading
Loading
Loading
Loading
+125 −12
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import static android.app.time.Capabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.time.Capabilities.CAPABILITY_NOT_SUPPORTED;
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;

import static java.util.stream.Collectors.joining;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.time.Capabilities.CapabilityState;
@@ -29,6 +31,10 @@ import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
import android.os.UserHandle;

import com.android.server.timedetector.TimeDetectorStrategy.Origin;

import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;

/**
@@ -39,12 +45,20 @@ import java.util.Objects;
public final class ConfigurationInternal {

    private final boolean mAutoDetectionSupported;
    private final int mSystemClockUpdateThresholdMillis;
    private final Instant mAutoTimeLowerBound;
    private final @Origin int[] mOriginPriorities;
    private final boolean mDeviceHasY2038Issue;
    private final boolean mAutoDetectionEnabledSetting;
    private final @UserIdInt int mUserId;
    private final boolean mUserConfigAllowed;

    private ConfigurationInternal(Builder builder) {
        mAutoDetectionSupported = builder.mAutoDetectionSupported;
        mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
        mAutoTimeLowerBound = Objects.requireNonNull(builder.mAutoTimeLowerBound);
        mOriginPriorities = Objects.requireNonNull(builder.mOriginPriorities);
        mDeviceHasY2038Issue = builder.mDeviceHasY2038Issue;
        mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;

        mUserId = builder.mUserId;
@@ -56,6 +70,42 @@ public final class ConfigurationInternal {
        return mAutoDetectionSupported;
    }

    /**
     * Returns the absolute threshold below which the system clock need not be updated. i.e. if
     * setting the system clock would adjust it by less than this (either backwards or forwards)
     * then it need not be set.
     */
    public int getSystemClockUpdateThresholdMillis() {
        return mSystemClockUpdateThresholdMillis;
    }

    /**
     * Returns the lower bound for valid automatic times. It is guaranteed to be in the past,
     * i.e. it is unrelated to the current system clock time.
     * It holds no other meaning; it could be related to when the device system image was built,
     * or could be updated by a mainline module.
     */
    @NonNull
    public Instant getAutoTimeLowerBound() {
        return mAutoTimeLowerBound;
    }

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

    /**
     * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
     * defines time_t as a 32-bit signed integer for 32-bit processes).
     */
    public boolean getDeviceHasY2038Issue() {
        return mDeviceHasY2038Issue;
    }

    /** Returns the value of the auto time detection enabled setting. */
    public boolean getAutoDetectionEnabledSetting() {
        return mAutoDetectionEnabledSetting;
@@ -146,38 +196,61 @@ public final class ConfigurationInternal {

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (this == o) {
            return true;
        }
        if (!(o instanceof ConfigurationInternal)) {
            return false;
        }
        ConfigurationInternal that = (ConfigurationInternal) o;
        return mAutoDetectionSupported == that.mAutoDetectionSupported
                && mUserId == that.mUserId
                && mUserConfigAllowed == that.mUserConfigAllowed
                && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting;
                && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
                && mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
                && mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
                && mAutoTimeLowerBound.equals(that.mAutoTimeLowerBound)
                && mDeviceHasY2038Issue == that.mDeviceHasY2038Issue
                && Arrays.equals(mOriginPriorities, that.mOriginPriorities);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mAutoDetectionSupported, mUserId,
                mUserConfigAllowed, mAutoDetectionEnabledSetting);
        int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
                mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoTimeLowerBound,
                mDeviceHasY2038Issue);
        result = 31 * result + Arrays.hashCode(mOriginPriorities);
        return result;
    }

    @Override
    public String toString() {
        String originPrioritiesString =
                Arrays.stream(mOriginPriorities)
                        .mapToObj(TimeDetectorStrategy::originToString)
                        .collect(joining(",", "[", "]"));
        return "ConfigurationInternal{"
                + "mAutoDetectionSupported=" + mAutoDetectionSupported
                + "mUserId=" + mUserId
                + ", mUserConfigAllowed=" + mUserConfigAllowed
                + ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
                + ", mAutoTimeLowerBound=" + mAutoTimeLowerBound
                + "(" + mAutoTimeLowerBound.toEpochMilli() + ")"
                + ", mOriginPriorities=" + originPrioritiesString
                + ", mDeviceHasY2038Issue=" + mDeviceHasY2038Issue
                + ", mAutoDetectionEnabled=" + mAutoDetectionEnabledSetting
                + ", mUserId=" + mUserId
                + ", mUserConfigAllowed=" + mUserConfigAllowed
                + '}';
    }

    static final class Builder {
        private final @UserIdInt int mUserId;

        private boolean mUserConfigAllowed;
        private boolean mAutoDetectionSupported;
        private int mSystemClockUpdateThresholdMillis;
        @NonNull private Instant mAutoTimeLowerBound;
        @NonNull private @Origin int[] mOriginPriorities;
        private boolean mDeviceHasY2038Issue;
        private boolean mAutoDetectionEnabledSetting;

        private final @UserIdInt int mUserId;
        private boolean mUserConfigAllowed;

        Builder(@UserIdInt int userId) {
            mUserId = userId;
        }
@@ -189,6 +262,10 @@ public final class ConfigurationInternal {
            this.mUserId = toCopy.mUserId;
            this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
            this.mAutoDetectionSupported = toCopy.mAutoDetectionSupported;
            this.mSystemClockUpdateThresholdMillis = toCopy.mSystemClockUpdateThresholdMillis;
            this.mAutoTimeLowerBound = toCopy.mAutoTimeLowerBound;
            this.mOriginPriorities = toCopy.mOriginPriorities;
            this.mDeviceHasY2038Issue = toCopy.mDeviceHasY2038Issue;
            this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
        }

@@ -208,6 +285,33 @@ public final class ConfigurationInternal {
            return this;
        }

        /**
         * Sets the absolute threshold below which the system clock need not be updated. i.e. if
         * setting the system clock would adjust it by less than this (either backwards or forwards)
         * then it need not be set.
         */
        public Builder setSystemClockUpdateThresholdMillis(int systemClockUpdateThresholdMillis) {
            mSystemClockUpdateThresholdMillis = systemClockUpdateThresholdMillis;
            return this;
        }

        /**
         * Sets the lower bound for valid automatic times.
         */
        public Builder setAutoTimeLowerBound(@NonNull Instant autoTimeLowerBound) {
            mAutoTimeLowerBound = Objects.requireNonNull(autoTimeLowerBound);
            return this;
        }

        /**
         * Sets the order to look at time suggestions when automatically detecting time.
         * See {@code #ORIGIN_} constants
         */
        public Builder setOriginPriorities(@NonNull @Origin int... originPriorities) {
            mOriginPriorities = Objects.requireNonNull(originPriorities);
            return this;
        }

        /**
         * Sets the value of the automatic time detection enabled setting for this device.
         */
@@ -216,6 +320,15 @@ public final class ConfigurationInternal {
            return this;
        }

        /**
         * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
         * defines time_t as a 32-bit signed integer for 32-bit processes).
         */
        Builder setDeviceHasY2038Issue(boolean deviceHasY2038Issue) {
            mDeviceHasY2038Issue = deviceHasY2038Issue;
            return this;
        }

        /** Returns a new {@link ConfigurationInternal}. */
        @NonNull
        ConfigurationInternal build() {
+0 −31
Original line number Diff line number Diff line
@@ -18,18 +18,14 @@ package com.android.server.timedetector;

import android.annotation.NonNull;
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserManager;
import android.util.Slog;

import com.android.server.timezonedetector.ConfigurationChangeListener;

import java.time.Instant;
import java.util.Objects;

/**
@@ -39,18 +35,13 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {

    private static final String LOG_TAG = TimeDetectorService.TAG;

    @NonNull private final Context mContext;
    @NonNull private final Handler mHandler;
    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
    @NonNull private final ContentResolver mContentResolver;
    @NonNull private final PowerManager.WakeLock mWakeLock;
    @NonNull private final AlarmManager mAlarmManager;
    @NonNull private final UserManager mUserManager;

    EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
        mContext = Objects.requireNonNull(context);
        mContentResolver = Objects.requireNonNull(context.getContentResolver());
        mHandler = Objects.requireNonNull(handler);
        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);

@@ -59,8 +50,6 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG));

        mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));

        mUserManager = Objects.requireNonNull(context.getSystemService(UserManager.class));
    }

    @Override
@@ -71,21 +60,6 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
        mServiceConfigAccessor.addConfigurationInternalChangeListener(configurationChangeListener);
    }

    @Override
    public int systemClockUpdateThresholdMillis() {
        return mServiceConfigAccessor.systemClockUpdateThresholdMillis();
    }

    @Override
    public Instant autoTimeLowerBound() {
        return mServiceConfigAccessor.autoTimeLowerBound();
    }

    @Override
    public int[] autoOriginPriorities() {
        return mServiceConfigAccessor.getOriginPriorities();
    }

    @Override
    public ConfigurationInternal getCurrentUserConfigurationInternal() {
        return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
@@ -121,11 +95,6 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
        mWakeLock.release();
    }

    @Override
    public boolean deviceHasY2038Issue() {
        return Build.SUPPORTED_32_BIT_ABIS.length > 0;
    }

    private void checkWakeLockHeld() {
        if (!mWakeLock.isHeld()) {
            Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
+0 −26
Original line number Diff line number Diff line
@@ -19,11 +19,8 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.time.TimeConfiguration;

import com.android.server.timedetector.TimeDetectorStrategy.Origin;
import com.android.server.timezonedetector.ConfigurationChangeListener;

import java.time.Instant;

/**
 * An interface that provides access to service configuration for time detection. This hides
 * how configuration is split between static, compile-time config, dynamic server-pushed flags and
@@ -68,27 +65,4 @@ public interface ServiceConfigAccessor {
     */
    @NonNull
    ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);

    /**
     * Returns the absolute threshold below which the system clock need not be updated. i.e. if
     * setting the system clock would adjust it by less than this (either backwards or forwards)
     * then it need not be set.
     */
    int systemClockUpdateThresholdMillis();

    /**
     * Returns a lower bound for valid automatic times. It is guaranteed to be in the past,
     * i.e. it is unrelated to the current system clock time.
     * It holds no other meaning; it could be related to when the device system image was built,
     * or could be updated by a mainline module.
     */
    @NonNull
    Instant autoTimeLowerBound();

    /**
     * Returns the order to look at time suggestions when automatically detecting time.
     * See {@code #ORIGIN_} constants
     */
    @NonNull
    @Origin int[] getOriginPriorities();
}
+32 −27
Original line number Diff line number Diff line
@@ -182,33 +182,6 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
        mConfigurationInternalListeners.remove(Objects.requireNonNull(listener));
    }

    @Override
    @NonNull
    public @Origin int[] getOriginPriorities() {
        int[] serverFlagsValue = mServerFlagsOriginPrioritiesSupplier.get();
        if (serverFlagsValue != null) {
            return serverFlagsValue;
        }

        int[] configValue = mConfigOriginPrioritiesSupplier.get();
        if (configValue != null) {
            return configValue;
        }
        return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
    }

    @Override
    public int systemClockUpdateThresholdMillis() {
        return mSystemClockUpdateThresholdMillis;
    }

    @Override
    @NonNull
    public Instant autoTimeLowerBound() {
        return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
                .orElse(TIME_LOWER_BOUND_DEFAULT);
    }

    @Override
    @NonNull
    public synchronized ConfigurationInternal getCurrentUserConfigurationInternal() {
@@ -268,6 +241,10 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
                .setUserConfigAllowed(isUserConfigAllowed(userId))
                .setAutoDetectionSupported(isAutoDetectionSupported())
                .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
                .setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
                .setAutoTimeLowerBound(getAutoTimeLowerBound())
                .setOriginPriorities(getOriginPriorities())
                .setDeviceHasY2038Issue(getDeviceHasY2038Issue())
                .build();
    }

@@ -309,6 +286,34 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
        return false;
    }

    private int getSystemClockUpdateThresholdMillis() {
        return mSystemClockUpdateThresholdMillis;
    }

    @NonNull
    private Instant getAutoTimeLowerBound() {
        return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
                .orElse(TIME_LOWER_BOUND_DEFAULT);
    }

    @NonNull
    private @Origin int[] getOriginPriorities() {
        @Origin int[] serverFlagsValue = mServerFlagsOriginPrioritiesSupplier.get();
        if (serverFlagsValue != null) {
            return serverFlagsValue;
        }

        @Origin int[] configValue = mConfigOriginPrioritiesSupplier.get();
        if (configValue != null) {
            return configValue;
        }
        return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
    }

    private boolean getDeviceHasY2038Issue() {
        return Build.SUPPORTED_32_BIT_ABIS.length > 0;
    }

    /**
     * A base supplier of an array of time origin integers in priority order.
     * It handles memoization of the result to avoid repeated string parsing when nothing has
+9 −47
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.server.timedetector;

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

import static java.util.stream.Collectors.joining;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
@@ -153,28 +151,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        /** Returns the {@link ConfigurationInternal} for the current user. */
        @NonNull ConfigurationInternal getCurrentUserConfigurationInternal();

        /**
         * Returns the absolute threshold below which the system clock need not be updated. i.e. if
         * setting the system clock would adjust it by less than this (either backwards or forwards)
         * then it need not be set.
         */
        int systemClockUpdateThresholdMillis();

        /**
         * Returns a lower bound for valid automatic times. It is guaranteed to be in the past,
         * i.e. it is unrelated to the current system clock time.
         * It holds no other meaning; it could be related to when the device system image was built,
         * or could be updated by a mainline module.
         */
        @NonNull
        Instant autoTimeLowerBound();

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

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

@@ -191,12 +167,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {

        /** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
        void releaseWakeLock();

        /**
         * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
         * defines time_t as a 32-bit signed integer for 32-bit processes).
         */
        boolean deviceHasY2038Issue();
    }

    static TimeDetectorStrategy create(
@@ -384,25 +354,13 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {

        ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
        ipw.println("mCurrentConfigurationInternal=" + mCurrentConfigurationInternal);
        ipw.println("[Capabilities=" + mCurrentConfigurationInternal.capabilitiesAndConfig()
                + "]");
        ipw.println("[Capabilities=" + mCurrentConfigurationInternal.capabilitiesAndConfig() + "]");
        long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
        ipw.printf("mEnvironment.elapsedRealtimeMillis()=%s (%s)\n",
                Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
        long systemClockMillis = mEnvironment.systemClockMillis();
        ipw.printf("mEnvironment.systemClockMillis()=%s (%s)\n",
                Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
        ipw.println("mEnvironment.systemClockUpdateThresholdMillis()="
                + mEnvironment.systemClockUpdateThresholdMillis());
        Instant autoTimeLowerBound = mEnvironment.autoTimeLowerBound();
        ipw.printf("mEnvironment.autoTimeLowerBound()=%s (%s)\n",
                autoTimeLowerBound, autoTimeLowerBound.toEpochMilli());
        String priorities =
                Arrays.stream(mEnvironment.autoOriginPriorities())
                        .mapToObj(TimeDetectorStrategy::originToString)
                        .collect(joining(",", "[", "]"));
        ipw.println("mEnvironment.autoOriginPriorities()=" + priorities);
        ipw.println("mEnvironment.deviceHasY2038Issue()=" + mEnvironment.deviceHasY2038Issue());

        ipw.println("Time change log:");
        ipw.increaseIndent(); // level 2
@@ -467,6 +425,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        return true;
    }

    @GuardedBy("this")
    private boolean validateSuggestionTime(
            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
        if (newUnixEpochTime.getValue() == null) {
@@ -485,7 +444,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        }

        if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
                && mEnvironment.deviceHasY2038Issue()) {
                && mCurrentConfigurationInternal.getDeviceHasY2038Issue()) {
            // This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
            // seconds through the normal passage of time, but it will stop it jumping above 2038
            // because of a "bad" suggestion. b/204193177
@@ -496,15 +455,17 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        return true;
    }

    @GuardedBy("this")
    private boolean validateAutoSuggestionTime(
            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion)  {
        return validateSuggestionTime(newUnixEpochTime, suggestion)
                && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion);
    }

    @GuardedBy("this")
    private boolean validateSuggestionAgainstLowerBound(
            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
        Instant lowerBound = mEnvironment.autoTimeLowerBound();
        Instant lowerBound = mCurrentConfigurationInternal.getAutoTimeLowerBound();

        // Suggestion is definitely wrong if it comes before lower time bound.
        if (lowerBound.isAfter(Instant.ofEpochMilli(newUnixEpochTime.getValue()))) {
@@ -524,7 +485,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        }

        // Try the different origins one at a time.
        int[] originPriorities = mEnvironment.autoOriginPriorities();
        int[] originPriorities = mCurrentConfigurationInternal.getAutoOriginPriorities();
        for (int origin : originPriorities) {
            TimestampedValue<Long> newUnixEpochTime = null;
            String cause = null;
@@ -814,7 +775,8 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
        // Check if the new signal would make sufficient difference to the system clock. If it's
        // below the threshold then ignore it.
        long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
        long systemClockUpdateThreshold = mEnvironment.systemClockUpdateThresholdMillis();
        long systemClockUpdateThreshold =
                mCurrentConfigurationInternal.getSystemClockUpdateThresholdMillis();
        if (absTimeDifference < systemClockUpdateThreshold) {
            if (DBG) {
                Slog.d(LOG_TAG, "Not setting system clock. New time and"
Loading