Prepare to make origin list mutable
This commit copies the pattern used in the time zone detector classes and applies it to the time detector. The origin will need to be mutable during tests to allow testing of the new "external" time source. Description of the pattern followed: Environment is the interface used by the Strategy to interact with the majority of hard-to-fake Android components. FakeEnvironment is used in the StrategyTest, EnvironmentImpl is the read deal. EnvironmentImpl further delegates to a ServiceConfigAccessor for non-user-facing settings. This hides whether the values come from static config or server flags. Specifics: The main change besides additional classes is that the EnvironmentImpl is now responsible for notifying the strategy of changes that may influence the choice of time suggestion to use. Previously, the TimeDetectorService handled notifications, which meant both the surrounding service object and the enclosed environment object knew about settings keys being used. Now it's all handled by the Environment. Later, the same callback from the environment will be used to indicate the origin list has been changed, once there's a ServerFlag to influence it. The new ServiceConfigAccessor is ready for server flags to be used, but doesn't have any yet. They will be added in a follow-up. This means there are a few constants that are not currently used, but they will be. Bug: 183239968 Test: atest services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java Test: atest services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java Change-Id: I4462afe12065a10ec762f77887c45611db052fe8
This commit is contained in:
@@ -16,26 +16,22 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.AlarmManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
@@ -43,62 +39,71 @@ import java.util.Objects;
|
||||
/**
|
||||
* The real implementation of {@link TimeDetectorStrategyImpl.Environment} used on device.
|
||||
*/
|
||||
public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
|
||||
|
||||
private static final String TAG = TimeDetectorService.TAG;
|
||||
|
||||
private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
|
||||
|
||||
/**
|
||||
* Time in the past. If automatic time suggestion is before this point, it's
|
||||
* incorrect for sure.
|
||||
*/
|
||||
private static final Instant TIME_LOWER_BOUND = Instant.ofEpochMilli(
|
||||
Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
|
||||
|
||||
/**
|
||||
* By default telephony and network only suggestions are accepted and telephony takes
|
||||
* precedence over network.
|
||||
*/
|
||||
private static final @Origin int[] DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES =
|
||||
{ ORIGIN_TELEPHONY, ORIGIN_NETWORK };
|
||||
|
||||
/**
|
||||
* If a newly calculated system clock time and the current system clock time differs by this or
|
||||
* more the system clock will actually be updated. Used to prevent the system clock being set
|
||||
* for only minor differences.
|
||||
*/
|
||||
private final int mSystemClockUpdateThresholdMillis;
|
||||
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;
|
||||
@NonNull private final int[] mOriginPriorities;
|
||||
|
||||
public EnvironmentImpl(@NonNull Context context) {
|
||||
// @NonNull after setConfigChangeListener() is called.
|
||||
@GuardedBy("this")
|
||||
private ConfigurationChangeListener mConfigChangeListener;
|
||||
|
||||
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);
|
||||
|
||||
PowerManager powerManager = context.getSystemService(PowerManager.class);
|
||||
mWakeLock = Objects.requireNonNull(
|
||||
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG));
|
||||
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG));
|
||||
|
||||
mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));
|
||||
|
||||
mUserManager = Objects.requireNonNull(context.getSystemService(UserManager.class));
|
||||
|
||||
mSystemClockUpdateThresholdMillis =
|
||||
SystemProperties.getInt("ro.sys.time_detector_update_diff",
|
||||
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
|
||||
// Wire up the config change listeners. All invocations are performed on the mHandler
|
||||
// thread.
|
||||
|
||||
mOriginPriorities = getOriginPriorities(context);
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
contentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true,
|
||||
new ContentObserver(mHandler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
handleAutoTimeDetectionChangedOnHandlerThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Internal method for handling the auto time setting being changed. */
|
||||
private void handleAutoTimeDetectionChangedOnHandlerThread() {
|
||||
synchronized (this) {
|
||||
if (mConfigChangeListener == null) {
|
||||
Slog.wtf(LOG_TAG, "mConfigChangeListener is unexpectedly null");
|
||||
}
|
||||
mConfigChangeListener.onChange();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
|
||||
synchronized (this) {
|
||||
mConfigChangeListener = Objects.requireNonNull(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int systemClockUpdateThresholdMillis() {
|
||||
return mSystemClockUpdateThresholdMillis;
|
||||
return mServiceConfigAccessor.systemClockUpdateThresholdMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,12 +117,12 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
|
||||
@Override
|
||||
public Instant autoTimeLowerBound() {
|
||||
return TIME_LOWER_BOUND;
|
||||
return mServiceConfigAccessor.autoTimeLowerBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] autoOriginPriorities() {
|
||||
return mOriginPriorities;
|
||||
return mServiceConfigAccessor.getOriginPriorities();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,7 +136,7 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
@Override
|
||||
public void acquireWakeLock() {
|
||||
if (mWakeLock.isHeld()) {
|
||||
Slog.wtf(TAG, "WakeLock " + mWakeLock + " already held");
|
||||
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " already held");
|
||||
}
|
||||
mWakeLock.acquire();
|
||||
}
|
||||
@@ -160,7 +165,7 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
|
||||
private void checkWakeLockHeld() {
|
||||
if (!mWakeLock.isHeld()) {
|
||||
Slog.wtf(TAG, "WakeLock " + mWakeLock + " not held");
|
||||
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,20 +173,4 @@ public final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environme
|
||||
UserHandle userHandle = UserHandle.of(userId);
|
||||
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
|
||||
}
|
||||
|
||||
private static int[] getOriginPriorities(@NonNull Context context) {
|
||||
String[] originStrings =
|
||||
context.getResources().getStringArray(R.array.config_autoTimeSourcesPriority);
|
||||
if (originStrings.length == 0) {
|
||||
return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
|
||||
} else {
|
||||
int[] origins = new int[originStrings.length];
|
||||
for (int i = 0; i < originStrings.length; i++) {
|
||||
int origin = stringToOrigin(originStrings[i]);
|
||||
origins[i] = origin;
|
||||
}
|
||||
|
||||
return origins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 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.timedetector;
|
||||
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A singleton that provides access to service configuration for time detection. This hides how
|
||||
* configuration is split between static, compile-time config and dynamic, server-pushed flags. It
|
||||
* provides a rudimentary mechanism to signal when values have changed.
|
||||
*/
|
||||
final class ServiceConfigAccessor {
|
||||
|
||||
private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
|
||||
|
||||
/**
|
||||
* By default telephony and network only suggestions are accepted and telephony takes
|
||||
* precedence over network.
|
||||
*/
|
||||
private static final @TimeDetectorStrategy.Origin int[]
|
||||
DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
|
||||
|
||||
/**
|
||||
* Time in the past. If an automatic time suggestion is before this point, it is sure to be
|
||||
* incorrect.
|
||||
*/
|
||||
private static final Instant TIME_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
|
||||
Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
|
||||
|
||||
private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
|
||||
new ArraySet<>(new String[] {
|
||||
}));
|
||||
|
||||
private static final Object SLOCK = new Object();
|
||||
|
||||
/** The singleton instance. Initialized once in {@link #getInstance(Context)}. */
|
||||
@GuardedBy("SLOCK")
|
||||
@Nullable
|
||||
private static ServiceConfigAccessor sInstance;
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final ServerFlags mServerFlags;
|
||||
@NonNull private final int[] mOriginPriorities;
|
||||
|
||||
/**
|
||||
* If a newly calculated system clock time and the current system clock time differs by this or
|
||||
* more the system clock will actually be updated. Used to prevent the system clock being set
|
||||
* for only minor differences.
|
||||
*/
|
||||
private final int mSystemClockUpdateThresholdMillis;
|
||||
|
||||
private ServiceConfigAccessor(@NonNull Context context) {
|
||||
mContext = Objects.requireNonNull(context);
|
||||
mServerFlags = ServerFlags.getInstance(mContext);
|
||||
mOriginPriorities = getOriginPrioritiesInternal();
|
||||
mSystemClockUpdateThresholdMillis =
|
||||
SystemProperties.getInt("ro.sys.time_detector_update_diff",
|
||||
SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
|
||||
}
|
||||
|
||||
/** Returns the singleton instance. */
|
||||
static ServiceConfigAccessor getInstance(Context context) {
|
||||
synchronized (SLOCK) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new ServiceConfigAccessor(context);
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that will be called when server flags related to this class 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.
|
||||
*/
|
||||
void addListener(@NonNull ConfigurationChangeListener listener) {
|
||||
mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
int[] getOriginPriorities() {
|
||||
return mOriginPriorities;
|
||||
}
|
||||
|
||||
int systemClockUpdateThresholdMillis() {
|
||||
return mSystemClockUpdateThresholdMillis;
|
||||
}
|
||||
|
||||
Instant autoTimeLowerBound() {
|
||||
return TIME_LOWER_BOUND_DEFAULT;
|
||||
}
|
||||
|
||||
private int[] getOriginPrioritiesInternal() {
|
||||
String[] originStrings =
|
||||
mContext.getResources().getStringArray(R.array.config_autoTimeSourcesPriority);
|
||||
if (originStrings.length == 0) {
|
||||
return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
|
||||
} else {
|
||||
int[] origins = new int[originStrings.length];
|
||||
for (int i = 0; i < originStrings.length; i++) {
|
||||
int origin = stringToOrigin(originStrings[i]);
|
||||
origins[i] = origin;
|
||||
}
|
||||
|
||||
return origins;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,9 @@ import android.app.timedetector.ITimeDetectorService;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.NetworkTimeSuggestion;
|
||||
import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -64,7 +61,16 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
TimeDetectorService service = TimeDetectorService.create(getContext());
|
||||
Context context = getContext();
|
||||
Handler handler = FgThread.getHandler();
|
||||
|
||||
ServiceConfigAccessor serviceConfigAccessor =
|
||||
ServiceConfigAccessor.getInstance(context);
|
||||
TimeDetectorStrategy timeDetectorStrategy =
|
||||
TimeDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
|
||||
|
||||
TimeDetectorService service =
|
||||
new TimeDetectorService(context, handler, timeDetectorStrategy);
|
||||
|
||||
// Publish the binder service so it can be accessed from other (appropriately
|
||||
// permissioned) processes.
|
||||
@@ -77,28 +83,6 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
@NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
|
||||
@NonNull private final CallerIdentityInjector mCallerIdentityInjector;
|
||||
|
||||
private static TimeDetectorService create(@NonNull Context context) {
|
||||
TimeDetectorStrategyImpl.Environment environment = new EnvironmentImpl(context);
|
||||
TimeDetectorStrategy timeDetectorStrategy = new TimeDetectorStrategyImpl(environment);
|
||||
|
||||
Handler handler = FgThread.getHandler();
|
||||
TimeDetectorService timeDetectorService =
|
||||
new TimeDetectorService(context, handler, timeDetectorStrategy);
|
||||
|
||||
// Wire up event listening.
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
contentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true,
|
||||
new ContentObserver(handler) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
timeDetectorService.handleAutoTimeDetectionChanged();
|
||||
}
|
||||
});
|
||||
|
||||
return timeDetectorService;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public TimeDetectorService(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull TimeDetectorStrategy timeDetectorStrategy) {
|
||||
@@ -185,12 +169,6 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub {
|
||||
mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal));
|
||||
}
|
||||
|
||||
/** Internal method for handling the auto time setting being changed. */
|
||||
@VisibleForTesting
|
||||
public void handleAutoTimeDetectionChanged() {
|
||||
mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
|
||||
@Nullable String[] args) {
|
||||
|
||||
@@ -92,12 +92,6 @@ public interface TimeDetectorStrategy extends Dumpable {
|
||||
/** Returns the configuration that controls time detector behaviour for specified user. */
|
||||
ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
|
||||
|
||||
/**
|
||||
* Handles the auto-time configuration changing For example, when the auto-time setting is
|
||||
* toggled on or off.
|
||||
*/
|
||||
void handleAutoTimeConfigChanged();
|
||||
|
||||
// Utility methods below are to be moved to a better home when one becomes more obvious.
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.app.timedetector.GnssTimeSuggestion;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.NetworkTimeSuggestion;
|
||||
import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.TimestampedValue;
|
||||
import android.util.IndentingPrintWriter;
|
||||
import android.util.LocalLog;
|
||||
@@ -37,6 +39,7 @@ import android.util.Slog;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.timezonedetector.ArrayMapWithHistory;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
import com.android.server.timezonedetector.ReferenceWithHistory;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -131,6 +134,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
*/
|
||||
public interface Environment {
|
||||
|
||||
/**
|
||||
* Sets a {@link ConfigurationChangeListener} that will be invoked when there are any
|
||||
* changes that could affect time detection. This is invoked during system server setup.
|
||||
*/
|
||||
void setConfigChangeListener(@NonNull ConfigurationChangeListener listener);
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -178,8 +187,19 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
void releaseWakeLock();
|
||||
}
|
||||
|
||||
static TimeDetectorStrategy create(
|
||||
@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
|
||||
|
||||
TimeDetectorStrategyImpl.Environment environment =
|
||||
new EnvironmentImpl(context, handler, serviceConfigAccessor);
|
||||
return new TimeDetectorStrategyImpl(environment);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TimeDetectorStrategyImpl(@NonNull Environment environment) {
|
||||
mEnvironment = Objects.requireNonNull(environment);
|
||||
mEnvironment.setConfigChangeListener(this::handleAutoTimeConfigChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,8 +299,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
return mEnvironment.configurationInternal(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void handleAutoTimeConfigChanged() {
|
||||
private synchronized void handleAutoTimeConfigChanged() {
|
||||
boolean enabled = mEnvironment.isAutoTimeDetectionEnabled();
|
||||
// When automatic time detection is enabled we update the system clock instantly if we can.
|
||||
// Conversely, when automatic time detection is disabled we leave the clock as it is.
|
||||
|
||||
@@ -47,7 +47,7 @@ import java.util.Optional;
|
||||
/**
|
||||
* The real implementation of {@link TimeZoneDetectorStrategyImpl.Environment}.
|
||||
*/
|
||||
public final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment {
|
||||
final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment {
|
||||
|
||||
private static final String LOG_TAG = TimeZoneDetectorService.TAG;
|
||||
private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
|
||||
|
||||
@@ -133,8 +133,8 @@ public final class ServiceConfigAccessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener that will be called 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 this class 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.
|
||||
|
||||
@@ -248,21 +248,6 @@ public class TimeDetectorServiceTest {
|
||||
mStubbedTimeDetectorStrategy.verifyDumpCalled();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoTimeDetectionToggle() throws Exception {
|
||||
mTimeDetectorService.handleAutoTimeDetectionChanged();
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionChangedCalled();
|
||||
|
||||
mStubbedTimeDetectorStrategy.resetCallTracking();
|
||||
|
||||
mTimeDetectorService.handleAutoTimeDetectionChanged();
|
||||
mTestHandler.assertTotalMessagesEnqueued(2);
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionChangedCalled();
|
||||
}
|
||||
|
||||
private static TelephonyTimeSuggestion createTelephonyTimeSuggestion() {
|
||||
int slotIndex = 1234;
|
||||
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
|
||||
@@ -298,7 +283,6 @@ public class TimeDetectorServiceTest {
|
||||
private NetworkTimeSuggestion mLastNetworkSuggestion;
|
||||
private GnssTimeSuggestion mLastGnssSuggestion;
|
||||
private ExternalTimeSuggestion mLastExternalSuggestion;
|
||||
private boolean mHandleAutoTimeDetectionChangedCalled;
|
||||
private boolean mDumpCalled;
|
||||
|
||||
@Override
|
||||
@@ -332,11 +316,6 @@ public class TimeDetectorServiceTest {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAutoTimeConfigChanged() {
|
||||
mHandleAutoTimeDetectionChangedCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(IndentingPrintWriter pw, String[] args) {
|
||||
mDumpCalled = true;
|
||||
@@ -348,7 +327,6 @@ public class TimeDetectorServiceTest {
|
||||
mLastNetworkSuggestion = null;
|
||||
mLastGnssSuggestion = null;
|
||||
mLastExternalSuggestion = null;
|
||||
mHandleAutoTimeDetectionChangedCalled = false;
|
||||
mDumpCalled = false;
|
||||
}
|
||||
|
||||
@@ -372,10 +350,6 @@ public class TimeDetectorServiceTest {
|
||||
assertEquals(expectedSuggestion, mLastExternalSuggestion);
|
||||
}
|
||||
|
||||
void verifyHandleAutoTimeDetectionChangedCalled() {
|
||||
assertTrue(mHandleAutoTimeDetectionChangedCalled);
|
||||
}
|
||||
|
||||
void verifyDumpCalled() {
|
||||
assertTrue(mDumpCalled);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.os.TimestampedValue;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -46,6 +47,7 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Objects;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TimeDetectorStrategyImplTest {
|
||||
@@ -1133,10 +1135,16 @@ public class TimeDetectorStrategyImplTest {
|
||||
private long mSystemClockMillis;
|
||||
private int mSystemClockUpdateThresholdMillis = 2000;
|
||||
private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY;
|
||||
private ConfigurationChangeListener mConfigChangeListener;
|
||||
|
||||
// Tracking operations.
|
||||
private boolean mSystemClockWasSet;
|
||||
|
||||
@Override
|
||||
public void setConfigChangeListener(ConfigurationChangeListener listener) {
|
||||
mConfigChangeListener = Objects.requireNonNull(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int systemClockUpdateThresholdMillis() {
|
||||
return mSystemClockUpdateThresholdMillis;
|
||||
@@ -1230,6 +1238,7 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
void simulateAutoTimeZoneDetectionToggle() {
|
||||
mAutoTimeDetectionEnabled = !mAutoTimeDetectionEnabled;
|
||||
mConfigChangeListener.onChange();
|
||||
}
|
||||
|
||||
void verifySystemClockNotSet() {
|
||||
@@ -1330,7 +1339,6 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Script simulateAutoTimeDetectionToggle() {
|
||||
mFakeEnvironment.simulateAutoTimeZoneDetectionToggle();
|
||||
mTimeDetectorStrategy.handleAutoTimeConfigChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user