Merge "Add internal service paths for enterprise setup"
This commit is contained in:
@@ -155,21 +155,33 @@ public final class ConfigurationInternal {
|
||||
return UserHandle.of(mUserId);
|
||||
}
|
||||
|
||||
/** Returns true if the user allowed to modify time zone configuration. */
|
||||
/**
|
||||
* Returns true if the user is allowed to modify time configuration, e.g. can be false due
|
||||
* to device policy (enterprise).
|
||||
*
|
||||
* <p>See also {@link #createCapabilitiesAndConfig(boolean)} for situations where this
|
||||
* value are ignored.
|
||||
*/
|
||||
public boolean isUserConfigAllowed() {
|
||||
return mUserConfigAllowed;
|
||||
}
|
||||
|
||||
/** Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values. */
|
||||
public TimeCapabilitiesAndConfig capabilitiesAndConfig() {
|
||||
return new TimeCapabilitiesAndConfig(timeCapabilities(), timeConfiguration());
|
||||
/**
|
||||
* Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
public TimeCapabilitiesAndConfig createCapabilitiesAndConfig(boolean bypassUserPolicyChecks) {
|
||||
return new TimeCapabilitiesAndConfig(
|
||||
timeCapabilities(bypassUserPolicyChecks), timeConfiguration());
|
||||
}
|
||||
|
||||
private TimeCapabilities timeCapabilities() {
|
||||
private TimeCapabilities timeCapabilities(boolean bypassUserPolicyChecks) {
|
||||
UserHandle userHandle = UserHandle.of(mUserId);
|
||||
TimeCapabilities.Builder builder = new TimeCapabilities.Builder(userHandle);
|
||||
|
||||
boolean allowConfigDateTime = isUserConfigAllowed();
|
||||
boolean allowConfigDateTime = isUserConfigAllowed() || bypassUserPolicyChecks;
|
||||
|
||||
boolean deviceHasAutoTimeDetection = isAutoDetectionSupported();
|
||||
final @CapabilityState int configureAutoDetectionEnabledCapability;
|
||||
@@ -186,15 +198,15 @@ public final class ConfigurationInternal {
|
||||
// current logic above, this could lead to a situation where a device hardware does not
|
||||
// support auto detection, the device has been forced into "auto" mode by an admin and the
|
||||
// user is unable to disable auto detection.
|
||||
final @CapabilityState int suggestManualTimeZoneCapability;
|
||||
final @CapabilityState int suggestManualTimeCapability;
|
||||
if (!allowConfigDateTime) {
|
||||
suggestManualTimeZoneCapability = CAPABILITY_NOT_ALLOWED;
|
||||
suggestManualTimeCapability = CAPABILITY_NOT_ALLOWED;
|
||||
} else if (getAutoDetectionEnabledBehavior()) {
|
||||
suggestManualTimeZoneCapability = CAPABILITY_NOT_APPLICABLE;
|
||||
suggestManualTimeCapability = CAPABILITY_NOT_APPLICABLE;
|
||||
} else {
|
||||
suggestManualTimeZoneCapability = CAPABILITY_POSSESSED;
|
||||
suggestManualTimeCapability = CAPABILITY_POSSESSED;
|
||||
}
|
||||
builder.setSetManualTimeCapability(suggestManualTimeZoneCapability);
|
||||
builder.setSetManualTimeCapability(suggestManualTimeCapability);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -53,11 +53,15 @@ public interface ServiceConfigAccessor {
|
||||
/**
|
||||
* Updates the configuration properties that control a device's time behavior.
|
||||
*
|
||||
* <p>This method returns {@code true} if the configuration was changed,
|
||||
* {@code false} otherwise.
|
||||
* <p>This method returns {@code true} if the configuration was changed, {@code false}
|
||||
* otherwise.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
boolean updateConfiguration(
|
||||
@UserIdInt int userId, @NonNull TimeConfiguration requestedConfiguration);
|
||||
@UserIdInt int userId, @NonNull TimeConfiguration requestedConfiguration,
|
||||
boolean bypassUserPolicyChecks);
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the configuration that controls time zone detector behavior for the
|
||||
|
||||
@@ -194,11 +194,11 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
|
||||
|
||||
@Override
|
||||
public synchronized boolean updateConfiguration(@UserIdInt int userId,
|
||||
@NonNull TimeConfiguration requestedConfiguration) {
|
||||
@NonNull TimeConfiguration requestedConfiguration, boolean bypassUserPolicyChecks) {
|
||||
Objects.requireNonNull(requestedConfiguration);
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
getCurrentUserConfigurationInternal().capabilitiesAndConfig();
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = getCurrentUserConfigurationInternal()
|
||||
.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
TimeConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
|
||||
|
||||
|
||||
@@ -17,16 +17,47 @@
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
|
||||
/**
|
||||
* The internal (in-process) system server API for the {@link
|
||||
* com.android.server.timedetector.TimeDetectorService}.
|
||||
* The internal (in-process) system server API for the time detector service.
|
||||
*
|
||||
* <p>The methods on this class can be called from any thread.
|
||||
*
|
||||
* <p>Methods marked with "[For device policy manager only]" are for use by the device policy
|
||||
* manager to set device state and must not enforce device policy restrictions.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TimeDetectorInternal {
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Returns a snapshot of the configuration that controls time
|
||||
* detector behavior for the current user.
|
||||
*/
|
||||
@NonNull
|
||||
TimeCapabilitiesAndConfig getCapabilitiesAndConfigForDpm();
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Updates the configuration properties that control a device's
|
||||
* time behavior for the current user.
|
||||
*
|
||||
* <p>This method returns {@code true} if the configuration was changed, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
boolean updateConfigurationForDpm(@NonNull TimeConfiguration configuration);
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Attempts to set the device to a manually entered time.
|
||||
* Returns {@code false} if the suggestion is invalid, or the device configuration prevents the
|
||||
* suggestion being used, {@code true} if the suggestion has been accepted. A suggestion that is
|
||||
* valid but does not change the time because it matches the current device time is considered
|
||||
* accepted.
|
||||
*/
|
||||
boolean setManualTimeForDpm(@NonNull ManualTimeSuggestion manualTimeSuggestion);
|
||||
|
||||
/** Used to pass new network time suggestions to the time detector. */
|
||||
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal);
|
||||
|
||||
|
||||
@@ -17,9 +17,14 @@
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.android.server.timezonedetector.CurrentUserIdentityInjector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -31,15 +36,49 @@ public class TimeDetectorInternalImpl implements TimeDetectorInternal {
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final CurrentUserIdentityInjector mCurrentUserIdentityInjector;
|
||||
@NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
|
||||
@NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;
|
||||
|
||||
public TimeDetectorInternalImpl(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull CurrentUserIdentityInjector currentUserIdentityInjector,
|
||||
@NonNull ServiceConfigAccessor serviceConfigAccessor,
|
||||
@NonNull TimeDetectorStrategy timeDetectorStrategy) {
|
||||
mContext = Objects.requireNonNull(context);
|
||||
mHandler = Objects.requireNonNull(handler);
|
||||
mCurrentUserIdentityInjector = Objects.requireNonNull(currentUserIdentityInjector);
|
||||
mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
|
||||
mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public TimeCapabilitiesAndConfig getCapabilitiesAndConfigForDpm() {
|
||||
int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
final boolean bypassUserPolicyCheck = true;
|
||||
ConfigurationInternal configurationInternal =
|
||||
mServiceConfigAccessor.getConfigurationInternal(currentUserId);
|
||||
return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyCheck);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateConfigurationForDpm(@NonNull TimeConfiguration configuration) {
|
||||
Objects.requireNonNull(configuration);
|
||||
|
||||
int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
final boolean bypassUserPolicyCheck = true;
|
||||
return mServiceConfigAccessor.updateConfiguration(
|
||||
currentUserId, configuration, bypassUserPolicyCheck);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setManualTimeForDpm(@NonNull ManualTimeSuggestion timeSignal) {
|
||||
Objects.requireNonNull(timeSignal);
|
||||
|
||||
int userId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
return mTimeDetectorStrategy.suggestManualTime(userId, timeSignal, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
|
||||
Objects.requireNonNull(timeSignal);
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.android.internal.util.DumpUtils;
|
||||
import com.android.server.FgThread;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.timezonedetector.CallerIdentityInjector;
|
||||
import com.android.server.timezonedetector.CurrentUserIdentityInjector;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -84,8 +85,11 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
TimeDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
|
||||
|
||||
// Create and publish the local service for use by internal callers.
|
||||
TimeDetectorInternal internal =
|
||||
new TimeDetectorInternalImpl(context, handler, timeDetectorStrategy);
|
||||
CurrentUserIdentityInjector currentUserIdentityInjector =
|
||||
CurrentUserIdentityInjector.REAL;
|
||||
TimeDetectorInternal internal = new TimeDetectorInternalImpl(
|
||||
context, handler, currentUserIdentityInjector, serviceConfigAccessor,
|
||||
timeDetectorStrategy);
|
||||
publishLocalService(TimeDetectorInternal.class, internal);
|
||||
|
||||
CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
|
||||
@@ -147,7 +151,8 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
try {
|
||||
ConfigurationInternal configurationInternal =
|
||||
mServiceConfigAccessor.getConfigurationInternal(userId);
|
||||
return configurationInternal.capabilitiesAndConfig();
|
||||
final boolean bypassUserPolicyCheck = false;
|
||||
return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyCheck);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -170,7 +175,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
return mServiceConfigAccessor.updateConfiguration(resolvedUserId, configuration);
|
||||
final boolean bypassUserPolicyCheck = false;
|
||||
return mServiceConfigAccessor.updateConfiguration(
|
||||
resolvedUserId, configuration, bypassUserPolicyCheck);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -313,7 +320,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
int userId = mCallerIdentityInjector.getCallingUserId();
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return mTimeDetectorStrategy.suggestManualTime(userId, timeSignal);
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return mTimeDetectorStrategy.suggestManualTime(
|
||||
userId, timeSignal, bypassUserPolicyChecks);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -335,7 +344,9 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
int userId = mCallerIdentityInjector.getCallingUserId();
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
return mTimeDetectorStrategy.suggestManualTime(userId, timeSignal);
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return mTimeDetectorStrategy.suggestManualTime(
|
||||
userId, timeSignal, bypassUserPolicyChecks);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -400,19 +411,19 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub
|
||||
}
|
||||
|
||||
private void enforceSuggestManualTimePermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE,
|
||||
"suggest manual time and time zone");
|
||||
}
|
||||
|
||||
private void enforceSuggestNetworkTimePermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.SET_TIME,
|
||||
"set time");
|
||||
}
|
||||
|
||||
private void enforceSuggestGnssTimePermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.SET_TIME,
|
||||
"suggest gnss time");
|
||||
}
|
||||
|
||||
@@ -93,8 +93,12 @@ public interface TimeDetectorStrategy extends Dumpable {
|
||||
* invalid, or the device configuration prevented the suggestion being used, {@code true} if the
|
||||
* suggestion was accepted. A suggestion that is valid but does not change the time because it
|
||||
* matches the current device time is considered accepted.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
boolean suggestManualTime(@UserIdInt int userId, @NonNull ManualTimeSuggestion timeSuggestion);
|
||||
boolean suggestManualTime(@UserIdInt int userId, @NonNull ManualTimeSuggestion timeSuggestion,
|
||||
boolean bypassUserPolicyChecks);
|
||||
|
||||
/** Processes the suggested time from network sources. */
|
||||
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static android.app.time.Capabilities.CAPABILITY_POSSESSED;
|
||||
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
|
||||
import static com.android.server.SystemClockTime.TIME_CONFIDENCE_LOW;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
|
||||
@@ -26,6 +28,8 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.TimeCapabilities;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeState;
|
||||
import android.app.time.UnixEpochTime;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
@@ -244,7 +248,8 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
@Override
|
||||
public synchronized boolean suggestManualTime(
|
||||
@UserIdInt int userId, @NonNull ManualTimeSuggestion suggestion) {
|
||||
@UserIdInt int userId, @NonNull ManualTimeSuggestion suggestion,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
|
||||
ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
|
||||
if (currentUserConfig.getUserId() != userId) {
|
||||
@@ -256,6 +261,18 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
}
|
||||
|
||||
Objects.requireNonNull(suggestion);
|
||||
String cause = "Manual time suggestion received: suggestion=" + suggestion;
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
currentUserConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
if (capabilities.getSetManualTimeCapability() != CAPABILITY_POSSESSED) {
|
||||
Slog.i(LOG_TAG, "User does not have the capability needed to set the time manually"
|
||||
+ ": capabilities=" + capabilities
|
||||
+ ", suggestion=" + suggestion
|
||||
+ ", cause=" + cause);
|
||||
return false;
|
||||
}
|
||||
|
||||
final UnixEpochTime newUnixEpochTime = suggestion.getUnixEpochTime();
|
||||
|
||||
@@ -263,7 +280,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
String cause = "Manual time suggestion received: suggestion=" + suggestion;
|
||||
return setSystemClockAndConfidenceIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
|
||||
}
|
||||
|
||||
@@ -428,7 +444,10 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
|
||||
|
||||
ipw.println("mLastAutoSystemClockTimeSet=" + mLastAutoSystemClockTimeSet);
|
||||
ipw.println("mCurrentConfigurationInternal=" + mCurrentConfigurationInternal);
|
||||
ipw.println("[Capabilities=" + mCurrentConfigurationInternal.capabilitiesAndConfig() + "]");
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
ipw.println("[Capabilities="
|
||||
+ mCurrentConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks)
|
||||
+ "]");
|
||||
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
|
||||
ipw.printf("mEnvironment.elapsedRealtimeMillis()=%s (%s)\n",
|
||||
Duration.ofMillis(elapsedRealtimeMillis), elapsedRealtimeMillis);
|
||||
|
||||
@@ -147,7 +147,13 @@ public final class ConfigurationInternal {
|
||||
return UserHandle.of(mUserId);
|
||||
}
|
||||
|
||||
/** Returns true if the user allowed to modify time zone configuration. */
|
||||
/**
|
||||
* Returns true if the user is allowed to modify time zone configuration, e.g. can be false due
|
||||
* to device policy (enterprise).
|
||||
*
|
||||
* <p>See also {@link #createCapabilitiesAndConfig(boolean)} for situations where this value
|
||||
* are ignored.
|
||||
*/
|
||||
public boolean isUserConfigAllowed() {
|
||||
return mUserConfigAllowed;
|
||||
}
|
||||
@@ -190,17 +196,24 @@ public final class ConfigurationInternal {
|
||||
|| getGeoDetectionRunInBackgroundEnabled());
|
||||
}
|
||||
|
||||
/** Creates a {@link TimeZoneCapabilitiesAndConfig} object using the configuration values. */
|
||||
public TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig() {
|
||||
return new TimeZoneCapabilitiesAndConfig(asCapabilities(), asConfiguration());
|
||||
/**
|
||||
* Creates a {@link TimeZoneCapabilitiesAndConfig} object using the configuration values.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
public TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
|
||||
boolean bypassUserPolicyChecks) {
|
||||
return new TimeZoneCapabilitiesAndConfig(
|
||||
asCapabilities(bypassUserPolicyChecks), asConfiguration());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private TimeZoneCapabilities asCapabilities() {
|
||||
private TimeZoneCapabilities asCapabilities(boolean bypassUserPolicyChecks) {
|
||||
UserHandle userHandle = UserHandle.of(mUserId);
|
||||
TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(userHandle);
|
||||
|
||||
boolean allowConfigDateTime = isUserConfigAllowed();
|
||||
boolean allowConfigDateTime = isUserConfigAllowed() || bypassUserPolicyChecks;
|
||||
|
||||
// Automatic time zone detection is only supported on devices if there is a telephony
|
||||
// network available or geolocation time zone detection is possible.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 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 android.annotation.UserIdInt;
|
||||
import android.app.ActivityManagerInternal;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
/**
|
||||
* An interface to access the current user identity in an easy to fake for tests way.
|
||||
*/
|
||||
public interface CurrentUserIdentityInjector {
|
||||
|
||||
/** A singleton for the real implementation of {@link CurrentUserIdentityInjector}. */
|
||||
CurrentUserIdentityInjector REAL = new Real();
|
||||
|
||||
/** A {@link ActivityManagerInternal#getCurrentUserId()} call. */
|
||||
@UserIdInt int getCurrentUserId();
|
||||
|
||||
/** The real implementation of {@link CurrentUserIdentityInjector}. */
|
||||
class Real implements CurrentUserIdentityInjector {
|
||||
|
||||
protected Real() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentUserId() {
|
||||
return LocalServices.getService(ActivityManagerInternal.class).getCurrentUserId();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,11 +81,15 @@ public interface ServiceConfigAccessor {
|
||||
/**
|
||||
* Updates the configuration properties that control a device's time zone behavior.
|
||||
*
|
||||
* <p>This method returns {@code true} if the configuration was changed,
|
||||
* {@code false} otherwise.
|
||||
* <p>This method returns {@code true} if the configuration was changed, {@code false}
|
||||
* otherwise.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
boolean updateConfiguration(@UserIdInt int userId,
|
||||
@NonNull TimeZoneConfiguration requestedConfiguration);
|
||||
boolean updateConfiguration(
|
||||
@UserIdInt int userId, @NonNull TimeZoneConfiguration requestedConfiguration,
|
||||
boolean bypassUserPolicyChecks);
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the configuration that controls time zone detector behavior for the
|
||||
|
||||
@@ -234,11 +234,11 @@ public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
|
||||
|
||||
@Override
|
||||
public synchronized boolean updateConfiguration(@UserIdInt int userId,
|
||||
@NonNull TimeZoneConfiguration requestedConfiguration) {
|
||||
@NonNull TimeZoneConfiguration requestedConfiguration, boolean bypassUserPolicyChecks) {
|
||||
Objects.requireNonNull(requestedConfiguration);
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
getConfigurationInternal(userId).createCapabilitiesAndConfig();
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = getConfigurationInternal(userId)
|
||||
.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
TimeZoneConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
|
||||
|
||||
|
||||
@@ -17,16 +17,47 @@
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.time.TimeZoneCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneConfiguration;
|
||||
import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
|
||||
/**
|
||||
* The internal (in-process) system server API for the {@link
|
||||
* com.android.server.timezonedetector.TimeZoneDetectorService}.
|
||||
* The internal (in-process) system server API for the time zone detector service.
|
||||
*
|
||||
* <p>The methods on this class can be called from any thread.
|
||||
*
|
||||
* <p>Methods marked with "[For device policy manager only]" are for use by the device policy
|
||||
* manager to set device state and must not enforce device policy restrictions.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface TimeZoneDetectorInternal {
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Returns a snapshot of the configuration that controls time
|
||||
* zone detector behavior for the current user.
|
||||
*/
|
||||
@NonNull
|
||||
TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfigForDpm();
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Updates the configuration properties that control a device's
|
||||
* time zone behavior for the current user.
|
||||
*
|
||||
* <p>This method returns {@code true} if the configuration was changed,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
boolean updateConfigurationForDpm(@NonNull TimeZoneConfiguration configuration);
|
||||
|
||||
/**
|
||||
* [For device policy manager only] Attempts to set the device to a manually entered time zone.
|
||||
* Returns {@code false} if the suggestion is invalid, or the device configuration prevents the
|
||||
* suggestion being used, {@code true} if the suggestion has been accepted. A suggestion that is
|
||||
* valid but does not change the time zone because it matches the current device time zone is
|
||||
* considered accepted.
|
||||
*/
|
||||
boolean setManualTimeZoneForDpm(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion);
|
||||
|
||||
/**
|
||||
* Suggests the current time zone, determined using geolocation, to the detector. The
|
||||
* detector may ignore the signal based on system settings, whether better information is
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.time.TimeZoneCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneConfiguration;
|
||||
import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
@@ -31,15 +34,51 @@ public final class TimeZoneDetectorInternalImpl implements TimeZoneDetectorInter
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final CurrentUserIdentityInjector mCurrentUserIdentityInjector;
|
||||
@NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
|
||||
@NonNull private final TimeZoneDetectorStrategy mTimeZoneDetectorStrategy;
|
||||
|
||||
public TimeZoneDetectorInternalImpl(@NonNull Context context, @NonNull Handler handler,
|
||||
@NonNull CurrentUserIdentityInjector currentUserIdentityInjector,
|
||||
@NonNull ServiceConfigAccessor serviceConfigAccessor,
|
||||
@NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
|
||||
mContext = Objects.requireNonNull(context);
|
||||
mHandler = Objects.requireNonNull(handler);
|
||||
mCurrentUserIdentityInjector = Objects.requireNonNull(currentUserIdentityInjector);
|
||||
mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
|
||||
mTimeZoneDetectorStrategy = Objects.requireNonNull(timeZoneDetectorStrategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public TimeZoneCapabilitiesAndConfig getCapabilitiesAndConfigForDpm() {
|
||||
int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
ConfigurationInternal configurationInternal =
|
||||
mServiceConfigAccessor.getConfigurationInternal(currentUserId);
|
||||
final boolean bypassUserPolicyChecks = true;
|
||||
return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateConfigurationForDpm(@NonNull TimeZoneConfiguration configuration) {
|
||||
Objects.requireNonNull(configuration);
|
||||
|
||||
int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
final boolean bypassUserPolicyChecks = true;
|
||||
return mServiceConfigAccessor.updateConfiguration(
|
||||
currentUserId, configuration, bypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setManualTimeZoneForDpm(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
|
||||
Objects.requireNonNull(timeZoneSuggestion);
|
||||
|
||||
int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
|
||||
final boolean bypassUserPolicyChecks = true;
|
||||
return mTimeZoneDetectorStrategy.suggestManualTimeZone(
|
||||
currentUserId, timeZoneSuggestion, bypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestGeolocationTimeZone(
|
||||
@NonNull GeolocationTimeZoneSuggestion timeZoneSuggestion) {
|
||||
|
||||
@@ -96,8 +96,11 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
});
|
||||
|
||||
// Create and publish the local service for use by internal callers.
|
||||
TimeZoneDetectorInternal internal =
|
||||
new TimeZoneDetectorInternalImpl(context, handler, timeZoneDetectorStrategy);
|
||||
CurrentUserIdentityInjector currentUserIdentityInjector =
|
||||
CurrentUserIdentityInjector.REAL;
|
||||
TimeZoneDetectorInternal internal = new TimeZoneDetectorInternalImpl(
|
||||
context, handler, currentUserIdentityInjector, serviceConfigAccessor,
|
||||
timeZoneDetectorStrategy);
|
||||
publishLocalService(TimeZoneDetectorInternal.class, internal);
|
||||
|
||||
// Publish the binder service so it can be accessed from other (appropriately
|
||||
@@ -175,7 +178,8 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
try {
|
||||
ConfigurationInternal configurationInternal =
|
||||
mServiceConfigAccessor.getConfigurationInternal(userId);
|
||||
return configurationInternal.createCapabilitiesAndConfig();
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -199,7 +203,9 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
return mServiceConfigAccessor.updateConfiguration(resolvedUserId, configuration);
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return mServiceConfigAccessor.updateConfiguration(
|
||||
resolvedUserId, configuration, bypassUserPolicyChecks);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -350,7 +356,9 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
int userId = mCallerIdentityInjector.getCallingUserId();
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
return mTimeZoneDetectorStrategy.suggestManualTimeZone(userId, timeZoneSuggestion);
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return mTimeZoneDetectorStrategy.suggestManualTimeZone(
|
||||
userId, timeZoneSuggestion, bypassUserPolicyChecks);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -364,7 +372,9 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
int userId = mCallerIdentityInjector.getCallingUserId();
|
||||
final long token = mCallerIdentityInjector.clearCallingIdentity();
|
||||
try {
|
||||
return mTimeZoneDetectorStrategy.suggestManualTimeZone(userId, timeZoneSuggestion);
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
return mTimeZoneDetectorStrategy.suggestManualTimeZone(
|
||||
userId, timeZoneSuggestion, bypassUserPolicyChecks);
|
||||
} finally {
|
||||
mCallerIdentityInjector.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -449,7 +459,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
private void enforceSuggestGeolocationTimeZonePermission() {
|
||||
// The associated method is only used for the shell command interface, it's not possible to
|
||||
// call it via Binder, and Shell currently can set the time zone directly anyway.
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.SET_TIME_ZONE,
|
||||
"suggest geolocation time zone");
|
||||
}
|
||||
@@ -461,7 +471,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
|
||||
}
|
||||
|
||||
private void enforceSuggestManualTimeZonePermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
mContext.enforceCallingPermission(
|
||||
android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE,
|
||||
"suggest manual time and time zone");
|
||||
}
|
||||
|
||||
@@ -120,9 +120,13 @@ public interface TimeZoneDetectorStrategy extends Dumpable {
|
||||
|
||||
/**
|
||||
* Suggests a time zone for the device using manually-entered (i.e. user sourced) information.
|
||||
*
|
||||
* @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
|
||||
* policy restrictions that should apply to actual users can be ignored
|
||||
*/
|
||||
boolean suggestManualTimeZone(
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion suggestion);
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion suggestion,
|
||||
boolean bypassUserPolicyChecks);
|
||||
|
||||
/**
|
||||
* Suggests a time zone for the device, or withdraws a previous suggestion if
|
||||
|
||||
@@ -317,7 +317,8 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
|
||||
|
||||
@Override
|
||||
public synchronized boolean suggestManualTimeZone(
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion suggestion) {
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion suggestion,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
|
||||
ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
|
||||
if (currentUserConfig.getUserId() != userId) {
|
||||
@@ -334,7 +335,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
|
||||
String cause = "Manual time suggestion received: suggestion=" + suggestion;
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
currentUserConfig.createCapabilitiesAndConfig();
|
||||
currentUserConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
if (capabilities.getSetManualTimeZoneCapability() != CAPABILITY_POSSESSED) {
|
||||
Slog.i(LOG_TAG, "User does not have the capability needed to set the time zone manually"
|
||||
@@ -757,7 +758,9 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
|
||||
|
||||
ipw.increaseIndent(); // level 1
|
||||
ipw.println("mCurrentConfigurationInternal=" + mCurrentConfigurationInternal);
|
||||
ipw.println("[Capabilities=" + mCurrentConfigurationInternal.createCapabilitiesAndConfig()
|
||||
final boolean bypassUserPolicyChecks = false;
|
||||
ipw.println("[Capabilities="
|
||||
+ mCurrentConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks)
|
||||
+ "]");
|
||||
ipw.println("mEnvironment.getDeviceTimeZone()=" + mEnvironment.getDeviceTimeZone());
|
||||
ipw.println("mEnvironment.getDeviceTimeZoneConfidence()="
|
||||
|
||||
@@ -31,8 +31,6 @@ import android.app.time.TimeCapabilities;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -40,7 +38,14 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationInternal} and associated {@link TimeCapabilitiesAndConfig}
|
||||
* behavior.
|
||||
*/
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class ConfigurationInternalTest {
|
||||
|
||||
private static final int ARBITRARY_USER_ID = 99999;
|
||||
@@ -51,116 +56,86 @@ public class ConfigurationInternalTest {
|
||||
private static final @Origin int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
|
||||
|
||||
/**
|
||||
* Tests when {@link ConfigurationInternal#isUserConfigAllowed()} and
|
||||
* {@link ConfigurationInternal#isAutoDetectionSupported()} are both true.
|
||||
* Tests {@link TimeCapabilitiesAndConfig} behavior in different scenarios when auto detection
|
||||
* is supported.
|
||||
*/
|
||||
@Test
|
||||
public void test_unrestricted() {
|
||||
ConfigurationInternal
|
||||
baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
|
||||
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSetManualTimeCapability());
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getSetManualTimeCapability());
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertFalse(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests when {@link ConfigurationInternal#isUserConfigAllowed()} is false */
|
||||
@Test
|
||||
public void test_restricted() {
|
||||
ConfigurationInternal
|
||||
baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(false)
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
|
||||
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertFalse(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests when {@link ConfigurationInternal#isAutoDetectionSupported()} is false. */
|
||||
@Test
|
||||
public void test_autoDetectNotSupported() {
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void test_autoDetectionSupported_capabilitiesAndConfiguration(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
|
||||
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
|
||||
boolean userRestrictionsExpected = !(userConfigAllowed || bypassUserPolicyChecks);
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSetManualTimeCapability());
|
||||
}
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getSetManualTimeCapability());
|
||||
}
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertFalse(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link TimeCapabilitiesAndConfig} behavior in different scenarios when auto detection
|
||||
* is not supported.
|
||||
*/
|
||||
@Test
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void test_autoDetectNotSupported_capabilitiesAndConfiguration(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.setAutoDetectionSupported(false)
|
||||
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
@@ -169,6 +144,9 @@ public class ConfigurationInternalTest {
|
||||
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
boolean userRestrictionsExpected = !(userConfigAllowed || bypassUserPolicyChecks);
|
||||
|
||||
// Auto-detection enabled.
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
@@ -176,30 +154,41 @@ public class ConfigurationInternalTest {
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
|
||||
assertFalse(autoOnConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOnConfig.capabilitiesAndConfig();
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeCapability());
|
||||
}
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
}
|
||||
|
||||
// Auto-detection disabled.
|
||||
{
|
||||
ConfigurationInternal
|
||||
autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
|
||||
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig = autoOffConfig.capabilitiesAndConfig();
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeCapability());
|
||||
}
|
||||
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertFalse(configuration.isAutoDetectionEnabled());
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** A partially implemented, fake implementation of ServiceConfigAccessor for tests. */
|
||||
class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
public class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
|
||||
private final List<ConfigurationChangeListener> mConfigurationInternalChangeListeners =
|
||||
new ArrayList<>();
|
||||
@@ -54,7 +54,8 @@ class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
|
||||
@Override
|
||||
public boolean updateConfiguration(
|
||||
@UserIdInt int userID, @NonNull TimeConfiguration requestedChanges) {
|
||||
@UserIdInt int userID, @NonNull TimeConfiguration requestedChanges,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
assertNotNull(mConfigurationInternal);
|
||||
assertNotNull(requestedChanges);
|
||||
|
||||
@@ -62,7 +63,7 @@ class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
// old configuration merged with the new if the user has the capability to up the settings.
|
||||
// Then, if the configuration changed, the change listener is invoked.
|
||||
TimeCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
mConfigurationInternal.capabilitiesAndConfig();
|
||||
mConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
TimeConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
TimeConfiguration newConfiguration =
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.TimeState;
|
||||
@@ -31,20 +28,10 @@ import android.util.IndentingPrintWriter;
|
||||
* A fake implementation of {@link com.android.server.timedetector.TimeDetectorStrategy} for use
|
||||
* in tests.
|
||||
*/
|
||||
class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||
public class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||
// State
|
||||
private TimeState mTimeState;
|
||||
|
||||
// Call tracking.
|
||||
private TelephonyTimeSuggestion mLastTelephonySuggestion;
|
||||
private @UserIdInt Integer mLastManualSuggestionUserId;
|
||||
private ManualTimeSuggestion mLastManualSuggestion;
|
||||
private NetworkTimeSuggestion mLastNetworkSuggestion;
|
||||
private GnssTimeSuggestion mLastGnssSuggestion;
|
||||
private ExternalTimeSuggestion mLastExternalSuggestion;
|
||||
private UnixEpochTime mLastConfirmedTime;
|
||||
private boolean mDumpCalled;
|
||||
|
||||
@Override
|
||||
public TimeState getTimeState() {
|
||||
return mTimeState;
|
||||
@@ -57,80 +44,32 @@ class FakeTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||
|
||||
@Override
|
||||
public boolean confirmTime(UnixEpochTime confirmationTime) {
|
||||
mLastConfirmedTime = confirmationTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestTelephonyTime(TelephonyTimeSuggestion timeSuggestion) {
|
||||
mLastTelephonySuggestion = timeSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suggestManualTime(@UserIdInt int userId, ManualTimeSuggestion timeSuggestion) {
|
||||
mLastManualSuggestionUserId = userId;
|
||||
mLastManualSuggestion = timeSuggestion;
|
||||
public boolean suggestManualTime(@UserIdInt int userId, ManualTimeSuggestion timeSuggestion,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
|
||||
mLastNetworkSuggestion = timeSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
|
||||
mLastGnssSuggestion = timeSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestExternalTime(ExternalTimeSuggestion timeSuggestion) {
|
||||
mLastExternalSuggestion = timeSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(IndentingPrintWriter pw, String[] args) {
|
||||
mDumpCalled = true;
|
||||
}
|
||||
|
||||
void resetCallTracking() {
|
||||
mLastTelephonySuggestion = null;
|
||||
mLastManualSuggestionUserId = null;
|
||||
mLastManualSuggestion = null;
|
||||
mLastNetworkSuggestion = null;
|
||||
mLastGnssSuggestion = null;
|
||||
mLastExternalSuggestion = null;
|
||||
mLastConfirmedTime = null;
|
||||
mDumpCalled = false;
|
||||
}
|
||||
|
||||
void verifySuggestTelephonyTimeCalled(TelephonyTimeSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastTelephonySuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestManualTimeCalled(
|
||||
@UserIdInt int expectedUserId, ManualTimeSuggestion expectedSuggestion) {
|
||||
assertEquals((Integer) expectedUserId, mLastManualSuggestionUserId);
|
||||
assertEquals(expectedSuggestion, mLastManualSuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestNetworkTimeCalled(NetworkTimeSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastNetworkSuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestGnssTimeCalled(GnssTimeSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastGnssSuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestExternalTimeCalled(ExternalTimeSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastExternalSuggestion);
|
||||
}
|
||||
|
||||
void verifyConfirmTimeCalled(UnixEpochTime expectedConfirmationTime) {
|
||||
assertEquals(mLastConfirmedTime, expectedConfirmationTime);
|
||||
}
|
||||
|
||||
void verifyDumpCalled() {
|
||||
assertTrue(mDumpCalled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,24 @@
|
||||
|
||||
package com.android.server.timedetector;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.time.UnixEpochTime;
|
||||
import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.timezonedetector.TestCurrentUserIdentityInjector;
|
||||
import com.android.server.timezonedetector.TestHandler;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -31,15 +41,25 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TimeDetectorInternalImplTest {
|
||||
private static final int ARBITRARY_USER_ID = 9999;
|
||||
private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
|
||||
private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
|
||||
private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
|
||||
Instant.ofEpochMilli(Long.MAX_VALUE);
|
||||
private static final int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
|
||||
|
||||
private Context mMockContext;
|
||||
private FakeTimeDetectorStrategy mFakeTimeDetectorStrategy;
|
||||
|
||||
private TimeDetectorInternalImpl mTimeDetectorInternal;
|
||||
private HandlerThread mHandlerThread;
|
||||
private TestHandler mTestHandler;
|
||||
private TestCurrentUserIdentityInjector mTestCurrentUserIdentityInjector;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
|
||||
private FakeTimeDetectorStrategy mFakeTimeDetectorStrategySpy;
|
||||
|
||||
private TimeDetectorInternalImpl mTimeDetectorInternal;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -49,11 +69,14 @@ public class TimeDetectorInternalImplTest {
|
||||
mHandlerThread = new HandlerThread("TimeDetectorInternalTest");
|
||||
mHandlerThread.start();
|
||||
mTestHandler = new TestHandler(mHandlerThread.getLooper());
|
||||
|
||||
mFakeTimeDetectorStrategy = new FakeTimeDetectorStrategy();
|
||||
mTestCurrentUserIdentityInjector = new TestCurrentUserIdentityInjector();
|
||||
mTestCurrentUserIdentityInjector.initializeCurrentUserId(ARBITRARY_USER_ID);
|
||||
mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
|
||||
mFakeTimeDetectorStrategySpy = spy(new FakeTimeDetectorStrategy());
|
||||
|
||||
mTimeDetectorInternal = new TimeDetectorInternalImpl(
|
||||
mMockContext, mTestHandler, mFakeTimeDetectorStrategy);
|
||||
mMockContext, mTestHandler, mTestCurrentUserIdentityInjector,
|
||||
mFakeServiceConfigAccessorSpy, mFakeTimeDetectorStrategySpy);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -62,6 +85,56 @@ public class TimeDetectorInternalImplTest {
|
||||
mHandlerThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCapabilitiesAndConfigForDpm() throws Exception {
|
||||
final boolean autoDetectionEnabled = true;
|
||||
ConfigurationInternal testConfig = createConfigurationInternal(autoDetectionEnabled);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(testConfig);
|
||||
|
||||
TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
|
||||
mTimeDetectorInternal.getCapabilitiesAndConfigForDpm();
|
||||
|
||||
int expectedUserId = mTestCurrentUserIdentityInjector.getCurrentUserId();
|
||||
verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
|
||||
|
||||
final boolean bypassUserPolicyChecks = true;
|
||||
TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
|
||||
testConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
assertEquals(expectedCapabilitiesAndConfig, actualCapabilitiesAndConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateConfigurationForDpm() throws Exception {
|
||||
final boolean autoDetectionEnabled = false;
|
||||
ConfigurationInternal initialConfigurationInternal =
|
||||
createConfigurationInternal(autoDetectionEnabled);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfigurationInternal);
|
||||
|
||||
TimeConfiguration timeConfiguration = new TimeConfiguration.Builder()
|
||||
.setAutoDetectionEnabled(true)
|
||||
.build();
|
||||
assertTrue(mTimeDetectorInternal.updateConfigurationForDpm(timeConfiguration));
|
||||
|
||||
final boolean expectedBypassUserPolicyChecks = true;
|
||||
verify(mFakeServiceConfigAccessorSpy).updateConfiguration(
|
||||
mTestCurrentUserIdentityInjector.getCurrentUserId(),
|
||||
timeConfiguration,
|
||||
expectedBypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetManualTimeZoneForDpm() throws Exception {
|
||||
ManualTimeSuggestion timeSuggestion = createManualTimeSuggestion();
|
||||
|
||||
// The fake strategy always returns true.
|
||||
assertTrue(mTimeDetectorInternal.setManualTimeForDpm(timeSuggestion));
|
||||
|
||||
int expectedUserId = mTestCurrentUserIdentityInjector.getCurrentUserId();
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestManualTime(
|
||||
expectedUserId, timeSuggestion, expectedBypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestNetworkTime() throws Exception {
|
||||
NetworkTimeSuggestion networkTimeSuggestion = createNetworkTimeSuggestion();
|
||||
@@ -70,7 +143,7 @@ public class TimeDetectorInternalImplTest {
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestNetworkTimeCalled(networkTimeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestNetworkTime(networkTimeSuggestion);
|
||||
}
|
||||
|
||||
private static NetworkTimeSuggestion createNetworkTimeSuggestion() {
|
||||
@@ -86,11 +159,29 @@ public class TimeDetectorInternalImplTest {
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestGnssTime(gnssTimeSuggestion);
|
||||
}
|
||||
|
||||
private static ManualTimeSuggestion createManualTimeSuggestion() {
|
||||
UnixEpochTime timeValue = new UnixEpochTime(100L, 1_000_000L);
|
||||
return new ManualTimeSuggestion(timeValue);
|
||||
}
|
||||
|
||||
private static GnssTimeSuggestion createGnssTimeSuggestion() {
|
||||
UnixEpochTime timeValue = new UnixEpochTime(100L, 1_000_000L);
|
||||
return new GnssTimeSuggestion(timeValue);
|
||||
}
|
||||
|
||||
private static ConfigurationInternal createConfigurationInternal(boolean autoDetectionEnabled) {
|
||||
return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setAutoDetectionSupported(true)
|
||||
.setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
|
||||
.setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
|
||||
.setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
|
||||
.setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
|
||||
.setAutoDetectionEnabledSetting(autoDetectionEnabled)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,14 @@ import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.app.time.ITimeDetectorListener;
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeConfiguration;
|
||||
import android.app.time.TimeState;
|
||||
import android.app.time.UnixEpochTime;
|
||||
@@ -77,14 +79,14 @@ public class TimeDetectorServiceTest {
|
||||
|
||||
private Context mMockContext;
|
||||
|
||||
private TimeDetectorService mTimeDetectorService;
|
||||
private HandlerThread mHandlerThread;
|
||||
private TestHandler mTestHandler;
|
||||
private TestCallerIdentityInjector mTestCallerIdentityInjector;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessor;
|
||||
private NtpTrustedTime mMockNtpTrustedTime;
|
||||
private FakeTimeDetectorStrategy mFakeTimeDetectorStrategy;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
|
||||
private FakeTimeDetectorStrategy mFakeTimeDetectorStrategySpy;
|
||||
|
||||
private NtpTrustedTime mMockNtpTrustedTime;
|
||||
private TimeDetectorService mTimeDetectorService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -98,13 +100,13 @@ public class TimeDetectorServiceTest {
|
||||
mTestCallerIdentityInjector = new TestCallerIdentityInjector();
|
||||
mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
|
||||
|
||||
mFakeTimeDetectorStrategy = new FakeTimeDetectorStrategy();
|
||||
mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
|
||||
mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
|
||||
mFakeTimeDetectorStrategySpy = spy(new FakeTimeDetectorStrategy());
|
||||
mMockNtpTrustedTime = mock(NtpTrustedTime.class);
|
||||
|
||||
mTimeDetectorService = new TimeDetectorService(
|
||||
mMockContext, mTestHandler, mTestCallerIdentityInjector, mFakeServiceConfigAccessor,
|
||||
mFakeTimeDetectorStrategy, mMockNtpTrustedTime);
|
||||
mMockContext, mTestHandler, mTestCallerIdentityInjector,
|
||||
mFakeServiceConfigAccessorSpy, mFakeTimeDetectorStrategySpy, mMockNtpTrustedTime);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -129,13 +131,19 @@ public class TimeDetectorServiceTest {
|
||||
|
||||
ConfigurationInternal configuration =
|
||||
createConfigurationInternal(true /* autoDetectionEnabled*/);
|
||||
mFakeServiceConfigAccessor.initializeConfiguration(configuration);
|
||||
|
||||
assertEquals(configuration.capabilitiesAndConfig(),
|
||||
mTimeDetectorService.getCapabilitiesAndConfig());
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(configuration);
|
||||
|
||||
TimeCapabilitiesAndConfig actualCapabilitiesAndConfig =
|
||||
mTimeDetectorService.getCapabilitiesAndConfig();
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
|
||||
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
TimeCapabilitiesAndConfig expectedCapabilitiesAndConfig =
|
||||
configuration.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
assertEquals(expectedCapabilitiesAndConfig, actualCapabilitiesAndConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,7 +173,7 @@ public class TimeDetectorServiceTest {
|
||||
public void testListenerRegistrationAndCallbacks() throws Exception {
|
||||
ConfigurationInternal initialConfiguration =
|
||||
createConfigurationInternal(false /* autoDetectionEnabled */);
|
||||
mFakeServiceConfigAccessor.initializeConfiguration(initialConfiguration);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfiguration);
|
||||
|
||||
IBinder mockListenerBinder = mock(IBinder.class);
|
||||
ITimeDetectorListener mockListener = mock(ITimeDetectorListener.class);
|
||||
@@ -258,32 +266,34 @@ public class TimeDetectorServiceTest {
|
||||
eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestTelephonyTimeCalled(timeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestTelephonyTime(timeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeDetectorService.suggestManualTime(manualTimeSuggestion));
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
|
||||
|
||||
assertTrue(mTimeDetectorService.suggestManualTime(manualTimeSuggestion));
|
||||
mFakeTimeDetectorStrategy.verifySuggestManualTimeCalled(
|
||||
mTestCallerIdentityInjector.getCallingUserId(), manualTimeSuggestion);
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestManualTime(
|
||||
expectedUserId, manualTimeSuggestion, expectedBypassUserPolicyChecks);
|
||||
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString());
|
||||
|
||||
}
|
||||
@@ -291,55 +301,55 @@ public class TimeDetectorServiceTest {
|
||||
@Test
|
||||
public void testSuggestNetworkTime_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
NetworkTimeSuggestion networkTimeSuggestion = createNetworkTimeSuggestion();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeDetectorService.suggestNetworkTime(networkTimeSuggestion));
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestNetworkTime() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
NetworkTimeSuggestion networkTimeSuggestion = createNetworkTimeSuggestion();
|
||||
mTimeDetectorService.suggestNetworkTime(networkTimeSuggestion);
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestNetworkTimeCalled(networkTimeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestNetworkTime(networkTimeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestGnssTime_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion));
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestGnssTime() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
|
||||
mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion);
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestGnssTime(gnssTimeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -366,7 +376,7 @@ public class TimeDetectorServiceTest {
|
||||
eq(android.Manifest.permission.SUGGEST_EXTERNAL_TIME), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeDetectorStrategy.verifySuggestExternalTimeCalled(externalTimeSuggestion);
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestExternalTime(externalTimeSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -390,7 +400,7 @@ public class TimeDetectorServiceTest {
|
||||
public void testGetTimeState() {
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
TimeState fakeState = new TimeState(new UnixEpochTime(12345L, 98765L), true);
|
||||
mFakeTimeDetectorStrategy.setTimeState(fakeState);
|
||||
mFakeTimeDetectorStrategySpy.setTimeState(fakeState);
|
||||
|
||||
TimeState actualState = mTimeDetectorService.getTimeState();
|
||||
|
||||
@@ -418,7 +428,7 @@ public class TimeDetectorServiceTest {
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
assertEquals(mFakeTimeDetectorStrategy.getTimeState(), state);
|
||||
assertEquals(mFakeTimeDetectorStrategySpy.getTimeState(), state);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -442,7 +452,7 @@ public class TimeDetectorServiceTest {
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
mFakeTimeDetectorStrategy.verifyConfirmTimeCalled(confirmationTime);
|
||||
verify(mFakeTimeDetectorStrategySpy).confirmTime(confirmationTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -467,8 +477,10 @@ public class TimeDetectorServiceTest {
|
||||
mTimeDetectorService.setManualTime(timeSuggestion));
|
||||
|
||||
// The service calls "suggestManualTime()" because the logic is the same.
|
||||
mFakeTimeDetectorStrategy.verifySuggestManualTimeCalled(
|
||||
mTestCallerIdentityInjector.getCallingUserId(), timeSuggestion);
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
verify(mFakeTimeDetectorStrategySpy).suggestManualTime(
|
||||
expectedUserId, timeSuggestion, expectedBypassUserPolicyChecks);
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
@@ -495,7 +507,7 @@ public class TimeDetectorServiceTest {
|
||||
mTimeDetectorService.dump(null, pw, null);
|
||||
|
||||
verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
|
||||
mFakeTimeDetectorStrategy.verifyDumpCalled();
|
||||
verify(mFakeTimeDetectorStrategySpy).dump(any(), any());
|
||||
}
|
||||
|
||||
private static TimeConfiguration createTimeConfiguration(boolean autoDetectionEnabled) {
|
||||
|
||||
@@ -38,8 +38,6 @@ import android.app.timedetector.ManualTimeSuggestion;
|
||||
import android.app.timedetector.TelephonyTimeSuggestion;
|
||||
import android.os.TimestampedValue;
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.SystemClockTime.TimeConfidence;
|
||||
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
|
||||
import com.android.server.timezonedetector.ConfigurationChangeListener;
|
||||
@@ -55,7 +53,10 @@ import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Objects;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class TimeDetectorStrategyImplTest {
|
||||
|
||||
private static final @UserIdInt int ARBITRARY_USER_ID = 9876;
|
||||
@@ -656,12 +657,45 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
}
|
||||
|
||||
/** Confirms the effect of user policy restrictions on being able to set the time. */
|
||||
@Test
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void testSuggestManualTime_autoTimeDisabled_userRestrictions(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal configAutoDisabled =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.build();
|
||||
Script script = new Script().simulateConfigurationInternalChange(configAutoDisabled)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
|
||||
|
||||
ManualTimeSuggestion timeSuggestion =
|
||||
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
|
||||
script.simulateTimePassing();
|
||||
|
||||
long expectedSystemClockMillis =
|
||||
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
|
||||
boolean expectedResult = userConfigAllowed || bypassUserPolicyChecks;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult);
|
||||
if (expectedResult) {
|
||||
script.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
|
||||
} else {
|
||||
script.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTime_retainsAutoSignal() {
|
||||
Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
|
||||
@@ -704,8 +738,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
long expectedManualClockMillis =
|
||||
script.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, manualTimeSuggestion, true /* expectedResult */)
|
||||
ARBITRARY_USER_ID, manualTimeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
|
||||
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
|
||||
@@ -737,9 +773,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
ManualTimeSuggestion timeSuggestion =
|
||||
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
|
||||
script.simulateTimePassing()
|
||||
.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = false;
|
||||
script.simulateTimePassing().simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
@@ -755,8 +792,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = false;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
@@ -772,8 +811,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
|
||||
}
|
||||
@@ -789,8 +830,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = false;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
|
||||
.verifySystemClockWasNotSetAndResetCallTracking();
|
||||
}
|
||||
@@ -806,8 +849,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
|
||||
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
|
||||
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
|
||||
}
|
||||
@@ -1758,8 +1803,10 @@ public class TimeDetectorStrategyImplTest {
|
||||
ManualTimeSuggestion timeSuggestion =
|
||||
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
|
||||
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeSuggestion(
|
||||
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
|
||||
ARBITRARY_USER_ID, timeSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
|
||||
}
|
||||
|
||||
@@ -1951,14 +1998,15 @@ public class TimeDetectorStrategyImplTest {
|
||||
|
||||
Script simulateManualTimeSuggestion(
|
||||
@UserIdInt int userId, ManualTimeSuggestion timeSuggestion,
|
||||
boolean expectedResult) {
|
||||
boolean bypassUserPolicyChecks, boolean expectedResult) {
|
||||
String errorMessage = expectedResult
|
||||
? "Manual time suggestion was ignored, but expected to be accepted."
|
||||
: "Manual time suggestion was accepted, but expected to be ignored.";
|
||||
assertEquals(
|
||||
errorMessage,
|
||||
expectedResult,
|
||||
mTimeDetectorStrategy.suggestManualTime(userId, timeSuggestion));
|
||||
mTimeDetectorStrategy.suggestManualTime(
|
||||
userId, timeSuggestion, bypassUserPolicyChecks));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,27 +29,36 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.time.TimeCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneCapabilities;
|
||||
import android.app.time.TimeZoneCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneConfiguration;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationInternal} and the {@link TimeZoneCapabilitiesAndConfig}.
|
||||
* Tests for {@link ConfigurationInternal} and associated {@link TimeZoneCapabilitiesAndConfig}
|
||||
* behavior.
|
||||
*/
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class ConfigurationInternalTest {
|
||||
|
||||
private static final int ARBITRARY_USER_ID = 99999;
|
||||
|
||||
/**
|
||||
* Tests when {@link ConfigurationInternal#isUserConfigAllowed()} and
|
||||
* {@link ConfigurationInternal#isAutoDetectionSupported()} are both true.
|
||||
* Tests {@link TimeCapabilitiesAndConfig} behavior in different scenarios when auto detection
|
||||
* is supported (and geo detection is supported)
|
||||
*/
|
||||
@Test
|
||||
public void test_unrestricted() {
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void test_autoDetectionSupported_capabilitiesAndConfiguration(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.setTelephonyDetectionFeatureSupported(true)
|
||||
.setGeoDetectionFeatureSupported(true)
|
||||
.setGeoDetectionRunInBackgroundEnabled(false)
|
||||
@@ -59,6 +68,10 @@ public class ConfigurationInternalTest {
|
||||
.setLocationEnabledSetting(true)
|
||||
.setGeoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
|
||||
boolean userRestrictionsExpected = !(userConfigAllowed || bypassUserPolicyChecks);
|
||||
|
||||
// Auto-detection enabled.
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
@@ -70,13 +83,21 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_GEO, autoOnConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig();
|
||||
autoOnConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
// This has user privacy implications so it is not restricted in the same way as others.
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
@@ -85,6 +106,7 @@ public class ConfigurationInternalTest {
|
||||
assertTrue(configuration.isGeoDetectionEnabled());
|
||||
}
|
||||
|
||||
// Auto-detection disabled.
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
@@ -96,81 +118,20 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_MANUAL, autoOffConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig();
|
||||
autoOffConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertFalse(configuration.isAutoDetectionEnabled());
|
||||
assertTrue(configuration.isGeoDetectionEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests when {@link ConfigurationInternal#isUserConfigAllowed()} is false */
|
||||
@Test
|
||||
public void test_restricted() {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(false)
|
||||
.setTelephonyDetectionFeatureSupported(true)
|
||||
.setGeoDetectionFeatureSupported(true)
|
||||
.setTelephonyFallbackSupported(false)
|
||||
.setGeoDetectionRunInBackgroundEnabled(false)
|
||||
.setEnhancedMetricsCollectionEnabled(false)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.setLocationEnabledSetting(true)
|
||||
.setGeoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
|
||||
assertTrue(autoOnConfig.getGeoDetectionEnabledSetting());
|
||||
assertTrue(autoOnConfig.getAutoDetectionEnabledBehavior());
|
||||
assertTrue(autoOnConfig.isGeoDetectionExecutionEnabled());
|
||||
assertEquals(DETECTION_MODE_GEO, autoOnConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig();
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
// This has user privacy implications so it is not restricted in the same way as others.
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
assertTrue(configuration.isGeoDetectionEnabled());
|
||||
}
|
||||
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
|
||||
assertTrue(autoOffConfig.getGeoDetectionEnabledSetting());
|
||||
assertFalse(autoOffConfig.getAutoDetectionEnabledBehavior());
|
||||
assertFalse(autoOffConfig.isGeoDetectionExecutionEnabled());
|
||||
assertEquals(DETECTION_MODE_MANUAL, autoOffConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig();
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
// This has user privacy implications so it is not restricted in the same way as others.
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
@@ -181,11 +142,16 @@ public class ConfigurationInternalTest {
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests when {@link ConfigurationInternal#isAutoDetectionSupported()} is false. */
|
||||
/**
|
||||
* Tests {@link TimeCapabilitiesAndConfig} behavior in different scenarios when auto detection
|
||||
* is not supported.
|
||||
*/
|
||||
@Test
|
||||
public void test_autoDetectNotSupported() {
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void test_autoDetectNotSupported_capabilitiesAndConfiguration(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.setTelephonyDetectionFeatureSupported(false)
|
||||
.setGeoDetectionFeatureSupported(false)
|
||||
.setGeoDetectionRunInBackgroundEnabled(false)
|
||||
@@ -195,6 +161,10 @@ public class ConfigurationInternalTest {
|
||||
.setLocationEnabledSetting(true)
|
||||
.setGeoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
|
||||
boolean userRestrictionsExpected = !(userConfigAllowed || bypassUserPolicyChecks);
|
||||
|
||||
// Auto-detection enabled.
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
@@ -206,12 +176,16 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_MANUAL, autoOnConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig();
|
||||
autoOnConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
@@ -219,6 +193,8 @@ public class ConfigurationInternalTest {
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
assertTrue(configuration.isGeoDetectionEnabled());
|
||||
}
|
||||
|
||||
// Auto-detection disabled.
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
@@ -230,12 +206,16 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_MANUAL, autoOffConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig();
|
||||
autoOffConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
@@ -246,13 +226,15 @@ public class ConfigurationInternalTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests when {@link ConfigurationInternal#isAutoDetectionSupported()} is true, but
|
||||
* {@link ConfigurationInternal#isGeoDetectionSupported()} is false.
|
||||
* Tests {@link TimeCapabilitiesAndConfig} behavior in different scenarios when auto detection
|
||||
* is supported (and geo detection is not supported).
|
||||
*/
|
||||
@Test
|
||||
public void test_geoDetectNotSupported() {
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void test_geoDetectNotSupported_capabilitiesAndConfiguration(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setUserConfigAllowed(true)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.setTelephonyDetectionFeatureSupported(true)
|
||||
.setGeoDetectionFeatureSupported(false)
|
||||
.setGeoDetectionRunInBackgroundEnabled(false)
|
||||
@@ -262,6 +244,10 @@ public class ConfigurationInternalTest {
|
||||
.setLocationEnabledSetting(true)
|
||||
.setGeoDetectionEnabledSetting(true)
|
||||
.build();
|
||||
|
||||
boolean userRestrictionsExpected = !(userConfigAllowed || bypassUserPolicyChecks);
|
||||
|
||||
// Auto-detection enabled.
|
||||
{
|
||||
ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(true)
|
||||
@@ -273,13 +259,20 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_TELEPHONY, autoOnConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOnConfig.createCapabilitiesAndConfig();
|
||||
autoOnConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_APPLICABLE,
|
||||
capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
@@ -287,6 +280,8 @@ public class ConfigurationInternalTest {
|
||||
assertTrue(configuration.isAutoDetectionEnabled());
|
||||
assertTrue(configuration.isGeoDetectionEnabled());
|
||||
}
|
||||
|
||||
// Auto-detection disabled.
|
||||
{
|
||||
ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
|
||||
.setAutoDetectionEnabledSetting(false)
|
||||
@@ -298,12 +293,18 @@ public class ConfigurationInternalTest {
|
||||
assertEquals(DETECTION_MODE_MANUAL, autoOffConfig.getDetectionMode());
|
||||
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
autoOffConfig.createCapabilitiesAndConfig();
|
||||
autoOffConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
if (userRestrictionsExpected) {
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSetManualTimeZoneCapability());
|
||||
} else {
|
||||
assertEquals(CAPABILITY_POSSESSED,
|
||||
capabilities.getConfigureAutoDetectionEnabledCapability());
|
||||
assertEquals(CAPABILITY_POSSESSED, capabilities.getSetManualTimeZoneCapability());
|
||||
}
|
||||
assertEquals(CAPABILITY_NOT_SUPPORTED,
|
||||
capabilities.getConfigureGeoDetectionEnabledCapability());
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/** A partially implemented, fake implementation of ServiceConfigAccessor for tests. */
|
||||
class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
public class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
|
||||
private final List<ConfigurationChangeListener> mConfigurationInternalChangeListeners =
|
||||
new ArrayList<>();
|
||||
@@ -55,7 +55,8 @@ class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
|
||||
@Override
|
||||
public boolean updateConfiguration(
|
||||
@UserIdInt int userID, @NonNull TimeZoneConfiguration requestedChanges) {
|
||||
@UserIdInt int userID, @NonNull TimeZoneConfiguration requestedChanges,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
assertNotNull(mConfigurationInternal);
|
||||
assertNotNull(requestedChanges);
|
||||
|
||||
@@ -63,7 +64,7 @@ class FakeServiceConfigAccessor implements ServiceConfigAccessor {
|
||||
// old configuration merged with the new if the user has the capability to up the settings.
|
||||
// Then, if the configuration changed, the change listener is invoked.
|
||||
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
|
||||
mConfigurationInternal.createCapabilitiesAndConfig();
|
||||
mConfigurationInternal.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
|
||||
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
|
||||
TimeZoneConfiguration newConfiguration =
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.app.time.TimeZoneState;
|
||||
@@ -25,21 +22,12 @@ import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
|
||||
public class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
|
||||
|
||||
private TimeZoneState mTimeZoneState;
|
||||
|
||||
// Call tracking.
|
||||
private GeolocationTimeZoneSuggestion mLastGeolocationSuggestion;
|
||||
private ManualTimeZoneSuggestion mLastManualSuggestion;
|
||||
private Integer mLastManualSuggestionUserId;
|
||||
private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
|
||||
private String mLastConfirmedTimeZone;
|
||||
private boolean mDumpCalled;
|
||||
|
||||
@Override
|
||||
public boolean confirmTimeZone(String timeZoneId) {
|
||||
mLastConfirmedTimeZone = timeZoneId;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -55,21 +43,17 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
|
||||
|
||||
@Override
|
||||
public void suggestGeolocationTimeZone(GeolocationTimeZoneSuggestion timeZoneSuggestion) {
|
||||
mLastGeolocationSuggestion = timeZoneSuggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suggestManualTimeZone(
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
|
||||
mLastManualSuggestionUserId = userId;
|
||||
mLastManualSuggestion = timeZoneSuggestion;
|
||||
@UserIdInt int userId, @NonNull ManualTimeZoneSuggestion timeZoneSuggestion,
|
||||
boolean bypassUserPolicyChecks) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestTelephonyTimeZone(
|
||||
@NonNull TelephonyTimeZoneSuggestion timeZoneSuggestion) {
|
||||
mLastTelephonySuggestion = timeZoneSuggestion;
|
||||
public void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion timeZoneSuggestion) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,38 +78,5 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
|
||||
|
||||
@Override
|
||||
public void dump(IndentingPrintWriter pw, String[] args) {
|
||||
mDumpCalled = true;
|
||||
}
|
||||
|
||||
void resetCallTracking() {
|
||||
mLastGeolocationSuggestion = null;
|
||||
mLastManualSuggestion = null;
|
||||
mLastManualSuggestionUserId = null;
|
||||
mLastTelephonySuggestion = null;
|
||||
mDumpCalled = false;
|
||||
mLastConfirmedTimeZone = null;
|
||||
}
|
||||
|
||||
void verifySuggestGeolocationTimeZoneCalled(
|
||||
GeolocationTimeZoneSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastGeolocationSuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestManualTimeZoneCalled(
|
||||
@UserIdInt int expectedUserId, ManualTimeZoneSuggestion expectedSuggestion) {
|
||||
assertEquals((Integer) expectedUserId, mLastManualSuggestionUserId);
|
||||
assertEquals(expectedSuggestion, mLastManualSuggestion);
|
||||
}
|
||||
|
||||
void verifySuggestTelephonyTimeZoneCalled(TelephonyTimeZoneSuggestion expectedSuggestion) {
|
||||
assertEquals(expectedSuggestion, mLastTelephonySuggestion);
|
||||
}
|
||||
|
||||
void verifyDumpCalled() {
|
||||
assertTrue(mDumpCalled);
|
||||
}
|
||||
|
||||
void verifyConfirmTimeZoneCalled(String expectedTimeZoneId) {
|
||||
assertEquals(expectedTimeZoneId, mLastConfirmedTimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2022 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 android.annotation.UserIdInt;
|
||||
|
||||
/** A fake {@link CurrentUserIdentityInjector} used in tests. */
|
||||
public class TestCurrentUserIdentityInjector implements CurrentUserIdentityInjector {
|
||||
|
||||
private Integer mCurrentUserId;
|
||||
|
||||
public void initializeCurrentUserId(@UserIdInt int userId) {
|
||||
mCurrentUserId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentUserId() {
|
||||
return mCurrentUserId;
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,15 @@
|
||||
|
||||
package com.android.server.timezonedetector;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.time.TimeZoneCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneConfiguration;
|
||||
import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
@@ -35,15 +42,18 @@ import java.util.List;
|
||||
public class TimeZoneDetectorInternalImplTest {
|
||||
|
||||
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
|
||||
private static final List<String> ARBITRARY_ZONE_IDS = Arrays.asList("TestZoneId");
|
||||
private static final String ARBITRARY_ZONE_ID = "TestZoneId";
|
||||
private static final List<String> ARBITRARY_ZONE_IDS = Arrays.asList(ARBITRARY_ZONE_ID);
|
||||
private static final int ARBITRARY_USER_ID = 9999;
|
||||
|
||||
private Context mMockContext;
|
||||
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
|
||||
|
||||
private TimeZoneDetectorInternalImpl mTimeZoneDetectorInternal;
|
||||
private HandlerThread mHandlerThread;
|
||||
private TestHandler mTestHandler;
|
||||
private TestCurrentUserIdentityInjector mTestCurrentUserIdentityInjector;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
|
||||
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategySpy;
|
||||
|
||||
private TimeZoneDetectorInternalImpl mTimeZoneDetectorInternal;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -53,11 +63,14 @@ public class TimeZoneDetectorInternalImplTest {
|
||||
mHandlerThread = new HandlerThread("TimeZoneDetectorInternalTest");
|
||||
mHandlerThread.start();
|
||||
mTestHandler = new TestHandler(mHandlerThread.getLooper());
|
||||
|
||||
mFakeTimeZoneDetectorStrategy = new FakeTimeZoneDetectorStrategy();
|
||||
mTestCurrentUserIdentityInjector = new TestCurrentUserIdentityInjector();
|
||||
mTestCurrentUserIdentityInjector.initializeCurrentUserId(ARBITRARY_USER_ID);
|
||||
mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
|
||||
mFakeTimeZoneDetectorStrategySpy = spy(new FakeTimeZoneDetectorStrategy());
|
||||
|
||||
mTimeZoneDetectorInternal = new TimeZoneDetectorInternalImpl(
|
||||
mMockContext, mTestHandler, mFakeTimeZoneDetectorStrategy);
|
||||
mMockContext, mTestHandler, mTestCurrentUserIdentityInjector,
|
||||
mFakeServiceConfigAccessorSpy, mFakeTimeZoneDetectorStrategySpy);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -66,6 +79,56 @@ public class TimeZoneDetectorInternalImplTest {
|
||||
mHandlerThread.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCapabilitiesAndConfigForDpm() throws Exception {
|
||||
final boolean autoDetectionEnabled = true;
|
||||
ConfigurationInternal testConfig = createConfigurationInternal(autoDetectionEnabled);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(testConfig);
|
||||
|
||||
TimeZoneCapabilitiesAndConfig actualCapabilitiesAndConfig =
|
||||
mTimeZoneDetectorInternal.getCapabilitiesAndConfigForDpm();
|
||||
|
||||
int expectedUserId = mTestCurrentUserIdentityInjector.getCurrentUserId();
|
||||
verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
|
||||
|
||||
final boolean bypassUserPolicyChecks = true;
|
||||
TimeZoneCapabilitiesAndConfig expectedCapabilitiesAndConfig =
|
||||
testConfig.createCapabilitiesAndConfig(bypassUserPolicyChecks);
|
||||
assertEquals(expectedCapabilitiesAndConfig, actualCapabilitiesAndConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateConfigurationForDpm() throws Exception {
|
||||
final boolean autoDetectionEnabled = false;
|
||||
ConfigurationInternal initialConfigurationInternal =
|
||||
createConfigurationInternal(autoDetectionEnabled);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfigurationInternal);
|
||||
|
||||
TimeZoneConfiguration timeConfiguration = new TimeZoneConfiguration.Builder()
|
||||
.setAutoDetectionEnabled(true)
|
||||
.build();
|
||||
assertTrue(mTimeZoneDetectorInternal.updateConfigurationForDpm(timeConfiguration));
|
||||
|
||||
final boolean expectedBypassUserPolicyChecks = true;
|
||||
verify(mFakeServiceConfigAccessorSpy).updateConfiguration(
|
||||
mTestCurrentUserIdentityInjector.getCurrentUserId(),
|
||||
timeConfiguration,
|
||||
expectedBypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetManualTimeZoneForDpm() throws Exception {
|
||||
ManualTimeZoneSuggestion timeZoneSuggestion = createManualTimeZoneSuggestion();
|
||||
|
||||
// The fake strategy always returns true.
|
||||
assertTrue(mTimeZoneDetectorInternal.setManualTimeZoneForDpm(timeZoneSuggestion));
|
||||
|
||||
int expectedUserId = mTestCurrentUserIdentityInjector.getCurrentUserId();
|
||||
boolean expectedBypassUserPolicyChecks = true;
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestManualTimeZone(
|
||||
expectedUserId, timeZoneSuggestion, expectedBypassUserPolicyChecks);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestGeolocationTimeZone() throws Exception {
|
||||
GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion();
|
||||
@@ -73,11 +136,28 @@ public class TimeZoneDetectorInternalImplTest {
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestGeolocationTimeZone(timeZoneSuggestion);
|
||||
}
|
||||
private static ManualTimeZoneSuggestion createManualTimeZoneSuggestion() {
|
||||
return new ManualTimeZoneSuggestion(ARBITRARY_ZONE_ID);
|
||||
}
|
||||
|
||||
private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
|
||||
return GeolocationTimeZoneSuggestion.createCertainSuggestion(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_ZONE_IDS);
|
||||
}
|
||||
|
||||
private static ConfigurationInternal createConfigurationInternal(boolean autoDetectionEnabled) {
|
||||
return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
|
||||
.setTelephonyDetectionFeatureSupported(true)
|
||||
.setGeoDetectionFeatureSupported(true)
|
||||
.setTelephonyFallbackSupported(false)
|
||||
.setGeoDetectionRunInBackgroundEnabled(false)
|
||||
.setEnhancedMetricsCollectionEnabled(false)
|
||||
.setUserConfigAllowed(true)
|
||||
.setAutoDetectionEnabledSetting(autoDetectionEnabled)
|
||||
.setLocationEnabledSetting(false)
|
||||
.setGeoDetectionEnabledSetting(false)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.time.ITimeZoneDetectorListener;
|
||||
import android.app.time.TimeZoneCapabilitiesAndConfig;
|
||||
import android.app.time.TimeZoneConfiguration;
|
||||
import android.app.time.TimeZoneState;
|
||||
import android.app.timezonedetector.ManualTimeZoneSuggestion;
|
||||
@@ -67,8 +69,8 @@ public class TimeZoneDetectorServiceTest {
|
||||
private HandlerThread mHandlerThread;
|
||||
private TestHandler mTestHandler;
|
||||
private TestCallerIdentityInjector mTestCallerIdentityInjector;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessor;
|
||||
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
|
||||
private FakeServiceConfigAccessor mFakeServiceConfigAccessorSpy;
|
||||
private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategySpy;
|
||||
|
||||
|
||||
@Before
|
||||
@@ -83,12 +85,12 @@ public class TimeZoneDetectorServiceTest {
|
||||
mTestCallerIdentityInjector = new TestCallerIdentityInjector();
|
||||
mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
|
||||
|
||||
mFakeTimeZoneDetectorStrategy = new FakeTimeZoneDetectorStrategy();
|
||||
mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
|
||||
mFakeServiceConfigAccessorSpy = spy(new FakeServiceConfigAccessor());
|
||||
mFakeTimeZoneDetectorStrategySpy = spy(new FakeTimeZoneDetectorStrategy());
|
||||
|
||||
mTimeZoneDetectorService = new TimeZoneDetectorService(
|
||||
mMockContext, mTestHandler, mTestCallerIdentityInjector,
|
||||
mFakeServiceConfigAccessor, mFakeTimeZoneDetectorStrategy);
|
||||
mFakeServiceConfigAccessorSpy, mFakeTimeZoneDetectorStrategySpy);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -113,13 +115,21 @@ public class TimeZoneDetectorServiceTest {
|
||||
|
||||
ConfigurationInternal configuration =
|
||||
createConfigurationInternal(true /* autoDetectionEnabled*/);
|
||||
mFakeServiceConfigAccessor.initializeConfiguration(configuration);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(configuration);
|
||||
|
||||
assertEquals(configuration.createCapabilitiesAndConfig(),
|
||||
mTimeZoneDetectorService.getCapabilitiesAndConfig());
|
||||
TimeZoneCapabilitiesAndConfig actualCapabilitiesAndConfig =
|
||||
mTimeZoneDetectorService.getCapabilitiesAndConfig();
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
verify(mFakeServiceConfigAccessorSpy).getConfigurationInternal(expectedUserId);
|
||||
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
TimeZoneCapabilitiesAndConfig expectedCapabilitiesAndConfig =
|
||||
configuration.createCapabilitiesAndConfig(expectedBypassUserPolicyChecks);
|
||||
assertEquals(expectedCapabilitiesAndConfig, actualCapabilitiesAndConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -150,7 +160,7 @@ public class TimeZoneDetectorServiceTest {
|
||||
public void testListenerRegistrationAndCallbacks() throws Exception {
|
||||
ConfigurationInternal initialConfiguration =
|
||||
createConfigurationInternal(false /* autoDetectionEnabled */);
|
||||
mFakeServiceConfigAccessor.initializeConfiguration(initialConfiguration);
|
||||
mFakeServiceConfigAccessorSpy.initializeConfiguration(initialConfiguration);
|
||||
|
||||
IBinder mockListenerBinder = mock(IBinder.class);
|
||||
ITimeZoneDetectorListener mockListener = mock(ITimeZoneDetectorListener.class);
|
||||
@@ -222,46 +232,46 @@ public class TimeZoneDetectorServiceTest {
|
||||
@Test
|
||||
public void testSuggestGeolocationTimeZone_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion));
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME_ZONE), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestGeolocationTimeZone() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion();
|
||||
|
||||
mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion);
|
||||
mTestHandler.assertTotalMessagesEnqueued(1);
|
||||
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SET_TIME_ZONE), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestGeolocationTimeZone(timeZoneSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTimeZone_withoutPermission() {
|
||||
doThrow(new SecurityException("Mock"))
|
||||
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
.when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
ManualTimeZoneSuggestion timeZoneSuggestion = createManualTimeZoneSuggestion();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mTimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion));
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuggestManualTimeZone() throws Exception {
|
||||
doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
|
||||
ManualTimeZoneSuggestion timeZoneSuggestion = createManualTimeZoneSuggestion();
|
||||
|
||||
@@ -269,10 +279,12 @@ public class TimeZoneDetectorServiceTest {
|
||||
assertEquals(expectedResult,
|
||||
mTimeZoneDetectorService.suggestManualTimeZone(timeZoneSuggestion));
|
||||
|
||||
mFakeTimeZoneDetectorStrategy.verifySuggestManualTimeZoneCalled(
|
||||
mTestCallerIdentityInjector.getCallingUserId(), timeZoneSuggestion);
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestManualTimeZone(
|
||||
expectedUserId, timeZoneSuggestion, expectedBypassUserPolicyChecks);
|
||||
|
||||
verify(mMockContext).enforceCallingOrSelfPermission(
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE), anyString());
|
||||
}
|
||||
|
||||
@@ -312,20 +324,20 @@ public class TimeZoneDetectorServiceTest {
|
||||
eq(android.Manifest.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE), anyString());
|
||||
|
||||
mTestHandler.waitForMessagesToBeProcessed();
|
||||
mFakeTimeZoneDetectorStrategy.verifySuggestTelephonyTimeZoneCalled(timeZoneSuggestion);
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestTelephonyTimeZone(timeZoneSuggestion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTimeZoneState() {
|
||||
doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
|
||||
TimeZoneState fakeState = new TimeZoneState("Europe/Narnia", true);
|
||||
mFakeTimeZoneDetectorStrategy.setTimeZoneState(fakeState);
|
||||
mFakeTimeZoneDetectorStrategySpy.setTimeZoneState(fakeState);
|
||||
|
||||
TimeZoneState actualState = mTimeZoneDetectorService.getTimeZoneState();
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
assertEquals(actualState, fakeState);
|
||||
assertEquals(fakeState, actualState);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -347,7 +359,7 @@ public class TimeZoneDetectorServiceTest {
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
assertEquals(mFakeTimeZoneDetectorStrategy.getTimeZoneState(), state);
|
||||
assertEquals(state, mFakeTimeZoneDetectorStrategySpy.getTimeZoneState());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -371,7 +383,7 @@ public class TimeZoneDetectorServiceTest {
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
mFakeTimeZoneDetectorStrategy.verifyConfirmTimeZoneCalled("Europe/Narnia");
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).confirmTimeZone("Europe/Narnia");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -396,8 +408,10 @@ public class TimeZoneDetectorServiceTest {
|
||||
mTimeZoneDetectorService.setManualTimeZone(timeZoneSuggestion));
|
||||
|
||||
// The service calls "suggestManualTimeZone()" because the logic is the same.
|
||||
mFakeTimeZoneDetectorStrategy.verifySuggestManualTimeZoneCalled(
|
||||
mTestCallerIdentityInjector.getCallingUserId(), timeZoneSuggestion);
|
||||
int expectedUserId = mTestCallerIdentityInjector.getCallingUserId();
|
||||
boolean expectedBypassUserPolicyChecks = false;
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).suggestManualTimeZone(
|
||||
expectedUserId, timeZoneSuggestion, expectedBypassUserPolicyChecks);
|
||||
|
||||
verify(mMockContext).enforceCallingPermission(
|
||||
eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION), anyString());
|
||||
@@ -427,7 +441,7 @@ public class TimeZoneDetectorServiceTest {
|
||||
mTimeZoneDetectorService.dump(null, pw, null);
|
||||
|
||||
verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
|
||||
mFakeTimeZoneDetectorStrategy.verifyDumpCalled();
|
||||
verify(mFakeTimeZoneDetectorStrategySpy).dump(any(), any());
|
||||
verify(dumpable).dump(any(), any());
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.Qualifie
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
@@ -60,9 +61,13 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import junitparams.JUnitParamsRunner;
|
||||
import junitparams.Parameters;
|
||||
|
||||
/**
|
||||
* White-box unit tests for {@link TimeZoneDetectorStrategyImpl}.
|
||||
*/
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class TimeZoneDetectorStrategyImplTest {
|
||||
|
||||
private static final @UserIdInt int USER_ID = 9876;
|
||||
@@ -561,55 +566,10 @@ public class TimeZoneDetectorStrategyImplTest {
|
||||
.resetConfigurationTracking();
|
||||
|
||||
// Auto time zone detection is enabled so the manual suggestion should be ignored.
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, createManualSuggestion("Europe/Paris"), false /* expectedResult */)
|
||||
.verifyTimeZoneNotChanged();
|
||||
|
||||
assertNull(mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualSuggestion_restricted_simulateAutoTimeZoneEnabled() {
|
||||
Script script = new Script()
|
||||
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(CONFIG_USER_RESTRICTED_AUTO_ENABLED)
|
||||
.resetConfigurationTracking();
|
||||
|
||||
// User is restricted so the manual suggestion should be ignored.
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, createManualSuggestion("Europe/Paris"), false /* expectedResult */)
|
||||
.verifyTimeZoneNotChanged();
|
||||
|
||||
assertNull(mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualSuggestion_unrestricted_autoTimeZoneDetectionDisabled() {
|
||||
Script script = new Script()
|
||||
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED)
|
||||
.resetConfigurationTracking();
|
||||
|
||||
// Auto time zone detection is disabled so the manual suggestion should be used.
|
||||
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, manualSuggestion, true /* expectedResult */)
|
||||
.verifyTimeZoneChangedAndReset(manualSuggestion);
|
||||
|
||||
assertEquals(manualSuggestion, mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManualSuggestion_restricted_autoTimeZoneDetectionDisabled() {
|
||||
Script script = new Script()
|
||||
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(CONFIG_USER_RESTRICTED_AUTO_DISABLED)
|
||||
.resetConfigurationTracking();
|
||||
|
||||
// Restricted users do not have the capability.
|
||||
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, manualSuggestion, false /* expectedResult */)
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = false;
|
||||
script.simulateManualTimeZoneSuggestion(USER_ID, createManualSuggestion("Europe/Paris"),
|
||||
bypassUserPolicyChecks, expectedResult)
|
||||
.verifyTimeZoneNotChanged();
|
||||
|
||||
assertNull(mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
@@ -624,13 +584,63 @@ public class TimeZoneDetectorStrategyImplTest {
|
||||
|
||||
// Unrestricted users have the capability.
|
||||
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, manualSuggestion, true /* expectedResult */)
|
||||
USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifyTimeZoneChangedAndReset(manualSuggestion);
|
||||
|
||||
assertEquals(manualSuggestion, mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void testManualSuggestion_autoTimeEnabled_userRestrictions(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal config =
|
||||
new ConfigurationInternal.Builder(CONFIG_USER_RESTRICTED_AUTO_ENABLED)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.build();
|
||||
Script script = new Script()
|
||||
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(config)
|
||||
.resetConfigurationTracking();
|
||||
|
||||
// User is restricted so the manual suggestion should be ignored.
|
||||
boolean expectedResult = false;
|
||||
script.simulateManualTimeZoneSuggestion(USER_ID, createManualSuggestion("Europe/Paris"),
|
||||
bypassUserPolicyChecks, expectedResult)
|
||||
.verifyTimeZoneNotChanged();
|
||||
|
||||
assertNull(mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameters({ "true,true", "true,false", "false,true", "false,false" })
|
||||
public void testManualSuggestion_autoTimeDisabled_userRestrictions(
|
||||
boolean userConfigAllowed, boolean bypassUserPolicyChecks) {
|
||||
ConfigurationInternal config =
|
||||
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED_GEO_DISABLED)
|
||||
.setUserConfigAllowed(userConfigAllowed)
|
||||
.build();
|
||||
Script script = new Script()
|
||||
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID, TIME_ZONE_CONFIDENCE_LOW)
|
||||
.simulateConfigurationInternalChange(config)
|
||||
.resetConfigurationTracking();
|
||||
|
||||
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
|
||||
boolean expectedResult = userConfigAllowed || bypassUserPolicyChecks;
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult);
|
||||
if (expectedResult) {
|
||||
script.verifyTimeZoneChangedAndReset(manualSuggestion);
|
||||
assertEquals(manualSuggestion, mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
} else {
|
||||
script.verifyTimeZoneNotChanged();
|
||||
assertNull(mTimeZoneDetectorStrategy.getLatestManualSuggestion());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeoSuggestion_uncertain() {
|
||||
Script script = new Script()
|
||||
@@ -1071,8 +1081,10 @@ public class TimeZoneDetectorStrategyImplTest {
|
||||
|
||||
// Make sure the manual suggestion is recorded.
|
||||
ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Zone1");
|
||||
script.simulateManualTimeZoneSuggestion(USER_ID, manualSuggestion,
|
||||
true /* expectedResult */)
|
||||
boolean bypassUserPolicyChecks = false;
|
||||
boolean expectedResult = true;
|
||||
script.simulateManualTimeZoneSuggestion(
|
||||
USER_ID, manualSuggestion, bypassUserPolicyChecks, expectedResult)
|
||||
.verifyTimeZoneChangedAndReset(manualSuggestion);
|
||||
expectedDeviceTimeZoneId = manualSuggestion.getZoneId();
|
||||
assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
|
||||
@@ -1350,9 +1362,9 @@ public class TimeZoneDetectorStrategyImplTest {
|
||||
/** Simulates the time zone detection strategy receiving a user-originated suggestion. */
|
||||
Script simulateManualTimeZoneSuggestion(
|
||||
@UserIdInt int userId, ManualTimeZoneSuggestion manualTimeZoneSuggestion,
|
||||
boolean expectedResult) {
|
||||
boolean bypassUserPolicyChecks, boolean expectedResult) {
|
||||
boolean actualResult = mTimeZoneDetectorStrategy.suggestManualTimeZone(
|
||||
userId, manualTimeZoneSuggestion);
|
||||
userId, manualTimeZoneSuggestion, bypassUserPolicyChecks);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user