From bae4665077c58c4e65dc7bcc44f9183ae20777c0 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Thu, 25 Nov 2021 10:30:29 +0000 Subject: [PATCH] Add "enhanced metrics collection" support Add "enhanced metrics collection" support to the time zone detector service. This commit doesn't make any actual changes to the metrics code, that will be done separately. This just adds the infrastructure to support the server flag to turn the behavior on. Details: "Enhanced metric collection" is for deployment to QA and other internal users only. This initially means the actual time zone IDs will optionally be recorded in the metrics collected by the device in addition to the original "time zone ID ordinal" approach used for general / public users. Manual testing: adb shell cmd time_zone_detector dump_metrics adb shell cmd device_config put system_time enhanced_metrics_collection_enabled true adb shell cmd time_zone_detector dump_metrics Bug: 200279201 Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/ Change-Id: Ibb480b748fb951f9781b3d6ccc9a14b682ff4a1a --- .../timezonedetector/TimeZoneDetector.java | 8 + .../android/app/time_zone_detector.proto | 33 ++-- .../server/timedetector/ServerFlags.java | 9 +- .../ConfigurationInternal.java | 26 ++- .../MetricsTimeZoneDetectorState.java | 114 +++++++++--- .../ServiceConfigAccessorImpl.java | 13 ++ .../TimeZoneDetectorService.java | 7 + .../TimeZoneDetectorShellCommand.java | 26 ++- .../ConfigurationInternalTest.java | 4 + .../MetricsTimeZoneDetectorStateTest.java | 170 ++++++++++++++++++ .../TimeZoneDetectorServiceTest.java | 1 + .../TimeZoneDetectorStrategyImplTest.java | 32 +++- .../location/TestSupport.java | 1 + 13 files changed, 389 insertions(+), 55 deletions(-) create mode 100644 services/tests/servicestests/src/com/android/server/timezonedetector/MetricsTimeZoneDetectorStateTest.java diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java index ceab02f510629..aac23d88fa7bc 100644 --- a/core/java/android/app/timezonedetector/TimeZoneDetector.java +++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java @@ -102,6 +102,14 @@ public interface TimeZoneDetector { */ String SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK = "enable_telephony_fallback"; + /** + * A shell command that dumps a {@link + * com.android.server.timezonedetector.MetricsTimeZoneDetectorState} object to stdout for + * debugging. + * @hide + */ + String SHELL_COMMAND_DUMP_METRICS = "dump_metrics"; + /** * A shared utility method to create a {@link ManualTimeZoneSuggestion}. * diff --git a/core/proto/android/app/time_zone_detector.proto b/core/proto/android/app/time_zone_detector.proto index b33ca1d4f476b..b52aa828bef98 100644 --- a/core/proto/android/app/time_zone_detector.proto +++ b/core/proto/android/app/time_zone_detector.proto @@ -32,16 +32,8 @@ message GeolocationTimeZoneSuggestionProto { } /* - * An obfuscated and simplified time zone suggestion for metrics use. - * - * The suggestion's time zone IDs (which relate to location) are obfuscated by - * mapping them to an ordinal. When the ordinal is assigned consistently across - * several objects (i.e. so the same time zone ID is always mapped to the same - * ordinal), this allows comparisons between those objects. For example, we can - * answer "did these two suggestions agree?", "does the suggestion match the - * device's current time zone?", without leaking knowledge of location. Ordinals - * are also significantly more compact than full IANA TZDB IDs, albeit highly - * unstable and of limited use. + * A generic-form time zone suggestion for metrics use. Required to be a superset of the + * MetricsTimeZoneSuggestion proto defined in atoms.proto to ensure binary compatibility. */ message MetricsTimeZoneSuggestion { option (android.msg_privacy).dest = DEST_AUTOMATIC; @@ -55,5 +47,24 @@ message MetricsTimeZoneSuggestion { // The ordinals for time zone(s) in the suggestion. Always empty for // UNCERTAIN, and can be empty for CERTAIN, for example when the device is in // a disputed area / on an ocean. - repeated uint32 time_zone_ordinals = 2; + // + // The suggestion's time zone IDs (which relate to location) are obfuscated by + // mapping them to an ordinal. When the ordinal is assigned consistently across + // several objects (i.e. so the same time zone ID is always mapped to the same + // ordinal), this allows comparisons between those objects. For example, we can + // answer "did these two suggestions agree?", "does the suggestion match the + // device's current time zone?", without leaking knowledge of location. Ordinals + // are also significantly more compact than full IANA TZDB IDs, albeit unstable + // and of limited use. + repeated int32 time_zone_ordinals = 2; + + // The actual time zone ID(s) in the suggestion. Similar to time_zone_ordinals + // but contains the actual string IDs. + // + // This information is only captured / reported for some devices based on the + // value of a server side flag, i.e. it could be enabled for internal testers. + // Therefore the list can be empty even when time_zone_ordinals is populated. + // + // When enabled, see time_zone_ordinals for the expected number of values. + repeated string time_zone_ids = 3; } diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java index d24a3df56420d..cf0e350d7f8ea 100644 --- a/services/core/java/com/android/server/timedetector/ServerFlags.java +++ b/services/core/java/com/android/server/timedetector/ServerFlags.java @@ -66,6 +66,7 @@ public final class ServerFlags { KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE, KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE, KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED, + KEY_ENHANCED_METRICS_COLLECTION_ENABLED, }) @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER }) @Retention(RetentionPolicy.SOURCE) @@ -156,12 +157,18 @@ public final class ServerFlags { "time_detector_origin_priorities_override"; /** - * The key to override the time detector lower bound configuration. The values is the number of + * The key to override the time detector lower bound configuration. The value is the number of * milliseconds since the beginning of the Unix epoch. */ public static final @DeviceConfigKey String KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE = "time_detector_lower_bound_millis_override"; + /** + * The key to allow extra metrics / telemetry information to be collected from internal testers. + */ + public static final @DeviceConfigKey String KEY_ENHANCED_METRICS_COLLECTION_ENABLED = + "enhanced_metrics_collection_enabled"; + @GuardedBy("mListeners") private final ArrayMap> mListeners = new ArrayMap<>(); diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java index 65f077ea60e0a..2291777651dd8 100644 --- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java +++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java @@ -40,6 +40,7 @@ public final class ConfigurationInternal { private final boolean mTelephonyDetectionSupported; private final boolean mGeoDetectionSupported; private final boolean mTelephonyFallbackSupported; + private final boolean mEnhancedMetricsCollectionEnabled; private final boolean mAutoDetectionEnabledSetting; private final @UserIdInt int mUserId; private final boolean mUserConfigAllowed; @@ -50,6 +51,7 @@ public final class ConfigurationInternal { mTelephonyDetectionSupported = builder.mTelephonyDetectionSupported; mGeoDetectionSupported = builder.mGeoDetectionSupported; mTelephonyFallbackSupported = builder.mTelephonyFallbackSupported; + mEnhancedMetricsCollectionEnabled = builder.mEnhancedMetricsCollectionEnabled; mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting; mUserId = builder.mUserId; @@ -81,6 +83,15 @@ public final class ConfigurationInternal { return mTelephonyFallbackSupported; } + /** + * 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 + * would not be collected from the set of public users. + */ + public boolean isEnhancedMetricsCollectionEnabled() { + return mEnhancedMetricsCollectionEnabled; + } + /** Returns the value of the auto time zone detection enabled setting. */ public boolean getAutoDetectionEnabledSetting() { return mAutoDetectionEnabledSetting; @@ -227,6 +238,7 @@ public final class ConfigurationInternal { && mTelephonyDetectionSupported == that.mTelephonyDetectionSupported && mGeoDetectionSupported == that.mGeoDetectionSupported && mTelephonyFallbackSupported == that.mTelephonyFallbackSupported + && mEnhancedMetricsCollectionEnabled == that.mEnhancedMetricsCollectionEnabled && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting && mLocationEnabledSetting == that.mLocationEnabledSetting && mGeoDetectionEnabledSetting == that.mGeoDetectionEnabledSetting; @@ -235,7 +247,8 @@ public final class ConfigurationInternal { @Override public int hashCode() { return Objects.hash(mUserId, mUserConfigAllowed, mTelephonyDetectionSupported, - mGeoDetectionSupported, mTelephonyFallbackSupported, mAutoDetectionEnabledSetting, + mGeoDetectionSupported, mTelephonyFallbackSupported, + mEnhancedMetricsCollectionEnabled, mAutoDetectionEnabledSetting, mLocationEnabledSetting, mGeoDetectionEnabledSetting); } @@ -247,6 +260,7 @@ public final class ConfigurationInternal { + ", mTelephonyDetectionSupported=" + mTelephonyDetectionSupported + ", mGeoDetectionSupported=" + mGeoDetectionSupported + ", mTelephonyFallbackSupported=" + mTelephonyFallbackSupported + + ", mEnhancedMetricsCollectionEnabled=" + mEnhancedMetricsCollectionEnabled + ", mAutoDetectionEnabledSetting=" + mAutoDetectionEnabledSetting + ", mLocationEnabledSetting=" + mLocationEnabledSetting + ", mGeoDetectionEnabledSetting=" + mGeoDetectionEnabledSetting @@ -264,6 +278,7 @@ public final class ConfigurationInternal { private boolean mTelephonyDetectionSupported; private boolean mGeoDetectionSupported; private boolean mTelephonyFallbackSupported; + private boolean mEnhancedMetricsCollectionEnabled; private boolean mAutoDetectionEnabledSetting; private boolean mLocationEnabledSetting; private boolean mGeoDetectionEnabledSetting; @@ -284,6 +299,7 @@ public final class ConfigurationInternal { this.mTelephonyDetectionSupported = toCopy.mTelephonyDetectionSupported; this.mTelephonyFallbackSupported = toCopy.mTelephonyFallbackSupported; this.mGeoDetectionSupported = toCopy.mGeoDetectionSupported; + this.mEnhancedMetricsCollectionEnabled = toCopy.mEnhancedMetricsCollectionEnabled; this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting; this.mLocationEnabledSetting = toCopy.mLocationEnabledSetting; this.mGeoDetectionEnabledSetting = toCopy.mGeoDetectionEnabledSetting; @@ -322,6 +338,14 @@ public final class ConfigurationInternal { return this; } + /** + * Sets the value for enhanced metrics collection. + */ + public Builder setEnhancedMetricsCollectionEnabled(boolean enabled) { + mEnhancedMetricsCollectionEnabled = enabled; + return this; + } + /** * Sets the value of the automatic time zone detection enabled setting for this device. */ diff --git a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java index f156f8c8e59de..ecac267ff4e91 100644 --- a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java +++ b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java @@ -34,11 +34,13 @@ import java.util.Objects; * A class that provides time zone detector state information for metrics. * *

- * Regarding time zone ID ordinals: + * Regarding the use of time zone ID ordinals in metrics / telemetry: *

- * We don't want to leak user location information by reporting time zone IDs. Instead, time zone - * IDs are consistently identified within a given instance of this class by a numeric ID. This - * allows comparison of IDs without revealing what those IDs are. + * For general metrics, we don't want to leak user location information by reporting time zone + * IDs. Instead, time zone IDs are consistently identified within a given instance of this class by + * a numeric ID (ordinal). This allows comparison of IDs without revealing what those IDs are. + * See {@link #isEnhancedMetricsCollectionEnabled()} for the setting that enables actual IDs to be + * collected. */ public final class MetricsTimeZoneDetectorState { @@ -54,6 +56,7 @@ public final class MetricsTimeZoneDetectorState { @NonNull private final ConfigurationInternal mConfigurationInternal; private final int mDeviceTimeZoneIdOrdinal; + @Nullable private final String mDeviceTimeZoneId; @Nullable private final MetricsTimeZoneSuggestion mLatestManualSuggestion; @Nullable private final MetricsTimeZoneSuggestion mLatestTelephonySuggestion; @Nullable private final MetricsTimeZoneSuggestion mLatestGeolocationSuggestion; @@ -61,11 +64,13 @@ public final class MetricsTimeZoneDetectorState { private MetricsTimeZoneDetectorState( @NonNull ConfigurationInternal configurationInternal, int deviceTimeZoneIdOrdinal, + @Nullable String deviceTimeZoneId, @Nullable MetricsTimeZoneSuggestion latestManualSuggestion, @Nullable MetricsTimeZoneSuggestion latestTelephonySuggestion, @Nullable MetricsTimeZoneSuggestion latestGeolocationSuggestion) { mConfigurationInternal = Objects.requireNonNull(configurationInternal); mDeviceTimeZoneIdOrdinal = deviceTimeZoneIdOrdinal; + mDeviceTimeZoneId = deviceTimeZoneId; mLatestManualSuggestion = latestManualSuggestion; mLatestTelephonySuggestion = latestTelephonySuggestion; mLatestGeolocationSuggestion = latestGeolocationSuggestion; @@ -83,18 +88,24 @@ public final class MetricsTimeZoneDetectorState { @Nullable TelephonyTimeZoneSuggestion latestTelephonySuggestion, @Nullable GeolocationTimeZoneSuggestion latestGeolocationSuggestion) { + boolean includeZoneIds = configurationInternal.isEnhancedMetricsCollectionEnabled(); + String metricDeviceTimeZoneId = includeZoneIds ? deviceTimeZoneId : null; int deviceTimeZoneIdOrdinal = tzIdOrdinalGenerator.ordinal(Objects.requireNonNull(deviceTimeZoneId)); MetricsTimeZoneSuggestion latestCanonicalManualSuggestion = - createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestManualSuggestion); + createMetricsTimeZoneSuggestion( + tzIdOrdinalGenerator, latestManualSuggestion, includeZoneIds); MetricsTimeZoneSuggestion latestCanonicalTelephonySuggestion = - createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestTelephonySuggestion); + createMetricsTimeZoneSuggestion( + tzIdOrdinalGenerator, latestTelephonySuggestion, includeZoneIds); MetricsTimeZoneSuggestion latestCanonicalGeolocationSuggestion = - createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestGeolocationSuggestion); + createMetricsTimeZoneSuggestion( + tzIdOrdinalGenerator, latestGeolocationSuggestion, includeZoneIds); return new MetricsTimeZoneDetectorState( - configurationInternal, deviceTimeZoneIdOrdinal, latestCanonicalManualSuggestion, - latestCanonicalTelephonySuggestion, latestCanonicalGeolocationSuggestion); + configurationInternal, deviceTimeZoneIdOrdinal, metricDeviceTimeZoneId, + latestCanonicalManualSuggestion, latestCanonicalTelephonySuggestion, + latestCanonicalGeolocationSuggestion); } /** Returns true if the device supports telephony time zone detection. */ @@ -112,6 +123,11 @@ public final class MetricsTimeZoneDetectorState { return mConfigurationInternal.isTelephonyFallbackSupported(); } + /** Returns true if enhanced metric collection is enabled. */ + public boolean isEnhancedMetricsCollectionEnabled() { + return mConfigurationInternal.isEnhancedMetricsCollectionEnabled(); + } + /** Returns true if user's location can be used generally. */ public boolean getUserLocationEnabledSetting() { return mConfigurationInternal.getLocationEnabledSetting(); @@ -142,13 +158,23 @@ public final class MetricsTimeZoneDetectorState { } /** - * Returns the ordinal for the device's currently set time zone ID. + * Returns the ordinal for the device's current time zone ID. * See {@link MetricsTimeZoneDetectorState} for information about ordinals. */ public int getDeviceTimeZoneIdOrdinal() { return mDeviceTimeZoneIdOrdinal; } + /** + * Returns the device's current time zone ID. This will only be populated if {@link + * #isEnhancedMetricsCollectionEnabled()} is {@code true}. See {@link + * MetricsTimeZoneDetectorState} for details. + */ + @Nullable + public String getDeviceTimeZoneId() { + return mDeviceTimeZoneId; + } + /** * Returns a canonical form of the last manual suggestion received. */ @@ -183,6 +209,7 @@ public final class MetricsTimeZoneDetectorState { } MetricsTimeZoneDetectorState that = (MetricsTimeZoneDetectorState) o; return mDeviceTimeZoneIdOrdinal == that.mDeviceTimeZoneIdOrdinal + && Objects.equals(mDeviceTimeZoneId, that.mDeviceTimeZoneId) && mConfigurationInternal.equals(that.mConfigurationInternal) && Objects.equals(mLatestManualSuggestion, that.mLatestManualSuggestion) && Objects.equals(mLatestTelephonySuggestion, that.mLatestTelephonySuggestion) @@ -191,7 +218,7 @@ public final class MetricsTimeZoneDetectorState { @Override public int hashCode() { - return Objects.hash(mConfigurationInternal, mDeviceTimeZoneIdOrdinal, + return Objects.hash(mConfigurationInternal, mDeviceTimeZoneIdOrdinal, mDeviceTimeZoneId, mLatestManualSuggestion, mLatestTelephonySuggestion, mLatestGeolocationSuggestion); } @@ -200,6 +227,7 @@ public final class MetricsTimeZoneDetectorState { return "MetricsTimeZoneDetectorState{" + "mConfigurationInternal=" + mConfigurationInternal + ", mDeviceTimeZoneIdOrdinal=" + mDeviceTimeZoneIdOrdinal + + ", mDeviceTimeZoneId=" + mDeviceTimeZoneId + ", mLatestManualSuggestion=" + mLatestManualSuggestion + ", mLatestTelephonySuggestion=" + mLatestTelephonySuggestion + ", mLatestGeolocationSuggestion=" + mLatestGeolocationSuggestion @@ -209,34 +237,40 @@ public final class MetricsTimeZoneDetectorState { @Nullable private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion( @NonNull OrdinalGenerator zoneIdOrdinalGenerator, - @NonNull ManualTimeZoneSuggestion manualSuggestion) { + @NonNull ManualTimeZoneSuggestion manualSuggestion, + boolean includeFullZoneIds) { if (manualSuggestion == null) { return null; } - int zoneIdOrdinal = zoneIdOrdinalGenerator.ordinal(manualSuggestion.getZoneId()); - return MetricsTimeZoneSuggestion.createCertain( - new int[] { zoneIdOrdinal }); + String suggestionZoneId = manualSuggestion.getZoneId(); + String[] metricZoneIds = includeFullZoneIds ? new String[] { suggestionZoneId } : null; + int[] zoneIdOrdinals = new int[] { zoneIdOrdinalGenerator.ordinal(suggestionZoneId) }; + return MetricsTimeZoneSuggestion.createCertain(metricZoneIds, zoneIdOrdinals); } @Nullable private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion( @NonNull OrdinalGenerator zoneIdOrdinalGenerator, - @NonNull TelephonyTimeZoneSuggestion telephonySuggestion) { + @NonNull TelephonyTimeZoneSuggestion telephonySuggestion, + boolean includeFullZoneIds) { if (telephonySuggestion == null) { return null; } - if (telephonySuggestion.getZoneId() == null) { + String suggestionZoneId = telephonySuggestion.getZoneId(); + if (suggestionZoneId == null) { return MetricsTimeZoneSuggestion.createUncertain(); } - int zoneIdOrdinal = zoneIdOrdinalGenerator.ordinal(telephonySuggestion.getZoneId()); - return MetricsTimeZoneSuggestion.createCertain(new int[] { zoneIdOrdinal }); + String[] metricZoneIds = includeFullZoneIds ? new String[] { suggestionZoneId } : null; + int[] zoneIdOrdinals = new int[] { zoneIdOrdinalGenerator.ordinal(suggestionZoneId) }; + return MetricsTimeZoneSuggestion.createCertain(metricZoneIds, zoneIdOrdinals); } @Nullable private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion( @NonNull OrdinalGenerator zoneIdOrdinalGenerator, - @Nullable GeolocationTimeZoneSuggestion geolocationSuggestion) { + @Nullable GeolocationTimeZoneSuggestion geolocationSuggestion, + boolean includeFullZoneIds) { if (geolocationSuggestion == null) { return null; } @@ -245,7 +279,9 @@ public final class MetricsTimeZoneDetectorState { if (zoneIds == null) { return MetricsTimeZoneSuggestion.createUncertain(); } - return MetricsTimeZoneSuggestion.createCertain(zoneIdOrdinalGenerator.ordinals(zoneIds)); + String[] metricZoneIds = includeFullZoneIds ? zoneIds.toArray(new String[0]) : null; + int[] zoneIdOrdinals = zoneIdOrdinalGenerator.ordinals(zoneIds); + return MetricsTimeZoneSuggestion.createCertain(metricZoneIds, zoneIdOrdinals); } /** @@ -254,33 +290,49 @@ public final class MetricsTimeZoneDetectorState { * MetricsTimeZoneSuggestion proto definition. */ public static final class MetricsTimeZoneSuggestion { - @Nullable - private final int[] mZoneIdOrdinals; + @Nullable private final String[] mZoneIds; + @Nullable private final int[] mZoneIdOrdinals; - MetricsTimeZoneSuggestion(@Nullable int[] zoneIdOrdinals) { + private MetricsTimeZoneSuggestion( + @Nullable String[] zoneIds, @Nullable int[] zoneIdOrdinals) { + mZoneIds = zoneIds; mZoneIdOrdinals = zoneIdOrdinals; } @NonNull static MetricsTimeZoneSuggestion createUncertain() { - return new MetricsTimeZoneSuggestion(null); + return new MetricsTimeZoneSuggestion(null, null); } @NonNull static MetricsTimeZoneSuggestion createCertain( - @NonNull int[] zoneIdOrdinals) { - return new MetricsTimeZoneSuggestion(zoneIdOrdinals); + @Nullable String[] zoneIds, @NonNull int[] zoneIdOrdinals) { + return new MetricsTimeZoneSuggestion(zoneIds, zoneIdOrdinals); } public boolean isCertain() { return mZoneIdOrdinals != null; } + /** + * Returns ordinals for the time zone IDs contained in the suggestion. + * See {@link MetricsTimeZoneDetectorState} for information about ordinals. + */ @Nullable public int[] getZoneIdOrdinals() { return mZoneIdOrdinals; } + /** + * Returns the time zone IDs contained in the suggestion. This will only be populated if + * {@link #isEnhancedMetricsCollectionEnabled()} is {@code true}. See {@link + * MetricsTimeZoneDetectorState} for details. + */ + @Nullable + public String[] getZoneIds() { + return mZoneIds; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -290,18 +342,22 @@ public final class MetricsTimeZoneDetectorState { return false; } MetricsTimeZoneSuggestion that = (MetricsTimeZoneSuggestion) o; - return Arrays.equals(mZoneIdOrdinals, that.mZoneIdOrdinals); + return Arrays.equals(mZoneIdOrdinals, that.mZoneIdOrdinals) + && Arrays.equals(mZoneIds, that.mZoneIds); } @Override public int hashCode() { - return Arrays.hashCode(mZoneIdOrdinals); + int result = Arrays.hashCode(mZoneIds); + result = 31 * result + Arrays.hashCode(mZoneIdOrdinals); + return result; } @Override public String toString() { return "MetricsTimeZoneSuggestion{" + "mZoneIdOrdinals=" + Arrays.toString(mZoneIdOrdinals) + + ", mZoneIds=" + Arrays.toString(mZoneIds) + '}'; } } diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java index 02ea43341beff..4612f659d51a9 100644 --- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java +++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java @@ -62,6 +62,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { private static final Set CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(new ArraySet<>(new String[] { ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED, + ServerFlags.KEY_ENHANCED_METRICS_COLLECTION_ENABLED, ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE, ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED, @@ -296,6 +297,7 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { isTelephonyTimeZoneDetectionFeatureSupported()) .setGeoDetectionFeatureSupported(isGeoTimeZoneDetectionFeatureSupported()) .setTelephonyFallbackSupported(isTelephonyFallbackSupported()) + .setEnhancedMetricsCollectionEnabled(isEnhancedMetricsCollectionEnabled()) .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting()) .setUserConfigAllowed(isUserConfigAllowed(userId)) .setLocationEnabledSetting(getLocationEnabledSetting(userId)) @@ -400,6 +402,17 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor { defaultEnabled); } + /** + * Returns {@code true} if extra metrics / telemetry information can be collected. Used for + * internal testers. + */ + private boolean isEnhancedMetricsCollectionEnabled() { + final boolean defaultEnabled = false; + return mServerFlags.getBoolean( + ServerFlags.KEY_ENHANCED_METRICS_COLLECTION_ENABLED, + defaultEnabled); + } + @Override @NonNull public synchronized String getPrimaryLocationTimeZoneProviderPackageName() { diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java index 14784cf0d5501..f75608e145395 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java @@ -364,6 +364,13 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub } } + @NonNull + MetricsTimeZoneDetectorState generateMetricsState() { + enforceManageTimeZoneDetectorPermission(); + + return mTimeZoneDetectorStrategy.generateMetricsState(); + } + @Override protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @Nullable String[] args) { diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java index 2b912ad7ba601..8535b3d485c4d 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java @@ -15,6 +15,7 @@ */ package com.android.server.timezonedetector; +import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_DUMP_METRICS; import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK; import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED; import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_ENABLED; @@ -28,6 +29,7 @@ import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SUGGES import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE; 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_SETTING_ENABLED_DEFAULT; import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE; @@ -80,6 +82,8 @@ class TimeZoneDetectorShellCommand extends ShellCommand { return runSuggestTelephonyTimeZone(); case SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK: return runEnableTelephonyFallback(); + case SHELL_COMMAND_DUMP_METRICS: + return runDumpMetrics(); default: { return handleDefaultCommands(cmd); } @@ -168,14 +172,22 @@ class TimeZoneDetectorShellCommand extends ShellCommand { pw.println("Suggestion " + suggestion + " injected."); return 0; } catch (RuntimeException e) { - pw.println(e.toString()); + pw.println(e); return 1; } } private int runEnableTelephonyFallback() { mInterface.enableTelephonyFallback(); - return 1; + return 0; + } + + private int runDumpMetrics() { + final PrintWriter pw = getOutPrintWriter(); + MetricsTimeZoneDetectorState metricsState = mInterface.generateMetricsState(); + pw.println("MetricsTimeZoneDetectorState:"); + pw.println(metricsState.toString()); + return 0; } @Override @@ -208,10 +220,10 @@ class TimeZoneDetectorShellCommand extends ShellCommand { pw.println(); pw.printf(" %s \n", SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE); - pw.printf(" %s \n", - SHELL_COMMAND_SUGGEST_MANUAL_TIME_ZONE); - pw.printf(" %s \n", - SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE); + pw.printf(" %s \n", SHELL_COMMAND_SUGGEST_MANUAL_TIME_ZONE); + pw.printf(" %s \n", SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE); + pw.printf(" %s\n", SHELL_COMMAND_DUMP_METRICS); + pw.printf(" Dumps the service metrics to stdout for inspection.\n"); pw.println(); GeolocationTimeZoneSuggestion.printCommandLineOpts(pw); pw.println(); @@ -235,6 +247,8 @@ class TimeZoneDetectorShellCommand extends ShellCommand { pw.printf(" %s\n", KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED); pw.printf(" Used to enable / disable support for telephony detection fallback. Also see" + " the %s command.\n", SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK); + pw.printf(" %s\n", KEY_ENHANCED_METRICS_COLLECTION_ENABLED); + pw.printf(" Used to increase the detail of metrics collected / reported.\n"); pw.println(); pw.printf("[*] To be enabled, the user must still have location = on / auto time zone" + " detection = on.\n"); diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java index 6ee6020c79852..a963785c25e72 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java @@ -49,6 +49,7 @@ public class ConfigurationInternalTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(true) @@ -112,6 +113,7 @@ public class ConfigurationInternalTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(true) @@ -177,6 +179,7 @@ public class ConfigurationInternalTest { .setTelephonyDetectionFeatureSupported(false) .setGeoDetectionFeatureSupported(false) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(true) @@ -240,6 +243,7 @@ public class ConfigurationInternalTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(false) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(true) diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/MetricsTimeZoneDetectorStateTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/MetricsTimeZoneDetectorStateTest.java new file mode 100644 index 0000000000000..9029ac57d31e0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/MetricsTimeZoneDetectorStateTest.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.timezonedetector; + +import static com.android.server.timezonedetector.MetricsTimeZoneDetectorState.DETECTION_MODE_GEO; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import android.annotation.ElapsedRealtimeLong; +import android.annotation.UserIdInt; +import android.app.timezonedetector.ManualTimeZoneSuggestion; +import android.app.timezonedetector.TelephonyTimeZoneSuggestion; + +import com.android.server.timezonedetector.MetricsTimeZoneDetectorState.MetricsTimeZoneSuggestion; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.function.Function; + +/** Tests for {@link MetricsTimeZoneDetectorState}. */ +public class MetricsTimeZoneDetectorStateTest { + + private static final @UserIdInt int ARBITRARY_USER_ID = 1; + private static final @ElapsedRealtimeLong long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L; + private static final String DEVICE_TIME_ZONE_ID = "DeviceTimeZoneId"; + + private static final ManualTimeZoneSuggestion MANUAL_TIME_ZONE_SUGGESTION = + new ManualTimeZoneSuggestion("ManualTimeZoneId"); + + private static final TelephonyTimeZoneSuggestion TELEPHONY_TIME_ZONE_SUGGESTION = + new TelephonyTimeZoneSuggestion.Builder(0) + .setZoneId("TelephonyZoneId") + .setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY) + .setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE) + .build(); + + private static final GeolocationTimeZoneSuggestion GEOLOCATION_TIME_ZONE_SUGGESTION = + GeolocationTimeZoneSuggestion.createCertainSuggestion( + ARBITRARY_ELAPSED_REALTIME_MILLIS, + Arrays.asList("GeoTimeZoneId1", "GeoTimeZoneId2")); + + private final OrdinalGenerator mOrdinalGenerator = + new OrdinalGenerator<>(Function.identity()); + + @Test + public void enhancedMetricsCollectionEnabled() { + final boolean enhancedMetricsCollectionEnabled = true; + ConfigurationInternal configurationInternal = + createConfigurationInternal(enhancedMetricsCollectionEnabled); + + // Create the object. + MetricsTimeZoneDetectorState metricsTimeZoneDetectorState = + MetricsTimeZoneDetectorState.create(mOrdinalGenerator, configurationInternal, + DEVICE_TIME_ZONE_ID, MANUAL_TIME_ZONE_SUGGESTION, + TELEPHONY_TIME_ZONE_SUGGESTION, GEOLOCATION_TIME_ZONE_SUGGESTION); + + // Assert the content. + assertCommonConfiguration(configurationInternal, metricsTimeZoneDetectorState); + + assertEquals(DEVICE_TIME_ZONE_ID, metricsTimeZoneDetectorState.getDeviceTimeZoneId()); + MetricsTimeZoneSuggestion expectedManualSuggestion = + MetricsTimeZoneSuggestion.createCertain( + new String[] { MANUAL_TIME_ZONE_SUGGESTION.getZoneId() }, + new int[] { 1 }); + assertEquals(expectedManualSuggestion, + metricsTimeZoneDetectorState.getLatestManualSuggestion()); + + MetricsTimeZoneSuggestion expectedTelephonySuggestion = + MetricsTimeZoneSuggestion.createCertain( + new String[] { TELEPHONY_TIME_ZONE_SUGGESTION.getZoneId() }, + new int[] { 2 }); + assertEquals(expectedTelephonySuggestion, + metricsTimeZoneDetectorState.getLatestTelephonySuggestion()); + + MetricsTimeZoneSuggestion expectedGeoSuggestion = + MetricsTimeZoneSuggestion.createCertain( + GEOLOCATION_TIME_ZONE_SUGGESTION.getZoneIds().toArray(new String[0]), + new int[] { 3, 4 }); + assertEquals(expectedGeoSuggestion, + metricsTimeZoneDetectorState.getLatestGeolocationSuggestion()); + } + + @Test + public void enhancedMetricsCollectionDisabled() { + final boolean enhancedMetricsCollectionEnabled = false; + ConfigurationInternal configurationInternal = + createConfigurationInternal(enhancedMetricsCollectionEnabled); + + // Create the object. + MetricsTimeZoneDetectorState metricsTimeZoneDetectorState = + MetricsTimeZoneDetectorState.create(mOrdinalGenerator, configurationInternal, + DEVICE_TIME_ZONE_ID, MANUAL_TIME_ZONE_SUGGESTION, + TELEPHONY_TIME_ZONE_SUGGESTION, GEOLOCATION_TIME_ZONE_SUGGESTION); + + // Assert the content. + assertCommonConfiguration(configurationInternal, metricsTimeZoneDetectorState); + + // When enhancedMetricsCollectionEnabled == false, no time zone IDs should be included. + assertNull(metricsTimeZoneDetectorState.getDeviceTimeZoneId()); + final String[] omittedZoneIds = null; + + MetricsTimeZoneSuggestion expectedManualSuggestion = + MetricsTimeZoneSuggestion.createCertain( + omittedZoneIds, + new int[] { 1 }); + assertEquals(expectedManualSuggestion, + metricsTimeZoneDetectorState.getLatestManualSuggestion()); + + MetricsTimeZoneSuggestion expectedTelephonySuggestion = + MetricsTimeZoneSuggestion.createCertain( + omittedZoneIds, + new int[] { 2 }); + assertEquals(expectedTelephonySuggestion, + metricsTimeZoneDetectorState.getLatestTelephonySuggestion()); + + MetricsTimeZoneSuggestion expectedGeoSuggestion = + MetricsTimeZoneSuggestion.createCertain( + omittedZoneIds, + new int[] { 3, 4 }); + assertEquals(expectedGeoSuggestion, + metricsTimeZoneDetectorState.getLatestGeolocationSuggestion()); + } + + private static void assertCommonConfiguration(ConfigurationInternal configurationInternal, + MetricsTimeZoneDetectorState metricsTimeZoneDetectorState) { + assertEquals(configurationInternal.isTelephonyDetectionSupported(), + metricsTimeZoneDetectorState.isTelephonyDetectionSupported()); + assertEquals(configurationInternal.isGeoDetectionSupported(), + metricsTimeZoneDetectorState.isGeoDetectionSupported()); + assertEquals(configurationInternal.getAutoDetectionEnabledSetting(), + metricsTimeZoneDetectorState.getAutoDetectionEnabledSetting()); + assertEquals(configurationInternal.getLocationEnabledSetting(), + metricsTimeZoneDetectorState.getUserLocationEnabledSetting()); + assertEquals(configurationInternal.getGeoDetectionEnabledSetting(), + metricsTimeZoneDetectorState.getGeoDetectionEnabledSetting()); + assertEquals(configurationInternal.isEnhancedMetricsCollectionEnabled(), + metricsTimeZoneDetectorState.isEnhancedMetricsCollectionEnabled()); + assertEquals(0, metricsTimeZoneDetectorState.getDeviceTimeZoneIdOrdinal()); + assertEquals(DETECTION_MODE_GEO, metricsTimeZoneDetectorState.getDetectionMode()); + } + + private static ConfigurationInternal createConfigurationInternal( + boolean enhancedMetricsCollectionEnabled) { + return new ConfigurationInternal.Builder(ARBITRARY_USER_ID) + .setUserConfigAllowed(true) + .setTelephonyDetectionFeatureSupported(true) + .setGeoDetectionFeatureSupported(true) + .setEnhancedMetricsCollectionEnabled(enhancedMetricsCollectionEnabled) + .setAutoDetectionEnabledSetting(true) + .setLocationEnabledSetting(true) + .setGeoDetectionEnabledSetting(true) + .build(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java index 193b2e3d07669..e0e5ba0560483 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java @@ -379,6 +379,7 @@ public class TimeZoneDetectorServiceTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setUserConfigAllowed(true) .setAutoDetectionEnabledSetting(autoDetectionEnabled) .setLocationEnabledSetting(geoDetectionEnabled) diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index ef1b4f58dd769..27f7814c5d237 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -87,10 +87,11 @@ public class TimeZoneDetectorStrategyImplTest { private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_DISABLED = new ConfigurationInternal.Builder(USER_ID) - .setUserConfigAllowed(false) .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) + .setUserConfigAllowed(false) .setAutoDetectionEnabledSetting(false) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(false) @@ -98,10 +99,11 @@ public class TimeZoneDetectorStrategyImplTest { private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_ENABLED = new ConfigurationInternal.Builder(USER_ID) - .setUserConfigAllowed(false) .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) + .setUserConfigAllowed(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(true) @@ -109,10 +111,11 @@ public class TimeZoneDetectorStrategyImplTest { private static final ConfigurationInternal CONFIG_AUTO_DETECT_NOT_SUPPORTED = new ConfigurationInternal.Builder(USER_ID) - .setUserConfigAllowed(true) .setTelephonyDetectionFeatureSupported(false) .setGeoDetectionFeatureSupported(false) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) + .setUserConfigAllowed(true) .setAutoDetectionEnabledSetting(false) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(false) @@ -120,10 +123,11 @@ public class TimeZoneDetectorStrategyImplTest { private static final ConfigurationInternal CONFIG_AUTO_DISABLED_GEO_DISABLED = new ConfigurationInternal.Builder(USER_ID) - .setUserConfigAllowed(true) .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) + .setUserConfigAllowed(true) .setAutoDetectionEnabledSetting(false) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(false) @@ -134,6 +138,7 @@ public class TimeZoneDetectorStrategyImplTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setUserConfigAllowed(true) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) @@ -145,6 +150,7 @@ public class TimeZoneDetectorStrategyImplTest { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setUserConfigAllowed(true) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) @@ -955,8 +961,20 @@ public class TimeZoneDetectorStrategyImplTest { } @Test - public void testGenerateMetricsState() { - ConfigurationInternal expectedInternalConfig = CONFIG_AUTO_DISABLED_GEO_DISABLED; + public void testGenerateMetricsState_enhancedMetricsCollection() { + testGenerateMetricsState(true); + } + + @Test + public void testGenerateMetricsState_notEnhancedMetricsCollection() { + testGenerateMetricsState(false); + } + + private void testGenerateMetricsState(boolean enhancedMetricsCollection) { + ConfigurationInternal expectedInternalConfig = + new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED_GEO_DISABLED) + .setEnhancedMetricsCollectionEnabled(enhancedMetricsCollection) + .build(); String expectedDeviceTimeZoneId = "InitialZoneId"; Script script = new Script() @@ -1028,7 +1046,7 @@ public class TimeZoneDetectorStrategyImplTest { tzIdOrdinalGenerator, expectedInternalConfig, expectedDeviceTimeZoneId, expectedManualSuggestion, expectedTelephonySuggestion, expectedGeolocationTimeZoneSuggestion); - // Rely on MetricsTimeZoneDetectorState.equals() for time zone ID ordinal comparisons. + // Rely on MetricsTimeZoneDetectorState.equals() for time zone ID / ID ordinal comparisons. assertEquals(expectedState, actualState); } diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java index a2df31305c2f7..9d013101827c2 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java @@ -47,6 +47,7 @@ final class TestSupport { .setTelephonyDetectionFeatureSupported(true) .setGeoDetectionFeatureSupported(true) .setTelephonyFallbackSupported(false) + .setEnhancedMetricsCollectionEnabled(false) .setAutoDetectionEnabledSetting(true) .setLocationEnabledSetting(true) .setGeoDetectionEnabledSetting(geoDetectionEnabledSetting)