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

Commit 5a020246 authored by Neil Fuller's avatar Neil Fuller
Browse files

Add location-based tz detection in the background

Add support for running location-based tz detection in the background.

This is intended for use during QA / internal testing to understand the
behavior without affecting the tester's actual device time zone. For
example, this could help prove that the feature is broken with certain
flags without inconveniencing the testers too much: they can turn off
"Use location to set time zone" and we can still get useful feedback.

Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/
Bug: 200279201
Change-Id: I63a3cd02293a1c2322abb669b9804ac560858ba1
parent bae46650
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ public final class ServerFlags {
     */
    @StringDef(prefix = "KEY_", value = {
            KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
            KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED,
            KEY_PRIMARY_LTZP_MODE_OVERRIDE,
            KEY_SECONDARY_LTZP_MODE_OVERRIDE,
            KEY_LTZP_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
@@ -81,6 +82,15 @@ public final class ServerFlags {
    public static final @DeviceConfigKey String KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED =
            "location_time_zone_detection_feature_supported";

    /**
     * Controls whether location time zone detection should run all the time on supported devices,
     * even when the user has not enabled it explicitly in settings. Enabled for internal testing
     * only.
     */
    public static final @DeviceConfigKey String
            KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED =
            "location_time_zone_detection_run_in_background_enabled";

    /**
     * The key for the server flag that can override the device config for whether the primary
     * location time zone provider is enabled, disabled, or (for testing) in simulation mode.
+69 −8
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ 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 android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.time.TimeZoneCapabilities;
@@ -28,6 +29,10 @@ import android.app.time.TimeZoneCapabilitiesAndConfig;
import android.app.time.TimeZoneConfiguration;
import android.os.UserHandle;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;

/**
@@ -37,9 +42,23 @@ import java.util.Objects;
 */
public final class ConfigurationInternal {

    @IntDef(prefix = "DETECTION_MODE_",
            value = { DETECTION_MODE_UNKNOWN, DETECTION_MODE_MANUAL, DETECTION_MODE_GEO,
                    DETECTION_MODE_TELEPHONY }
    )
    @Retention(RetentionPolicy.SOURCE)
    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
    @interface DetectionMode {};

    public static final @DetectionMode int DETECTION_MODE_UNKNOWN = 0;
    public static final @DetectionMode int DETECTION_MODE_MANUAL = 1;
    public static final @DetectionMode int DETECTION_MODE_GEO = 2;
    public static final @DetectionMode int DETECTION_MODE_TELEPHONY = 3;

    private final boolean mTelephonyDetectionSupported;
    private final boolean mGeoDetectionSupported;
    private final boolean mTelephonyFallbackSupported;
    private final boolean mGeoDetectionRunInBackgroundEnabled;
    private final boolean mEnhancedMetricsCollectionEnabled;
    private final boolean mAutoDetectionEnabledSetting;
    private final @UserIdInt int mUserId;
@@ -51,6 +70,7 @@ public final class ConfigurationInternal {
        mTelephonyDetectionSupported = builder.mTelephonyDetectionSupported;
        mGeoDetectionSupported = builder.mGeoDetectionSupported;
        mTelephonyFallbackSupported = builder.mTelephonyFallbackSupported;
        mGeoDetectionRunInBackgroundEnabled = builder.mGeoDetectionRunInBackgroundEnabled;
        mEnhancedMetricsCollectionEnabled = builder.mEnhancedMetricsCollectionEnabled;
        mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;

@@ -83,6 +103,16 @@ public final class ConfigurationInternal {
        return mTelephonyFallbackSupported;
    }

    /**
     * Returns {@code true} if location time zone detection should run all the time on supported
     * devices, even when the user has not enabled it explicitly in settings. Enabled for internal
     * testing only. See {@link #isGeoDetectionExecutionEnabled()} and {@link #getDetectionMode()}
     * for details.
     */
    boolean getGeoDetectionRunInBackgroundEnabled() {
        return mGeoDetectionRunInBackgroundEnabled;
    }

    /**
     * Returns {@code true} if the device can collect / report extra metrics information for QA
     * / testers. These metrics might involve logging more expensive or more revealing data that
@@ -132,14 +162,31 @@ public final class ConfigurationInternal {
    }

    /**
     * Returns true if geolocation time zone detection behavior is actually enabled, which can be
     * distinct from the raw setting value.
     * Returns the detection mode to use, i.e. which suggestions to use to determine the device's
     * time zone.
     */
    public boolean getGeoDetectionEnabledBehavior() {
        return getAutoDetectionEnabledBehavior()
                && isGeoDetectionSupported()
    public @DetectionMode int getDetectionMode() {
        if (!getAutoDetectionEnabledBehavior()) {
            return DETECTION_MODE_MANUAL;
        } else if (isGeoDetectionSupported() && getLocationEnabledSetting()
                && getGeoDetectionEnabledSetting()) {
            return DETECTION_MODE_GEO;
        } else {
            return DETECTION_MODE_TELEPHONY;
        }
    }

    /**
     * Returns true if geolocation time zone detection behavior can execute. Typically, this will
     * agree with {@link #getDetectionMode()}, but under rare circumstances the geolocation detector
     * may be run in the background if the user's settings allow. See also {@link
     * #getGeoDetectionRunInBackgroundEnabled()}.
     */
    public boolean isGeoDetectionExecutionEnabled() {
        return isGeoDetectionSupported()
                && getLocationEnabledSetting()
                && getGeoDetectionEnabledSetting();
                && ((mAutoDetectionEnabledSetting && getGeoDetectionEnabledSetting())
                || getGeoDetectionRunInBackgroundEnabled());
    }

    /** Creates a {@link TimeZoneCapabilitiesAndConfig} object using the configuration values. */
@@ -238,6 +285,7 @@ public final class ConfigurationInternal {
                && mTelephonyDetectionSupported == that.mTelephonyDetectionSupported
                && mGeoDetectionSupported == that.mGeoDetectionSupported
                && mTelephonyFallbackSupported == that.mTelephonyFallbackSupported
                && mGeoDetectionRunInBackgroundEnabled == that.mGeoDetectionRunInBackgroundEnabled
                && mEnhancedMetricsCollectionEnabled == that.mEnhancedMetricsCollectionEnabled
                && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
                && mLocationEnabledSetting == that.mLocationEnabledSetting
@@ -248,8 +296,8 @@ public final class ConfigurationInternal {
    public int hashCode() {
        return Objects.hash(mUserId, mUserConfigAllowed, mTelephonyDetectionSupported,
                mGeoDetectionSupported, mTelephonyFallbackSupported,
                mEnhancedMetricsCollectionEnabled, mAutoDetectionEnabledSetting,
                mLocationEnabledSetting, mGeoDetectionEnabledSetting);
                mGeoDetectionRunInBackgroundEnabled, mEnhancedMetricsCollectionEnabled,
                mAutoDetectionEnabledSetting, mLocationEnabledSetting, mGeoDetectionEnabledSetting);
    }

    @Override
@@ -260,6 +308,7 @@ public final class ConfigurationInternal {
                + ", mTelephonyDetectionSupported=" + mTelephonyDetectionSupported
                + ", mGeoDetectionSupported=" + mGeoDetectionSupported
                + ", mTelephonyFallbackSupported=" + mTelephonyFallbackSupported
                + ", mGeoDetectionRunInBackgroundEnabled=" + mGeoDetectionRunInBackgroundEnabled
                + ", mEnhancedMetricsCollectionEnabled=" + mEnhancedMetricsCollectionEnabled
                + ", mAutoDetectionEnabledSetting=" + mAutoDetectionEnabledSetting
                + ", mLocationEnabledSetting=" + mLocationEnabledSetting
@@ -278,6 +327,7 @@ public final class ConfigurationInternal {
        private boolean mTelephonyDetectionSupported;
        private boolean mGeoDetectionSupported;
        private boolean mTelephonyFallbackSupported;
        private boolean mGeoDetectionRunInBackgroundEnabled;
        private boolean mEnhancedMetricsCollectionEnabled;
        private boolean mAutoDetectionEnabledSetting;
        private boolean mLocationEnabledSetting;
@@ -299,6 +349,7 @@ public final class ConfigurationInternal {
            this.mTelephonyDetectionSupported = toCopy.mTelephonyDetectionSupported;
            this.mTelephonyFallbackSupported = toCopy.mTelephonyFallbackSupported;
            this.mGeoDetectionSupported = toCopy.mGeoDetectionSupported;
            this.mGeoDetectionRunInBackgroundEnabled = toCopy.mGeoDetectionRunInBackgroundEnabled;
            this.mEnhancedMetricsCollectionEnabled = toCopy.mEnhancedMetricsCollectionEnabled;
            this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
            this.mLocationEnabledSetting = toCopy.mLocationEnabledSetting;
@@ -338,6 +389,16 @@ public final class ConfigurationInternal {
            return this;
        }

        /**
         * Sets whether location time zone detection should run all the time on supported devices,
         * even when the user has not enabled it explicitly in settings. Enabled for internal
         * testing only.
         */
        public Builder setGeoDetectionRunInBackgroundEnabled(boolean enabled) {
            mGeoDetectionRunInBackgroundEnabled = enabled;
            return this;
        }

        /**
         * Sets the value for enhanced metrics collection.
         */
+25 −10
Original line number Diff line number Diff line
@@ -45,14 +45,17 @@ import java.util.Objects;
public final class MetricsTimeZoneDetectorState {

    @IntDef(prefix = "DETECTION_MODE_",
            value = { DETECTION_MODE_MANUAL, DETECTION_MODE_GEO, DETECTION_MODE_TELEPHONY})
            value = { DETECTION_MODE_UNKNOWN, DETECTION_MODE_MANUAL, DETECTION_MODE_GEO,
                    DETECTION_MODE_TELEPHONY }
    )
    @Retention(RetentionPolicy.SOURCE)
    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
    public @interface DetectionMode {};

    public static final @DetectionMode int DETECTION_MODE_MANUAL = 0;
    public static final @DetectionMode int DETECTION_MODE_GEO = 1;
    public static final @DetectionMode int DETECTION_MODE_TELEPHONY = 2;
    public static final @DetectionMode int DETECTION_MODE_UNKNOWN = 0;
    public static final @DetectionMode int DETECTION_MODE_MANUAL = 1;
    public static final @DetectionMode int DETECTION_MODE_GEO = 2;
    public static final @DetectionMode int DETECTION_MODE_TELEPHONY = 3;

    @NonNull private final ConfigurationInternal mConfigurationInternal;
    private final int mDeviceTimeZoneIdOrdinal;
@@ -123,6 +126,15 @@ public final class MetricsTimeZoneDetectorState {
        return mConfigurationInternal.isTelephonyFallbackSupported();
    }

    /**
     * Returns {@code true} if location time zone detection should run all the time on supported
     * devices, even when the user has not enabled it explicitly in settings. Enabled for internal
     * testing only.
     */
    public boolean getGeoDetectionRunInBackgroundEnabled() {
        return mConfigurationInternal.getGeoDetectionRunInBackgroundEnabled();
    }

    /** Returns true if enhanced metric collection is enabled. */
    public boolean isEnhancedMetricsCollectionEnabled() {
        return mConfigurationInternal.isEnhancedMetricsCollectionEnabled();
@@ -148,12 +160,15 @@ public final class MetricsTimeZoneDetectorState {
     * things besides the user's setting.
     */
    public @DetectionMode int getDetectionMode() {
        if (!mConfigurationInternal.getAutoDetectionEnabledBehavior()) {
        switch (mConfigurationInternal.getDetectionMode()) {
            case ConfigurationInternal.DETECTION_MODE_MANUAL:
                return DETECTION_MODE_MANUAL;
        } else if (mConfigurationInternal.getGeoDetectionEnabledBehavior()) {
            case ConfigurationInternal.DETECTION_MODE_GEO:
                return DETECTION_MODE_GEO;
        } else {
            case ConfigurationInternal.DETECTION_MODE_TELEPHONY:
                return DETECTION_MODE_TELEPHONY;
            default:
                return DETECTION_MODE_UNKNOWN;
        }
    }

+15 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
    private static final Set<String> CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH =
            Collections.unmodifiableSet(new ArraySet<>(new String[] {
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED,
                    ServerFlags.KEY_ENHANCED_METRICS_COLLECTION_ENABLED,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
@@ -75,6 +76,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
    private static final Set<String> LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH =
            Collections.unmodifiableSet(new ArraySet<>(new String[] {
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
                    ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE,
@@ -297,6 +299,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
                        isTelephonyTimeZoneDetectionFeatureSupported())
                .setGeoDetectionFeatureSupported(isGeoTimeZoneDetectionFeatureSupported())
                .setTelephonyFallbackSupported(isTelephonyFallbackSupported())
                .setGeoDetectionRunInBackgroundEnabled(getGeoDetectionRunInBackgroundEnabled())
                .setEnhancedMetricsCollectionEnabled(isEnhancedMetricsCollectionEnabled())
                .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
                .setUserConfigAllowed(isUserConfigAllowed(userId))
@@ -402,6 +405,18 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
                defaultEnabled);
    }

    /**
     * Returns {@code true} if location time zone detection should run all the time on supported
     * devices, even when the user has not enabled it explicitly in settings. Enabled for internal
     * testing only.
     */
    private boolean getGeoDetectionRunInBackgroundEnabled() {
        final boolean defaultEnabled = false;
        return mServerFlags.getBoolean(
                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED,
                defaultEnabled);
    }

    /**
     * Returns {@code true} if extra metrics / telemetry information can be collected. Used for
     * internal testers.
+4 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;

import static com.android.server.timedetector.ServerFlags.KEY_ENHANCED_METRICS_COLLECTION_ENABLED;
import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED;
import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED;
import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT;
import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE;
import static com.android.server.timedetector.ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED;
@@ -237,6 +238,9 @@ class TimeZoneDetectorShellCommand extends ShellCommand {
        pw.printf("    Only observed if the geolocation time zone detection feature is enabled in"
                + " config.\n");
        pw.printf("    Set this to false to disable the feature.\n");
        pw.printf("  %s\n", KEY_LOCATION_TIME_ZONE_DETECTION_RUN_IN_BACKGROUND_ENABLED);
        pw.printf("    Runs geolocation time zone detection even when it not enabled by the user."
                + " The result is not used to set the device's time zone [*]\n");
        pw.printf("  %s\n", KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT);
        pw.printf("    Only used if the device does not have an explicit 'geolocation time zone"
                + " detection enabled' setting stored [*].\n");
Loading