Merge "Tidy up changes before API change"
This commit is contained in:
committed by
Android (Google) Code Review
commit
ca1f1e2934
@@ -74,39 +74,53 @@ public final class TimeZoneProviderEvent implements Parcelable {
|
||||
@Nullable
|
||||
private final String mFailureCause;
|
||||
|
||||
// Populated when mType == EVENT_TYPE_SUGGESTION or EVENT_TYPE_UNCERTAIN
|
||||
// May be populated when EVENT_TYPE_SUGGESTION or EVENT_TYPE_UNCERTAIN
|
||||
@Nullable
|
||||
private final TimeZoneProviderStatus mTimeZoneProviderStatus;
|
||||
|
||||
private TimeZoneProviderEvent(int type,
|
||||
private TimeZoneProviderEvent(@EventType int type,
|
||||
@ElapsedRealtimeLong long creationElapsedMillis,
|
||||
@Nullable TimeZoneProviderSuggestion suggestion,
|
||||
@Nullable String failureCause,
|
||||
@Nullable TimeZoneProviderStatus timeZoneProviderStatus) {
|
||||
mType = type;
|
||||
mType = validateEventType(type);
|
||||
mCreationElapsedMillis = creationElapsedMillis;
|
||||
mSuggestion = suggestion;
|
||||
mFailureCause = failureCause;
|
||||
mTimeZoneProviderStatus = timeZoneProviderStatus;
|
||||
|
||||
// Confirm the type and the provider status agree.
|
||||
if (mType == EVENT_TYPE_PERMANENT_FAILURE && mTimeZoneProviderStatus != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected status: mType=" + mType
|
||||
+ ", mTimeZoneProviderStatus=" + mTimeZoneProviderStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private static @EventType int validateEventType(@EventType int eventType) {
|
||||
if (eventType < EVENT_TYPE_PERMANENT_FAILURE || eventType > EVENT_TYPE_UNCERTAIN) {
|
||||
throw new IllegalArgumentException(Integer.toString(eventType));
|
||||
}
|
||||
return eventType;
|
||||
}
|
||||
|
||||
/** Returns an event of type {@link #EVENT_TYPE_SUGGESTION}. */
|
||||
public static TimeZoneProviderEvent createSuggestionEvent(
|
||||
@ElapsedRealtimeLong long creationElapsedMillis,
|
||||
@NonNull TimeZoneProviderSuggestion suggestion,
|
||||
@NonNull TimeZoneProviderStatus providerStatus) {
|
||||
@Nullable TimeZoneProviderStatus providerStatus) {
|
||||
return new TimeZoneProviderEvent(EVENT_TYPE_SUGGESTION, creationElapsedMillis,
|
||||
Objects.requireNonNull(suggestion), null, Objects.requireNonNull(providerStatus));
|
||||
Objects.requireNonNull(suggestion), null, providerStatus);
|
||||
}
|
||||
|
||||
/** Returns an event of type {@link #EVENT_TYPE_UNCERTAIN}. */
|
||||
public static TimeZoneProviderEvent createUncertainEvent(
|
||||
@ElapsedRealtimeLong long creationElapsedMillis,
|
||||
@NonNull TimeZoneProviderStatus timeZoneProviderStatus) {
|
||||
@Nullable TimeZoneProviderStatus timeZoneProviderStatus) {
|
||||
|
||||
return new TimeZoneProviderEvent(
|
||||
EVENT_TYPE_UNCERTAIN, creationElapsedMillis, null, null,
|
||||
Objects.requireNonNull(timeZoneProviderStatus));
|
||||
timeZoneProviderStatus);
|
||||
}
|
||||
|
||||
/** Returns an event of type {@link #EVENT_TYPE_PERMANENT_FAILURE}. */
|
||||
@@ -148,8 +162,8 @@ public final class TimeZoneProviderEvent implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the time zone provider. Populated when {@link #getType()} is {@link
|
||||
* #EVENT_TYPE_UNCERTAIN} or {@link #EVENT_TYPE_SUGGESTION}.
|
||||
* Returns the status of the time zone provider. May be populated when {@link #getType()} is
|
||||
* {@link #EVENT_TYPE_UNCERTAIN} or {@link #EVENT_TYPE_SUGGESTION}, otherwise {@code null}.
|
||||
*/
|
||||
@Nullable
|
||||
public TimeZoneProviderStatus getTimeZoneProviderStatus() {
|
||||
|
||||
@@ -203,7 +203,8 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
* details.
|
||||
*/
|
||||
public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion) {
|
||||
reportSuggestion(suggestion, TimeZoneProviderStatus.UNKNOWN);
|
||||
TimeZoneProviderStatus providerStatus = null;
|
||||
reportSuggestionInternal(suggestion, providerStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,6 +218,12 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
*/
|
||||
public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion,
|
||||
@NonNull TimeZoneProviderStatus providerStatus) {
|
||||
Objects.requireNonNull(providerStatus);
|
||||
reportSuggestionInternal(suggestion, providerStatus);
|
||||
}
|
||||
|
||||
private void reportSuggestionInternal(@NonNull TimeZoneProviderSuggestion suggestion,
|
||||
@Nullable TimeZoneProviderStatus providerStatus) {
|
||||
Objects.requireNonNull(suggestion);
|
||||
|
||||
mHandler.post(() -> {
|
||||
@@ -245,7 +252,8 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
* to a time zone.
|
||||
*/
|
||||
public final void reportUncertain() {
|
||||
reportUncertain(TimeZoneProviderStatus.UNKNOWN);
|
||||
TimeZoneProviderStatus providerStatus = null;
|
||||
reportUncertainInternal(providerStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,6 +268,11 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
* @hide
|
||||
*/
|
||||
public final void reportUncertain(@NonNull TimeZoneProviderStatus providerStatus) {
|
||||
Objects.requireNonNull(providerStatus);
|
||||
reportUncertainInternal(providerStatus);
|
||||
}
|
||||
|
||||
private void reportUncertainInternal(@Nullable TimeZoneProviderStatus providerStatus) {
|
||||
mHandler.post(() -> {
|
||||
synchronized (mLock) {
|
||||
ITimeZoneProviderManager manager = mManager;
|
||||
|
||||
@@ -18,14 +18,18 @@ package android.service.timezone;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Information about the status of a {@link TimeZoneProviderService}.
|
||||
@@ -71,7 +75,7 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
@IntDef(prefix = "DEPENDENCY_STATUS_", value = {
|
||||
DEPENDENCY_STATUS_UNKNOWN,
|
||||
DEPENDENCY_STATUS_NOT_APPLICABLE,
|
||||
DEPENDENCY_STATUS_WORKING,
|
||||
DEPENDENCY_STATUS_OK,
|
||||
DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE,
|
||||
DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT,
|
||||
DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS,
|
||||
@@ -81,14 +85,18 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface DependencyStatus {}
|
||||
|
||||
/** The dependency's status is unknown. */
|
||||
/**
|
||||
* The dependency's status is unknown.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final @DependencyStatus int DEPENDENCY_STATUS_UNKNOWN = 0;
|
||||
|
||||
/** The dependency is not used by the provider's implementation. */
|
||||
public static final @DependencyStatus int DEPENDENCY_STATUS_NOT_APPLICABLE = 1;
|
||||
|
||||
/** The dependency is applicable and working well. */
|
||||
public static final @DependencyStatus int DEPENDENCY_STATUS_WORKING = 2;
|
||||
/** The dependency is applicable and there are no known problems. */
|
||||
public static final @DependencyStatus int DEPENDENCY_STATUS_OK = 2;
|
||||
|
||||
/**
|
||||
* The dependency is used but is temporarily unavailable, e.g. connectivity has been lost for an
|
||||
@@ -136,76 +144,105 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
@IntDef(prefix = "OPERATION_STATUS_", value = {
|
||||
OPERATION_STATUS_UNKNOWN,
|
||||
OPERATION_STATUS_NOT_APPLICABLE,
|
||||
OPERATION_STATUS_WORKING,
|
||||
OPERATION_STATUS_OK,
|
||||
OPERATION_STATUS_FAILED,
|
||||
})
|
||||
@Target(ElementType.TYPE_USE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface OperationStatus {}
|
||||
|
||||
/** The operation's status is unknown. */
|
||||
/**
|
||||
* The operation's status is unknown.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final @OperationStatus int OPERATION_STATUS_UNKNOWN = 0;
|
||||
|
||||
/** The operation is not used by the provider's implementation. */
|
||||
public static final @OperationStatus int OPERATION_STATUS_NOT_APPLICABLE = 1;
|
||||
|
||||
/** The operation is applicable and working well. */
|
||||
public static final @OperationStatus int OPERATION_STATUS_WORKING = 2;
|
||||
/** The operation is applicable and there are no known problems. */
|
||||
public static final @OperationStatus int OPERATION_STATUS_OK = 2;
|
||||
|
||||
/** The operation is applicable and failed. */
|
||||
/** The operation is applicable and it recently failed. */
|
||||
public static final @OperationStatus int OPERATION_STATUS_FAILED = 3;
|
||||
|
||||
/**
|
||||
* An instance that provides no information about status. Effectively a "null" status.
|
||||
*/
|
||||
@NonNull
|
||||
public static final TimeZoneProviderStatus UNKNOWN = new TimeZoneProviderStatus(
|
||||
DEPENDENCY_STATUS_UNKNOWN, DEPENDENCY_STATUS_UNKNOWN, OPERATION_STATUS_UNKNOWN);
|
||||
|
||||
private final @DependencyStatus int mLocationDetectionStatus;
|
||||
private final @DependencyStatus int mConnectivityStatus;
|
||||
private final @OperationStatus int mTimeZoneResolutionStatus;
|
||||
private final @DependencyStatus int mLocationDetectionDependencyStatus;
|
||||
private final @DependencyStatus int mConnectivityDependencyStatus;
|
||||
private final @OperationStatus int mTimeZoneResolutionOperationStatus;
|
||||
|
||||
private TimeZoneProviderStatus(
|
||||
@DependencyStatus int locationDetectionStatus,
|
||||
@DependencyStatus int connectivityStatus,
|
||||
@OperationStatus int timeZoneResolutionStatus) {
|
||||
mLocationDetectionStatus = requireValidDependencyStatus(locationDetectionStatus);
|
||||
mConnectivityStatus = requireValidDependencyStatus(connectivityStatus);
|
||||
mTimeZoneResolutionStatus = requireValidOperationStatus(timeZoneResolutionStatus);
|
||||
mLocationDetectionDependencyStatus = locationDetectionStatus;
|
||||
mConnectivityDependencyStatus = connectivityStatus;
|
||||
mTimeZoneResolutionOperationStatus = timeZoneResolutionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the location detection dependencies used by the provider (where
|
||||
* applicable).
|
||||
*/
|
||||
public @DependencyStatus int getLocationDetectionStatus() {
|
||||
return mLocationDetectionStatus;
|
||||
public @DependencyStatus int getLocationDetectionDependencyStatus() {
|
||||
return mLocationDetectionDependencyStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the connectivity dependencies used by the provider (where applicable).
|
||||
*/
|
||||
public @DependencyStatus int getConnectivityStatus() {
|
||||
return mConnectivityStatus;
|
||||
public @DependencyStatus int getConnectivityDependencyStatus() {
|
||||
return mConnectivityDependencyStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the time zone resolution operation used by the provider.
|
||||
*/
|
||||
public @OperationStatus int getTimeZoneResolutionStatus() {
|
||||
return mTimeZoneResolutionStatus;
|
||||
public @OperationStatus int getTimeZoneResolutionOperationStatus() {
|
||||
return mTimeZoneResolutionOperationStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeZoneProviderStatus{"
|
||||
+ "mLocationDetectionStatus=" + mLocationDetectionStatus
|
||||
+ ", mConnectivityStatus=" + mConnectivityStatus
|
||||
+ ", mTimeZoneResolutionStatus=" + mTimeZoneResolutionStatus
|
||||
+ "mLocationDetectionDependencyStatus="
|
||||
+ dependencyStatusToString(mLocationDetectionDependencyStatus)
|
||||
+ ", mConnectivityDependencyStatus="
|
||||
+ dependencyStatusToString(mConnectivityDependencyStatus)
|
||||
+ ", mTimeZoneResolutionOperationStatus="
|
||||
+ operationStatusToString(mTimeZoneResolutionOperationStatus)
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a {@link TimeZoneProviderStatus} from a toString() string for manual command-line
|
||||
* testing.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public static TimeZoneProviderStatus parseProviderStatus(@NonNull String arg) {
|
||||
// Note: "}" has to be escaped on Android with "\\}" because the regexp library is not based
|
||||
// on OpenJDK code.
|
||||
Pattern pattern = Pattern.compile("TimeZoneProviderStatus\\{"
|
||||
+ "mLocationDetectionDependencyStatus=([^,]+)"
|
||||
+ ", mConnectivityDependencyStatus=([^,]+)"
|
||||
+ ", mTimeZoneResolutionOperationStatus=([^\\}]+)"
|
||||
+ "\\}");
|
||||
Matcher matcher = pattern.matcher(arg);
|
||||
if (!matcher.matches()) {
|
||||
throw new IllegalArgumentException("Unable to parse provider status: " + arg);
|
||||
}
|
||||
@DependencyStatus int locationDependencyStatus =
|
||||
dependencyStatusFromString(matcher.group(1));
|
||||
@DependencyStatus int connectivityDependencyStatus =
|
||||
dependencyStatusFromString(matcher.group(2));
|
||||
@OperationStatus int timeZoneResolutionOperationStatus =
|
||||
operationStatusFromString(matcher.group(3));
|
||||
return new TimeZoneProviderStatus(locationDependencyStatus, connectivityDependencyStatus,
|
||||
timeZoneResolutionOperationStatus);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<TimeZoneProviderStatus> CREATOR = new Creator<>() {
|
||||
@Override
|
||||
public TimeZoneProviderStatus createFromParcel(Parcel in) {
|
||||
@@ -229,9 +266,9 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel parcel, int flags) {
|
||||
parcel.writeInt(mLocationDetectionStatus);
|
||||
parcel.writeInt(mConnectivityStatus);
|
||||
parcel.writeInt(mTimeZoneResolutionStatus);
|
||||
parcel.writeInt(mLocationDetectionDependencyStatus);
|
||||
parcel.writeInt(mConnectivityDependencyStatus);
|
||||
parcel.writeInt(mTimeZoneResolutionOperationStatus);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,23 +280,33 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
TimeZoneProviderStatus that = (TimeZoneProviderStatus) o;
|
||||
return mLocationDetectionStatus == that.mLocationDetectionStatus
|
||||
&& mConnectivityStatus == that.mConnectivityStatus
|
||||
&& mTimeZoneResolutionStatus == that.mTimeZoneResolutionStatus;
|
||||
return mLocationDetectionDependencyStatus == that.mLocationDetectionDependencyStatus
|
||||
&& mConnectivityDependencyStatus == that.mConnectivityDependencyStatus
|
||||
&& mTimeZoneResolutionOperationStatus == that.mTimeZoneResolutionOperationStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
mLocationDetectionStatus, mConnectivityStatus, mTimeZoneResolutionStatus);
|
||||
mLocationDetectionDependencyStatus, mConnectivityDependencyStatus,
|
||||
mTimeZoneResolutionOperationStatus);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean couldEnableTelephonyFallback() {
|
||||
return mLocationDetectionDependencyStatus == DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT
|
||||
|| mLocationDetectionDependencyStatus == DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS
|
||||
|| mConnectivityDependencyStatus == DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT
|
||||
|| mConnectivityDependencyStatus == DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
|
||||
}
|
||||
|
||||
/** A builder for {@link TimeZoneProviderStatus}. */
|
||||
public static final class Builder {
|
||||
|
||||
private @DependencyStatus int mLocationDetectionStatus = DEPENDENCY_STATUS_UNKNOWN;
|
||||
private @DependencyStatus int mConnectivityStatus = DEPENDENCY_STATUS_UNKNOWN;
|
||||
private @OperationStatus int mTimeZoneResolutionStatus = OPERATION_STATUS_UNKNOWN;
|
||||
private @DependencyStatus int mLocationDetectionDependencyStatus =
|
||||
DEPENDENCY_STATUS_UNKNOWN;
|
||||
private @DependencyStatus int mConnectivityDependencyStatus = DEPENDENCY_STATUS_UNKNOWN;
|
||||
private @OperationStatus int mTimeZoneResolutionOperationStatus = OPERATION_STATUS_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Creates a new builder instance. At creation time all status properties are set to
|
||||
@@ -272,9 +319,9 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public Builder(TimeZoneProviderStatus toCopy) {
|
||||
mLocationDetectionStatus = toCopy.mLocationDetectionStatus;
|
||||
mConnectivityStatus = toCopy.mConnectivityStatus;
|
||||
mTimeZoneResolutionStatus = toCopy.mTimeZoneResolutionStatus;
|
||||
mLocationDetectionDependencyStatus = toCopy.mLocationDetectionDependencyStatus;
|
||||
mConnectivityDependencyStatus = toCopy.mConnectivityDependencyStatus;
|
||||
mTimeZoneResolutionOperationStatus = toCopy.mTimeZoneResolutionOperationStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,8 +329,9 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
* See the {@code DEPENDENCY_STATUS_} constants for more information.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setLocationDetectionStatus(@DependencyStatus int locationDetectionStatus) {
|
||||
mLocationDetectionStatus = locationDetectionStatus;
|
||||
public Builder setLocationDetectionDependencyStatus(
|
||||
@DependencyStatus int locationDetectionStatus) {
|
||||
mLocationDetectionDependencyStatus = locationDetectionStatus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -292,8 +340,8 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
* See the {@code DEPENDENCY_STATUS_} constants for more information.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setConnectivityStatus(@DependencyStatus int connectivityStatus) {
|
||||
mConnectivityStatus = connectivityStatus;
|
||||
public Builder setConnectivityDependencyStatus(@DependencyStatus int connectivityStatus) {
|
||||
mConnectivityDependencyStatus = connectivityStatus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -302,8 +350,9 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
* See the {@code OPERATION_STATUS_} constants for more information.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setTimeZoneResolutionStatus(@OperationStatus int timeZoneResolutionStatus) {
|
||||
mTimeZoneResolutionStatus = timeZoneResolutionStatus;
|
||||
public Builder setTimeZoneResolutionOperationStatus(
|
||||
@OperationStatus int timeZoneResolutionStatus) {
|
||||
mTimeZoneResolutionOperationStatus = timeZoneResolutionStatus;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -313,11 +362,14 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
@NonNull
|
||||
public TimeZoneProviderStatus build() {
|
||||
return new TimeZoneProviderStatus(
|
||||
mLocationDetectionStatus, mConnectivityStatus, mTimeZoneResolutionStatus);
|
||||
requireValidDependencyStatus(mLocationDetectionDependencyStatus),
|
||||
requireValidDependencyStatus(mConnectivityDependencyStatus),
|
||||
requireValidOperationStatus(mTimeZoneResolutionOperationStatus));
|
||||
}
|
||||
}
|
||||
|
||||
private @OperationStatus int requireValidOperationStatus(@OperationStatus int operationStatus) {
|
||||
private static @OperationStatus int requireValidOperationStatus(
|
||||
@OperationStatus int operationStatus) {
|
||||
if (operationStatus < OPERATION_STATUS_UNKNOWN
|
||||
|| operationStatus > OPERATION_STATUS_FAILED) {
|
||||
throw new IllegalArgumentException(Integer.toString(operationStatus));
|
||||
@@ -325,6 +377,45 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
return operationStatus;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@NonNull
|
||||
public static String operationStatusToString(@OperationStatus int operationStatus) {
|
||||
switch (operationStatus) {
|
||||
case OPERATION_STATUS_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case OPERATION_STATUS_NOT_APPLICABLE:
|
||||
return "NOT_APPLICABLE";
|
||||
case OPERATION_STATUS_OK:
|
||||
return "OK";
|
||||
case OPERATION_STATUS_FAILED:
|
||||
return "FAILED";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown status: " + operationStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static @OperationStatus int operationStatusFromString(
|
||||
@Nullable String operationStatusString) {
|
||||
|
||||
if (TextUtils.isEmpty(operationStatusString)) {
|
||||
throw new IllegalArgumentException("Empty status: " + operationStatusString);
|
||||
}
|
||||
|
||||
switch (operationStatusString) {
|
||||
case "UNKNOWN":
|
||||
return OPERATION_STATUS_UNKNOWN;
|
||||
case "NOT_APPLICABLE":
|
||||
return OPERATION_STATUS_NOT_APPLICABLE;
|
||||
case "OK":
|
||||
return OPERATION_STATUS_OK;
|
||||
case "FAILED":
|
||||
return OPERATION_STATUS_FAILED;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown status: " + operationStatusString);
|
||||
}
|
||||
}
|
||||
|
||||
private static @DependencyStatus int requireValidDependencyStatus(
|
||||
@DependencyStatus int dependencyStatus) {
|
||||
if (dependencyStatus < DEPENDENCY_STATUS_UNKNOWN
|
||||
@@ -333,4 +424,56 @@ public final class TimeZoneProviderStatus implements Parcelable {
|
||||
}
|
||||
return dependencyStatus;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@NonNull
|
||||
public static String dependencyStatusToString(@DependencyStatus int dependencyStatus) {
|
||||
switch (dependencyStatus) {
|
||||
case DEPENDENCY_STATUS_UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case DEPENDENCY_STATUS_NOT_APPLICABLE:
|
||||
return "NOT_APPLICABLE";
|
||||
case DEPENDENCY_STATUS_OK:
|
||||
return "OK";
|
||||
case DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE:
|
||||
return "TEMPORARILY_UNAVAILABLE";
|
||||
case DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT:
|
||||
return "BLOCKED_BY_ENVIRONMENT";
|
||||
case DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS:
|
||||
return "DEGRADED_BY_SETTINGS";
|
||||
case DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS:
|
||||
return "BLOCKED_BY_SETTINGS";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown status: " + dependencyStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static @DependencyStatus int dependencyStatusFromString(
|
||||
@Nullable String dependencyStatusString) {
|
||||
|
||||
if (TextUtils.isEmpty(dependencyStatusString)) {
|
||||
throw new IllegalArgumentException("Empty status: " + dependencyStatusString);
|
||||
}
|
||||
|
||||
switch (dependencyStatusString) {
|
||||
case "UNKNOWN":
|
||||
return DEPENDENCY_STATUS_UNKNOWN;
|
||||
case "NOT_APPLICABLE":
|
||||
return DEPENDENCY_STATUS_NOT_APPLICABLE;
|
||||
case "OK":
|
||||
return DEPENDENCY_STATUS_OK;
|
||||
case "TEMPORARILY_UNAVAILABLE":
|
||||
return DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE;
|
||||
case "BLOCKED_BY_ENVIRONMENT":
|
||||
return DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
|
||||
case "DEGRADED_BY_SETTINGS":
|
||||
return DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS;
|
||||
case "BLOCKED_BY_SETTINGS":
|
||||
return DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown status: " + dependencyStatusString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@
|
||||
package android.service.timezone;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
|
||||
import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
|
||||
import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -34,12 +39,92 @@ import java.util.Collections;
|
||||
|
||||
public class TimeZoneProviderEventTest {
|
||||
|
||||
public static final TimeZoneProviderStatus ARBITRARY_TIME_ZONE_PROVIDER_STATUS =
|
||||
new TimeZoneProviderStatus.Builder()
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
public void createPermanentFailure() {
|
||||
long creationElapsedMillis = 1111L;
|
||||
String cause = "Cause";
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createPermanentFailureEvent(
|
||||
creationElapsedMillis, cause);
|
||||
|
||||
assertEquals(EVENT_TYPE_PERMANENT_FAILURE, event.getType());
|
||||
assertEquals(cause, event.getFailureCause());
|
||||
assertEquals(creationElapsedMillis, event.getCreationElapsedMillis());
|
||||
assertNull(event.getSuggestion());
|
||||
assertNull(event.getTimeZoneProviderStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSuggestion() {
|
||||
long creationElapsedMillis = 1111L;
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setElapsedRealtimeMillis(2222L)
|
||||
.setTimeZoneIds(Collections.singletonList("Europe/London"))
|
||||
.build();
|
||||
|
||||
TimeZoneProviderStatus reportedStatus = new TimeZoneProviderStatus.Builder()
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
assertThrows(NullPointerException.class, () -> TimeZoneProviderEvent.createSuggestionEvent(
|
||||
creationElapsedMillis, /*suggestion=*/null, reportedStatus));
|
||||
|
||||
// Only TimeZoneProvider can report itself certain.
|
||||
{
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
creationElapsedMillis, suggestion, reportedStatus);
|
||||
assertEquals(EVENT_TYPE_SUGGESTION, event.getType());
|
||||
assertEquals(creationElapsedMillis, event.getCreationElapsedMillis());
|
||||
assertNull(event.getFailureCause());
|
||||
assertEquals(suggestion, event.getSuggestion());
|
||||
}
|
||||
|
||||
// Legacy API events can be created where the TimeZoneProviderStatus is omitted.
|
||||
{
|
||||
TimeZoneProviderStatus legacyStatus = null;
|
||||
TimeZoneProviderEvent legacyEvent = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
creationElapsedMillis, suggestion, legacyStatus);
|
||||
assertEquals(legacyStatus, legacyEvent.getTimeZoneProviderStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createUncertain() {
|
||||
long creationElapsedMillis = 1111L;
|
||||
|
||||
// The TimeZoneProvider can report itself uncertain.
|
||||
{
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(
|
||||
creationElapsedMillis, ARBITRARY_TIME_ZONE_PROVIDER_STATUS);
|
||||
assertEquals(EVENT_TYPE_UNCERTAIN, event.getType());
|
||||
assertEquals(creationElapsedMillis, event.getCreationElapsedMillis());
|
||||
assertNull(event.getFailureCause());
|
||||
assertNull(event.getSuggestion());
|
||||
}
|
||||
|
||||
// Legacy API events can be created where the TimeZoneProviderStatus is omitted.
|
||||
{
|
||||
TimeZoneProviderStatus legacyStatus = null;
|
||||
TimeZoneProviderEvent legacyEvent = TimeZoneProviderEvent.createUncertainEvent(
|
||||
creationElapsedMillis, legacyStatus);
|
||||
assertEquals(legacyStatus, legacyEvent.getTimeZoneProviderStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEquivalentToAndEquals() {
|
||||
long creationElapsedMillis = 1111L;
|
||||
TimeZoneProviderEvent failEvent =
|
||||
TimeZoneProviderEvent.createPermanentFailureEvent(creationElapsedMillis, "one");
|
||||
TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
|
||||
TimeZoneProviderStatus providerStatus = ARBITRARY_TIME_ZONE_PROVIDER_STATUS;
|
||||
|
||||
TimeZoneProviderEvent uncertainEvent =
|
||||
TimeZoneProviderEvent.createUncertainEvent(creationElapsedMillis, providerStatus);
|
||||
@@ -85,14 +170,14 @@ public class TimeZoneProviderEventTest {
|
||||
@Test
|
||||
public void isEquivalentToAndEquals_uncertain() {
|
||||
TimeZoneProviderStatus status1 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
|
||||
TimeZoneProviderEvent uncertain1v1 =
|
||||
@@ -123,14 +208,14 @@ public class TimeZoneProviderEventTest {
|
||||
@Test
|
||||
public void isEquivalentToAndEquals_suggestion() {
|
||||
TimeZoneProviderStatus status1 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
TimeZoneProviderSuggestion suggestion1 = new TimeZoneProviderSuggestion.Builder()
|
||||
.setElapsedRealtimeMillis(1111L)
|
||||
@@ -194,7 +279,13 @@ public class TimeZoneProviderEventTest {
|
||||
@Test
|
||||
public void testParcelable_uncertain() {
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(
|
||||
1111L, TimeZoneProviderStatus.UNKNOWN);
|
||||
1111L, ARBITRARY_TIME_ZONE_PROVIDER_STATUS);
|
||||
assertRoundTripParcelable(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelable_uncertain_legacy() {
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(1111L, null);
|
||||
assertRoundTripParcelable(event);
|
||||
}
|
||||
|
||||
@@ -204,7 +295,17 @@ public class TimeZoneProviderEventTest {
|
||||
.setTimeZoneIds(Arrays.asList("Europe/London", "Europe/Paris"))
|
||||
.build();
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
1111L, suggestion, TimeZoneProviderStatus.UNKNOWN);
|
||||
1111L, suggestion, ARBITRARY_TIME_ZONE_PROVIDER_STATUS);
|
||||
assertRoundTripParcelable(event);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelable_suggestion_legacy() {
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setTimeZoneIds(Arrays.asList("Europe/London", "Europe/Paris"))
|
||||
.build();
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
1111L, suggestion, null);
|
||||
assertRoundTripParcelable(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@ package android.service.timezone;
|
||||
|
||||
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
@@ -31,34 +32,45 @@ import org.junit.Test;
|
||||
|
||||
public class TimeZoneProviderStatusTest {
|
||||
|
||||
@Test
|
||||
public void parseProviderStatus() {
|
||||
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
assertEquals(status, TimeZoneProviderStatus.parseProviderStatus(status.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusValidation() {
|
||||
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setLocationDetectionStatus(-1)
|
||||
.setLocationDetectionDependencyStatus(-1)
|
||||
.build());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setConnectivityStatus(-1)
|
||||
.setConnectivityDependencyStatus(-1)
|
||||
.build());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setTimeZoneResolutionStatus(-1)
|
||||
.setTimeZoneResolutionOperationStatus(-1)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashcode() {
|
||||
TimeZoneProviderStatus status1_1 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
assertEqualsAndHashcode(status1_1, status1_1);
|
||||
assertNotEquals(status1_1, null);
|
||||
@@ -72,21 +84,21 @@ public class TimeZoneProviderStatusTest {
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
@@ -101,9 +113,9 @@ public class TimeZoneProviderStatusTest {
|
||||
@Test
|
||||
public void testParcelable() {
|
||||
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
assertRoundTripParcelable(status);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.annotation.Nullable;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.service.timezone.TimeZoneProviderEvent;
|
||||
import android.service.timezone.TimeZoneProviderStatus;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -294,6 +295,12 @@ abstract class LocationTimeZoneProvider implements Dumpable {
|
||||
|| stateEnum == PROVIDER_STATE_DESTROYED;
|
||||
}
|
||||
|
||||
/** Returns the status reported by the provider, if available. */
|
||||
@Nullable
|
||||
TimeZoneProviderStatus getReportedStatus() {
|
||||
return event == null ? null : event.getTimeZoneProviderStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// this.provider is omitted deliberately to avoid recursion, since the provider holds
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessor
|
||||
if (hasInvalidZones(event)) {
|
||||
TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder(
|
||||
event.getTimeZoneProviderStatus())
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
return TimeZoneProviderEvent.createUncertainEvent(
|
||||
event.getCreationElapsedMillis(), providerStatus);
|
||||
|
||||
@@ -31,9 +31,9 @@ public final class FakeTimeZoneProviderEventPreProcessor
|
||||
@Override
|
||||
public TimeZoneProviderEvent preProcess(TimeZoneProviderEvent timeZoneProviderEvent) {
|
||||
if (mIsUncertain) {
|
||||
TimeZoneProviderStatus timeZoneProviderStatus = null;
|
||||
return TimeZoneProviderEvent.createUncertainEvent(
|
||||
timeZoneProviderEvent.getCreationElapsedMillis(),
|
||||
TimeZoneProviderStatus.UNKNOWN);
|
||||
timeZoneProviderEvent.getCreationElapsedMillis(), timeZoneProviderStatus);
|
||||
}
|
||||
return timeZoneProviderEvent;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
package com.android.server.timezonedetector.location;
|
||||
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_NOT_APPLICABLE;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_UNKNOWN;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
|
||||
|
||||
import static com.android.server.timezonedetector.ConfigurationInternal.DETECTION_MODE_MANUAL;
|
||||
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
|
||||
@@ -87,9 +87,9 @@ public class LocationTimeZoneProviderControllerTest {
|
||||
createSuggestionEvent(asList("Europe/Paris"));
|
||||
private static final TimeZoneProviderStatus UNCERTAIN_PROVIDER_STATUS =
|
||||
new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_UNKNOWN)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_UNKNOWN)
|
||||
.build();
|
||||
private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
|
||||
TimeZoneProviderEvent.createUncertainEvent(
|
||||
@@ -1405,9 +1405,9 @@ public class LocationTimeZoneProviderControllerTest {
|
||||
|
||||
private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) {
|
||||
TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_NOT_APPLICABLE)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.android.server.timezonedetector.location;
|
||||
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
|
||||
|
||||
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
|
||||
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
|
||||
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
|
||||
@@ -57,6 +60,12 @@ import java.util.List;
|
||||
public class LocationTimeZoneProviderTest {
|
||||
|
||||
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 123456789L;
|
||||
private static final TimeZoneProviderStatus ARBITRARY_PROVIDER_STATUS =
|
||||
new TimeZoneProviderStatus.Builder()
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
private TestThreadingDomain mTestThreadingDomain;
|
||||
private TestProviderListener mProviderListener;
|
||||
@@ -80,91 +89,108 @@ public class LocationTimeZoneProviderTest {
|
||||
mTimeZoneProviderEventPreProcessor);
|
||||
|
||||
// initialize()
|
||||
provider.initialize(mProviderListener);
|
||||
provider.assertOnInitializeCalled();
|
||||
{
|
||||
provider.initialize(mProviderListener);
|
||||
provider.assertOnInitializeCalled();
|
||||
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED);
|
||||
assertNull(currentState.currentUserConfiguration);
|
||||
assertSame(provider, currentState.provider);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED,
|
||||
/*expectedReportedStatus=*/null);
|
||||
assertNull(currentState.currentUserConfiguration);
|
||||
assertSame(provider, currentState.provider);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
}
|
||||
|
||||
ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
|
||||
|
||||
// startUpdates()
|
||||
ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
|
||||
Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
|
||||
Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
|
||||
Duration arbitraryEventFilteringAgeThreshold = Duration.ofMinutes(3);
|
||||
provider.startUpdates(config, arbitraryInitializationTimeout,
|
||||
arbitraryInitializationTimeoutFuzz, arbitraryEventFilteringAgeThreshold);
|
||||
{
|
||||
Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
|
||||
Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
|
||||
Duration arbitraryEventFilteringAgeThreshold = Duration.ofMinutes(3);
|
||||
provider.startUpdates(config, arbitraryInitializationTimeout,
|
||||
arbitraryInitializationTimeoutFuzz, arbitraryEventFilteringAgeThreshold);
|
||||
|
||||
provider.assertOnStartCalled(
|
||||
arbitraryInitializationTimeout, arbitraryEventFilteringAgeThreshold);
|
||||
provider.assertOnStartCalled(
|
||||
arbitraryInitializationTimeout, arbitraryEventFilteringAgeThreshold);
|
||||
|
||||
currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_INITIALIZING);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
assertNull(currentState.event);
|
||||
// The initialization timeout should be queued.
|
||||
Duration expectedInitializationTimeout =
|
||||
arbitraryInitializationTimeout.plus(arbitraryInitializationTimeoutFuzz);
|
||||
mTestThreadingDomain.assertSingleDelayedQueueItem(expectedInitializationTimeout);
|
||||
// We don't intend to trigger the timeout, so clear it.
|
||||
mTestThreadingDomain.removeAllQueuedRunnables();
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_INITIALIZING,
|
||||
/*expectedReportedStatus=*/null);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
assertNull(currentState.event);
|
||||
// The initialization timeout should be queued.
|
||||
Duration expectedInitializationTimeout =
|
||||
arbitraryInitializationTimeout.plus(arbitraryInitializationTimeoutFuzz);
|
||||
mTestThreadingDomain.assertSingleDelayedQueueItem(expectedInitializationTimeout);
|
||||
// We don't intend to trigger the timeout, so clear it.
|
||||
mTestThreadingDomain.removeAllQueuedRunnables();
|
||||
|
||||
// Entering started does not trigger an onProviderStateChanged() as it is requested by the
|
||||
// controller.
|
||||
mProviderListener.assertProviderChangeNotReported();
|
||||
// Entering started does not trigger an onProviderStateChanged() as it is requested by
|
||||
// the controller.
|
||||
mProviderListener.assertProviderChangeNotReported();
|
||||
}
|
||||
|
||||
// Simulate a suggestion event being received.
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
|
||||
.setTimeZoneIds(Arrays.asList("Europe/London"))
|
||||
.build();
|
||||
TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, providerStatus);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
{
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
|
||||
.setTimeZoneIds(Arrays.asList("Europe/London"))
|
||||
.build();
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, ARBITRARY_PROVIDER_STATUS);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
|
||||
currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_CERTAIN);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(event, currentState.event);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_CERTAIN);
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_CERTAIN,
|
||||
ARBITRARY_PROVIDER_STATUS);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(event, currentState.event);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_CERTAIN);
|
||||
}
|
||||
|
||||
// Simulate an uncertain event being received.
|
||||
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
|
||||
TimeZoneProviderStatus.UNKNOWN);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
{
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_PROVIDER_STATUS);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
|
||||
currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_UNCERTAIN);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(event, currentState.event);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_UNCERTAIN);
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_UNCERTAIN,
|
||||
ARBITRARY_PROVIDER_STATUS);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(event, currentState.event);
|
||||
assertEquals(config, currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_UNCERTAIN);
|
||||
}
|
||||
|
||||
// stopUpdates()
|
||||
provider.stopUpdates();
|
||||
provider.assertOnStopUpdatesCalled();
|
||||
{
|
||||
provider.stopUpdates();
|
||||
provider.assertOnStopUpdatesCalled();
|
||||
|
||||
currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
|
||||
assertNull(currentState.event);
|
||||
assertNull(currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
// Entering stopped does not trigger an onProviderStateChanged() as it is requested by the
|
||||
// controller.
|
||||
mProviderListener.assertProviderChangeNotReported();
|
||||
ProviderState currentState = assertAndReturnProviderState(
|
||||
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED,
|
||||
/*expectedReportedStatus=*/null);
|
||||
assertSame(provider, currentState.provider);
|
||||
assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
|
||||
assertNull(currentState.event);
|
||||
assertNull(currentState.currentUserConfiguration);
|
||||
mTestThreadingDomain.assertQueueEmpty();
|
||||
// Entering stopped does not trigger an onProviderStateChanged() as it is requested by
|
||||
// the controller.
|
||||
mProviderListener.assertProviderChangeNotReported();
|
||||
}
|
||||
|
||||
// destroy()
|
||||
provider.destroy();
|
||||
provider.assertOnDestroyCalled();
|
||||
{
|
||||
provider.destroy();
|
||||
provider.assertOnDestroyCalled();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -196,13 +222,12 @@ public class LocationTimeZoneProviderTest {
|
||||
.setTimeZoneIds(Arrays.asList("Europe/London"))
|
||||
.build();
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, TimeZoneProviderStatus.UNKNOWN);
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, null);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_CERTAIN);
|
||||
|
||||
// Simulate an uncertain event being received.
|
||||
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
|
||||
TimeZoneProviderStatus.UNKNOWN);
|
||||
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS, null);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_UNCERTAIN);
|
||||
|
||||
@@ -239,7 +264,7 @@ public class LocationTimeZoneProviderTest {
|
||||
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
|
||||
.setTimeZoneIds(invalidTimeZoneIds)
|
||||
.build();
|
||||
TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
|
||||
TimeZoneProviderStatus providerStatus = null;
|
||||
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
|
||||
ARBITRARY_ELAPSED_REALTIME_MILLIS, invalidIdSuggestion, providerStatus);
|
||||
provider.simulateProviderEventReceived(event);
|
||||
@@ -275,9 +300,11 @@ public class LocationTimeZoneProviderTest {
|
||||
*/
|
||||
private static ProviderState assertAndReturnProviderState(
|
||||
TestLocationTimeZoneProvider provider,
|
||||
RecordingProviderMetricsLogger providerMetricsLogger, int expectedStateEnum) {
|
||||
RecordingProviderMetricsLogger providerMetricsLogger, int expectedStateEnum,
|
||||
TimeZoneProviderStatus expectedReportedStatus) {
|
||||
ProviderState currentState = provider.getCurrentState();
|
||||
assertEquals(expectedStateEnum, currentState.stateEnum);
|
||||
assertEquals(expectedReportedStatus, currentState.getReportedStatus());
|
||||
providerMetricsLogger.assertChangeLoggedAndRemove(expectedStateEnum);
|
||||
providerMetricsLogger.assertNoMoreLogEntries();
|
||||
return currentState;
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package com.android.server.timezonedetector.location;
|
||||
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
@@ -61,7 +61,7 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest {
|
||||
|
||||
TimeZoneProviderStatus expectedProviderStatus =
|
||||
new TimeZoneProviderStatus.Builder(event.getTimeZoneProviderStatus())
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
|
||||
TimeZoneProviderEvent expectedResultEvent =
|
||||
@@ -75,9 +75,9 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest {
|
||||
|
||||
private static TimeZoneProviderEvent timeZoneProviderEvent(String... timeZoneIds) {
|
||||
TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
|
||||
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
|
||||
.setTimeZoneIds(Arrays.asList(timeZoneIds))
|
||||
|
||||
Reference in New Issue
Block a user