Merge "A mixed bag of tidy ups / refactoring"

This commit is contained in:
Neil Fuller
2021-11-17 14:29:36 +00:00
committed by Android (Google) Code Review
14 changed files with 115 additions and 164 deletions

View File

@@ -24,18 +24,4 @@ public interface Dumpable {
/** Dump internal state. */
void dump(@NonNull IndentingPrintWriter pw, @Nullable String[] args);
/**
* An interface that can be used expose when one component allows another to be registered so
* that it is dumped at the same time.
*/
interface Container {
/**
* Registers the supplied {@link Dumpable}. When the implementation is dumped
* {@link Dumpable#dump(IndentingPrintWriter, String[])} should be called on the
* {@code dumpable}.
*/
void addDumpable(@NonNull Dumpable dumpable);
}
}

View File

@@ -72,8 +72,8 @@ final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment
mLocationManager = context.getSystemService(LocationManager.class);
mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
// Wire up the config change listeners. All invocations are performed on the mHandler
// thread.
// Wire up the config change listeners for anything that could affect the return values from
// this object. All listener invocations are performed on the mHandler thread.
// Listen for the user changing / the user's location mode changing.
IntentFilter filter = new IntentFilter();
@@ -88,25 +88,19 @@ final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment
// Add async callbacks for global settings being changed.
ContentResolver contentResolver = mContext.getContentResolver();
ContentObserver contentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
handleConfigChangeOnHandlerThread();
}
};
contentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
handleConfigChangeOnHandlerThread();
}
});
Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, contentObserver);
// Add async callbacks for user scoped location settings being changed.
contentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED),
true,
new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
handleConfigChangeOnHandlerThread();
}
}, UserHandle.USER_ALL);
true, contentObserver, UserHandle.USER_ALL);
}
private void handleConfigChangeOnHandlerThread() {

View File

@@ -39,12 +39,11 @@ import java.util.StringTokenizer;
* <ul>
* <li>{@code effectiveFromElapsedMillis}: The time according to the elapsed realtime clock
* after which the suggestion should be considered in effect. For example, when a location fix
* used to establish the time zone is old, then the suggestion
* {@code effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
* detected / correct at that time. The time_zone_detector is only expected to use the latest
* suggestion it has received, and so later suggestions always counteract previous suggestions.
* The inclusion of this information means that the time_zone_detector can take into account
* ordering when comparing suggestions from different sources.
* used to establish the time zone is old, then the suggestion's {@code
* effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
* detected / correct at that time. The inclusion of this information means that the
* time_zone_detector <em>may</em> take this into account if comparing suggestions or signals
* from different sources.
* <br />Note: Because the times can be back-dated, time_zone_detector can be sent a sequence of
* suggestions where the {@code effectiveFromElapsedMillis} of later suggestions is before
* the {@code effectiveFromElapsedMillis} of an earlier one.</li>

View File

@@ -21,7 +21,6 @@ import android.annotation.StringDef;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.SystemProperties;
import android.util.ArraySet;
import com.android.internal.R;
@@ -64,11 +63,11 @@ public final class ServiceConfigAccessor {
public static final @ProviderMode String PROVIDER_MODE_ENABLED = "enabled";
/**
* Device config keys that affect the {@link TimeZoneDetectorService} service and {@link
* com.android.server.timezonedetector.location.LocationTimeZoneManagerService}.
* Device config keys that can affect {@link
* com.android.server.timezonedetector.location.LocationTimeZoneManagerService} behavior.
*/
private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
new ArraySet<>(new String[] {
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_SETTING_ENABLED_DEFAULT,
ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
@@ -94,14 +93,6 @@ public final class ServiceConfigAccessor {
@NonNull private final Context mContext;
/**
* An ultimate "feature switch" for location-based time zone detection. If this is
* {@code false}, the device cannot support the feature without a config change or a reboot:
* This affects what services are started on boot to minimize expense when the feature is not
* wanted.
*/
private final boolean mGeoDetectionFeatureSupportedInConfig;
@NonNull private final ServerFlags mServerFlags;
/**
@@ -148,14 +139,6 @@ public final class ServiceConfigAccessor {
private ServiceConfigAccessor(@NonNull Context context) {
mContext = Objects.requireNonNull(context);
// The config value is expected to be the main feature flag. Platform developers can also
// force enable the feature using a persistent system property. Because system properties
// can change, this value is cached and only changes on reboot.
mGeoDetectionFeatureSupportedInConfig = context.getResources().getBoolean(
com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
|| SystemProperties.getBoolean(
"persist.sys.location_time_zone_detection_feature_supported", false);
mServerFlags = ServerFlags.getInstance(mContext);
}
@@ -170,14 +153,15 @@ public final class ServiceConfigAccessor {
}
/**
* Adds a listener that will be called when server flags related to this class change. The
* callbacks are delivered on the main looper thread.
* Adds a listener that will be called when server flags related to location_time_zone_manager
* change. The callbacks are delivered on the main looper thread.
*
* <p>Note: Only for use by long-lived objects. There is deliberately no associated remove
* method.
*/
public void addListener(@NonNull ConfigurationChangeListener listener) {
mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
public void addLocationTimeZoneManagerConfigListener(
@NonNull ConfigurationChangeListener listener) {
mServerFlags.addListener(listener, LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH);
}
/** Returns {@code true} if any form of automatic time zone detection is supported. */
@@ -197,11 +181,19 @@ public final class ServiceConfigAccessor {
/**
* Returns {@code true} if the location-based time zone detection feature can be supported on
* this device at all according to config. When {@code false}, implies that various other
* location-based settings will be turned off or rendered meaningless. Typically {@link
* #isGeoTimeZoneDetectionFeatureSupported()} should be used instead.
* location-based services and settings will be turned off or rendered meaningless.
*
* <p>This is the ultimate "feature switch" for location-based time zone detection. If this is
* {@code false}, the device cannot support the feature without a config change or a reboot:
* This affects what services are started on boot to minimize expense when the feature is not
* wanted.
*
* Typically {@link #isGeoTimeZoneDetectionFeatureSupported()} should be used except during
* boot.
*/
public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
return mGeoDetectionFeatureSupportedInConfig;
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection);
}
/**
@@ -213,7 +205,7 @@ public final class ServiceConfigAccessor {
// 1) Be turned on in config.
// 2) Not be turned off via a server flag.
// 3) There must be at least one location time zone provider enabled / configured.
return mGeoDetectionFeatureSupportedInConfig
return isGeoTimeZoneDetectionFeatureSupportedInConfig()
&& isGeoTimeZoneDetectionFeatureSupportedInternal()
&& atLeastOneProviderIsEnabled();
}

View File

@@ -25,7 +25,7 @@ import android.annotation.NonNull;
* <p>The methods on this class can be called from any thread.
* @hide
*/
public interface TimeZoneDetectorInternal extends Dumpable.Container {
public interface TimeZoneDetectorInternal {
/** Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed. */
void addConfigurationListener(@NonNull ConfigurationChangeListener listener);

View File

@@ -56,11 +56,6 @@ public final class TimeZoneDetectorInternalImpl implements TimeZoneDetectorInter
}
}
@Override
public void addDumpable(@NonNull Dumpable dumpable) {
mTimeZoneDetectorStrategy.addDumpable(dumpable);
}
@Override
public void addConfigurationListener(ConfigurationChangeListener listener) {
synchronized (mConfigurationListeners) {

View File

@@ -45,6 +45,8 @@ import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
@@ -59,6 +61,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
implements IBinder.DeathRecipient {
static final String TAG = "time_zone_detector";
static final boolean DBG = false;
/**
* Handles the service lifecycle for {@link TimeZoneDetectorService} and
@@ -112,17 +115,22 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
*/
@GuardedBy("mListeners")
@NonNull
private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners =
new ArrayMap<>();
private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners = new ArrayMap<>();
/**
* References to components that should be dumped when {@link
* #dump(FileDescriptor, PrintWriter, String[])} is called on the service.
*/
@GuardedBy("mDumpables")
private final List<Dumpable> mDumpables = new ArrayList<>();
private static TimeZoneDetectorService create(
@NonNull Context context, @NonNull Handler handler,
@NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
TimeZoneDetectorService service = new TimeZoneDetectorService(
return new TimeZoneDetectorService(
context, handler, callerIdentityInjector, timeZoneDetectorStrategy);
return service;
}
@VisibleForTesting
@@ -251,7 +259,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
if (!removedListener) {
Slog.w(TAG, "Notified of binder death for who=" + who
+ ", but did not remove any listeners."
+ " mConfigurationListeners=" + mListeners);
+ " mListeners=" + mListeners);
}
}
}
@@ -314,8 +322,17 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
boolean isGeoTimeZoneDetectionSupported() {
enforceManageTimeZoneDetectorPermission();
return ServiceConfigAccessor.getInstance(mContext)
.isGeoTimeZoneDetectionFeatureSupported();
return ServiceConfigAccessor.getInstance(mContext).isGeoTimeZoneDetectionFeatureSupported();
}
/**
* Registers the supplied {@link Dumpable} for dumping. When the service is dumped
* {@link Dumpable#dump(IndentingPrintWriter, String[])} will be called on the {@code dumpable}.
*/
void addDumpable(@NonNull Dumpable dumpable) {
synchronized (mDumpables) {
mDumpables.add(dumpable);
}
}
@Override
@@ -325,6 +342,13 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
mTimeZoneDetectorStrategy.dump(ipw, args);
synchronized (mDumpables) {
for (Dumpable dumpable : mDumpables) {
dumpable.dump(ipw, args);
}
}
ipw.flush();
}

View File

@@ -30,7 +30,7 @@ import android.util.IndentingPrintWriter;
* Suggestions are acted on or ignored as needed, depending on previously received suggestions and
* the current user's configuration (see {@link ConfigurationInternal}).
*
* <p>Devices can have zero, one or two automatic time zone detection algorithm available at any
* <p>Devices can have zero, one or two automatic time zone detection algorithms available at any
* point in time.
*
* <p>The two automatic detection algorithms supported are "telephony" and "geolocation". Algorithm
@@ -63,6 +63,13 @@ import android.util.IndentingPrintWriter;
* have an empty suggestion submitted in order to "withdraw" their previous suggestion otherwise it
* will remain in use.
*
* <p>The strategy uses only one algorithm at a time and does not attempt consensus even when
* more than one is available on a device. This "use only one" behavior is deliberate as different
* algorithms have edge cases and blind spots that lead to incorrect answers or uncertainty;
* different algorithms aren't guaranteed to agree, and algorithms may frequently lose certainty as
* users enter areas without the necessary signals. Ultimately, with no perfect algorithm available,
* the user is left to choose which algorithm works best for their circumstances.
*
* <p>Threading:
*
* <p>Suggestion calls with a void return type may be handed off to a separate thread and handled
@@ -73,7 +80,7 @@ import android.util.IndentingPrintWriter;
*
* @hide
*/
public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
public interface TimeZoneDetectorStrategy extends Dumpable {
/**
* Adds a listener that will be triggered whenever {@link ConfigurationInternal} may have

View File

@@ -98,7 +98,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
}
private static final String LOG_TAG = TimeZoneDetectorService.TAG;
private static final boolean DBG = false;
private static final boolean DBG = TimeZoneDetectorService.DBG;
/**
* The abstract score for an empty or invalid telephony suggestion.
@@ -168,7 +168,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
@GuardedBy("this")
@NonNull
private List<ConfigurationChangeListener> mConfigChangeListeners = new ArrayList<>();
private final List<ConfigurationChangeListener> mConfigChangeListeners = new ArrayList<>();
/**
* A log that records the decisions / decision metadata that affected the device's time zone.
@@ -183,7 +183,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
* to be stable.
*/
@GuardedBy("this")
private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
private final ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
mTelephonySuggestionsBySlotIndex =
new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@@ -192,18 +192,16 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
* detection then the latest suggestion is cleared.
*/
@GuardedBy("this")
private ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
private final ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
/**
* The latest manual suggestion received.
*/
@GuardedBy("this")
private ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
private final ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@GuardedBy("this")
private final List<Dumpable> mDumpables = new ArrayList<>();
/**
* Creates a new instance of {@link TimeZoneDetectorStrategyImpl}.
@@ -293,7 +291,9 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
// Only store a geolocation suggestion if geolocation detection is currently enabled.
// See also clearGeolocationSuggestionIfNeeded().
// See also handleConfigChanged(), which can clear mLatestGeoLocationSuggestion.
// The suggestion's "effective from" time is ignored: we currently assume suggestions
// are made in a sensible order and the most recent is always the best one to use.
mLatestGeoLocationSuggestion.set(suggestion);
// Now perform auto time zone detection. The new suggestion may be used to modify the
@@ -427,7 +427,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
return;
}
// Use the right suggestions based on the current configuration.
// Use the correct algorithm based on the user's current configuration.
if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
doGeolocationTimeZoneDetection(detectionReason);
} else {
@@ -598,15 +598,6 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
Slog.d(LOG_TAG, "handleConfigChanged()");
}
clearGeolocationSuggestionIfNeeded();
for (ConfigurationChangeListener listener : mConfigChangeListeners) {
listener.onChange();
}
}
@GuardedBy("this")
private void clearGeolocationSuggestionIfNeeded() {
// This method is called whenever the user changes or the config for any user changes. We
// don't know what happened, so we capture the current user's config, check to see if we
// need to clear state associated with a previous user, and rerun detection.
@@ -623,15 +614,17 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// said it is ok to do so.
mLatestGeoLocationSuggestion.set(null);
mTimeZoneChangesLog.log(
"clearGeolocationSuggestionIfNeeded: Cleared latest Geolocation suggestion.");
"handleConfigChanged: Cleared latest Geolocation suggestion.");
}
doAutoTimeZoneDetection(currentUserConfig, "clearGeolocationSuggestionIfNeeded()");
}
// The configuration change may have changed available suggestions or the way suggestions
// are used, so re-run detection.
doAutoTimeZoneDetection(currentUserConfig, "handleConfigChanged()");
@Override
public synchronized void addDumpable(@NonNull Dumpable dumpable) {
mDumpables.add(dumpable);
// Pass on the signal to sub-components.
for (ConfigurationChangeListener listener : mConfigChangeListeners) {
listener.onChange();
}
}
/**
@@ -671,10 +664,6 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
mTelephonySuggestionsBySlotIndex.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
for (Dumpable dumpable : mDumpables) {
dumpable.dump(ipw, args);
}
}
/**

View File

@@ -168,7 +168,8 @@ public class LocationTimeZoneManagerService extends Binder {
// According to the SystemService docs: All lifecycle methods are called from the system
// server's main looper thread.
void onSystemReady() {
mServiceConfigAccessor.addListener(this::handleServiceConfigurationChangedOnMainThread);
mServiceConfigAccessor.addLocationTimeZoneManagerConfigListener(
this::handleServiceConfigurationChangedOnMainThread);
}
private void handleServiceConfigurationChangedOnMainThread() {

View File

@@ -29,9 +29,6 @@ import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.util.IndentingPrintWriter;
import java.util.ArrayList;
import java.util.List;
class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
private ConfigurationChangeListener mConfigurationChangeListener;
@@ -44,7 +41,6 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
private ManualTimeZoneSuggestion mLastManualSuggestion;
private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
private boolean mDumpCalled;
private final List<Dumpable> mDumpables = new ArrayList<>();
@Override
public void addConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
@@ -122,11 +118,6 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
throw new UnsupportedOperationException();
}
@Override
public void addDumpable(Dumpable dumpable) {
mDumpables.add(dumpable);
}
@Override
public void dump(IndentingPrintWriter pw, String[] args) {
mDumpCalled = true;
@@ -159,8 +150,4 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
void verifyDumpCalled() {
assertTrue(mDumpCalled);
}
void verifyHasDumpable(Dumpable expected) {
assertTrue(mDumpables.contains(expected));
}
}

View File

@@ -77,16 +77,6 @@ public class TimeZoneDetectorInternalImplTest {
mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
}
@Test
public void testAddDumpable() throws Exception {
Dumpable stubbedDumpable = mock(Dumpable.class);
mTimeZoneDetectorInternal.addDumpable(stubbedDumpable);
mTestHandler.assertTotalMessagesEnqueued(0);
mFakeTimeZoneDetectorStrategy.verifyHasDumpable(stubbedDumpable);
}
@Test
public void testAddConfigurationListener() throws Exception {
boolean[] changeCalled = new boolean[2];

View File

@@ -60,12 +60,12 @@ public class TimeZoneDetectorServiceTest {
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
private Context mMockContext;
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
private TimeZoneDetectorService mTimeZoneDetectorService;
private HandlerThread mHandlerThread;
private TestHandler mTestHandler;
private TestCallerIdentityInjector mTestCallerIdentityInjector;
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
@Before
@@ -349,11 +349,15 @@ public class TimeZoneDetectorServiceTest {
when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
.thenReturn(PackageManager.PERMISSION_GRANTED);
Dumpable dumpable = mock(Dumpable.class);
mTimeZoneDetectorService.addDumpable(dumpable);
PrintWriter pw = new PrintWriter(new StringWriter());
mTimeZoneDetectorService.dump(null, pw, null);
verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
mFakeTimeZoneDetectorStrategy.verifyDumpCalled();
verify(dumpable).dump(any(), any());
}
private static TimeZoneConfiguration createTimeZoneConfiguration(boolean autoDetectionEnabled) {

View File

@@ -47,18 +47,15 @@ import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
import android.util.IndentingPrintWriter;
import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
import org.junit.Before;
import org.junit.Test;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
/**
@@ -66,8 +63,8 @@ import java.util.function.Function;
*/
public class TimeZoneDetectorStrategyImplTest {
/** A time zone used for initialization that does not occur elsewhere in tests. */
private static final @UserIdInt int USER_ID = 9876;
/** A time zone used for initialization that does not occur elsewhere in tests. */
private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC";
private static final int SLOT_INDEX1 = 10000;
private static final int SLOT_INDEX2 = 20000;
@@ -790,7 +787,7 @@ public class TimeZoneDetectorStrategyImplTest {
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateGeolocationTimeZoneSuggestion(suggestion)
.verifyTimeZoneChangedAndReset("Europe/London");
.verifyTimeZoneChangedAndReset(suggestion);
// Assert internal service state.
assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -815,7 +812,7 @@ public class TimeZoneDetectorStrategyImplTest {
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateGeolocationTimeZoneSuggestion(londonOnlySuggestion)
.verifyTimeZoneChangedAndReset("Europe/London");
.verifyTimeZoneChangedAndReset(londonOnlySuggestion);
assertEquals(londonOnlySuggestion,
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -826,7 +823,7 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
script.simulateGeolocationTimeZoneSuggestion(parisOnlySuggestion)
.verifyTimeZoneChangedAndReset("Europe/Paris");
.verifyTimeZoneChangedAndReset(parisOnlySuggestion);
assertEquals(parisOnlySuggestion,
mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -848,7 +845,7 @@ public class TimeZoneDetectorStrategyImplTest {
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateGeolocationTimeZoneSuggestion(suggestion)
.verifyTimeZoneChangedAndReset("Europe/London");
.verifyTimeZoneChangedAndReset(suggestion);
// Assert internal service state.
assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -903,7 +900,7 @@ public class TimeZoneDetectorStrategyImplTest {
USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged()
.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
.verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0));
.verifyTimeZoneChangedAndReset(geolocationSuggestion);
// Changing the detection to disable geo detection should cause the device tz setting to
// change to the telephony suggestion.
@@ -914,28 +911,6 @@ public class TimeZoneDetectorStrategyImplTest {
assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
}
@Test
public void testAddDumpable() {
new Script()
.initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
AtomicBoolean dumpCalled = new AtomicBoolean(false);
class FakeDumpable implements Dumpable {
@Override
public void dump(IndentingPrintWriter pw, String[] args) {
dumpCalled.set(true);
}
}
mTimeZoneDetectorStrategy.addDumpable(new FakeDumpable());
IndentingPrintWriter ipw = new IndentingPrintWriter(new StringWriter());
String[] args = {"ArgOne", "ArgTwo"};
mTimeZoneDetectorStrategy.dump(ipw, args);
assertTrue(dumpCalled.get());
}
@Test
public void testGenerateMetricsState() {
ConfigurationInternal expectedInternalConfig = CONFIG_INT_AUTO_DISABLED_GEO_DISABLED;
@@ -1254,6 +1229,14 @@ public class TimeZoneDetectorStrategyImplTest {
return this;
}
Script verifyTimeZoneChangedAndReset(GeolocationTimeZoneSuggestion suggestion) {
assertEquals("Only use this method with unambiguous geo suggestions",
1, suggestion.getZoneIds().size());
mFakeEnvironment.assertTimeZoneChangedTo(suggestion.getZoneIds().get(0));
mFakeEnvironment.commitAllChanges();
return this;
}
/**
* Verifies that the configuration has been changed to the expected value.
*/