summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Neil Fuller <nfuller@google.com> 2022-10-24 17:13:02 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-10-24 17:13:02 +0000
commit153f08e8aed7ae656ae16302d031a6ceb50b6ffd (patch)
tree84e4d49bb81ac1e90da9c85bd6b337b7949e7d44
parent314aec320b26b2f231579dfdb9115974d4f2618a (diff)
parent13c1a5cf4f00f0f80ae017c0cf53ce82a6120530 (diff)
Merge "Changes to support time zone provider status APIs"
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderEvent.java104
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderService.java33
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderStatus.aidl22
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderStatus.java336
-rw-r--r--core/tests/coretests/src/android/service/timezone/TimeZoneProviderEventTest.java102
-rw-r--r--core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java110
-rw-r--r--services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/location/FakeTimeZoneProviderEventPreProcessor.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderTest.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java28
11 files changed, 718 insertions, 77 deletions
diff --git a/core/java/android/service/timezone/TimeZoneProviderEvent.java b/core/java/android/service/timezone/TimeZoneProviderEvent.java
index f6433b7f371e..714afee197f1 100644
--- a/core/java/android/service/timezone/TimeZoneProviderEvent.java
+++ b/core/java/android/service/timezone/TimeZoneProviderEvent.java
@@ -57,7 +57,7 @@ public final class TimeZoneProviderEvent implements Parcelable {
/**
* The provider was uncertain about the time zone. See {@link
- * TimeZoneProviderService#reportUncertain()}
+ * TimeZoneProviderService#reportUncertain(TimeZoneProviderStatus)}
*/
public static final @EventType int EVENT_TYPE_UNCERTAIN = 3;
@@ -66,42 +66,55 @@ public final class TimeZoneProviderEvent implements Parcelable {
@ElapsedRealtimeLong
private final long mCreationElapsedMillis;
+ // Populated when mType == EVENT_TYPE_SUGGESTION
@Nullable
private final TimeZoneProviderSuggestion mSuggestion;
+ // Populated when mType == EVENT_TYPE_PERMANENT_FAILURE
@Nullable
private final String mFailureCause;
- private TimeZoneProviderEvent(@EventType int type,
+ // Populated when mType == EVENT_TYPE_SUGGESTION or EVENT_TYPE_UNCERTAIN
+ @Nullable
+ private final TimeZoneProviderStatus mTimeZoneProviderStatus;
+
+ private TimeZoneProviderEvent(int type,
@ElapsedRealtimeLong long creationElapsedMillis,
@Nullable TimeZoneProviderSuggestion suggestion,
- @Nullable String failureCause) {
+ @Nullable String failureCause,
+ @Nullable TimeZoneProviderStatus timeZoneProviderStatus) {
mType = type;
mCreationElapsedMillis = creationElapsedMillis;
mSuggestion = suggestion;
mFailureCause = failureCause;
+ mTimeZoneProviderStatus = timeZoneProviderStatus;
}
- /** Returns a event of type {@link #EVENT_TYPE_SUGGESTION}. */
+ /** Returns an event of type {@link #EVENT_TYPE_SUGGESTION}. */
public static TimeZoneProviderEvent createSuggestionEvent(
@ElapsedRealtimeLong long creationElapsedMillis,
- @NonNull TimeZoneProviderSuggestion suggestion) {
+ @NonNull TimeZoneProviderSuggestion suggestion,
+ @NonNull TimeZoneProviderStatus providerStatus) {
return new TimeZoneProviderEvent(EVENT_TYPE_SUGGESTION, creationElapsedMillis,
- Objects.requireNonNull(suggestion), null);
+ Objects.requireNonNull(suggestion), null, Objects.requireNonNull(providerStatus));
}
- /** Returns a event of type {@link #EVENT_TYPE_UNCERTAIN}. */
+ /** Returns an event of type {@link #EVENT_TYPE_UNCERTAIN}. */
public static TimeZoneProviderEvent createUncertainEvent(
- @ElapsedRealtimeLong long creationElapsedMillis) {
- return new TimeZoneProviderEvent(EVENT_TYPE_UNCERTAIN, creationElapsedMillis, null, null);
+ @ElapsedRealtimeLong long creationElapsedMillis,
+ @NonNull TimeZoneProviderStatus timeZoneProviderStatus) {
+
+ return new TimeZoneProviderEvent(
+ EVENT_TYPE_UNCERTAIN, creationElapsedMillis, null, null,
+ Objects.requireNonNull(timeZoneProviderStatus));
}
- /** Returns a event of type {@link #EVENT_TYPE_PERMANENT_FAILURE}. */
+ /** Returns an event of type {@link #EVENT_TYPE_PERMANENT_FAILURE}. */
public static TimeZoneProviderEvent createPermanentFailureEvent(
@ElapsedRealtimeLong long creationElapsedMillis,
@NonNull String cause) {
return new TimeZoneProviderEvent(EVENT_TYPE_PERMANENT_FAILURE, creationElapsedMillis, null,
- Objects.requireNonNull(cause));
+ Objects.requireNonNull(cause), null);
}
/**
@@ -126,7 +139,7 @@ public final class TimeZoneProviderEvent implements Parcelable {
}
/**
- * Returns the failure cauese. Populated when {@link #getType()} is {@link
+ * Returns the failure cause. Populated when {@link #getType()} is {@link
* #EVENT_TYPE_PERMANENT_FAILURE}.
*/
@Nullable
@@ -134,24 +147,34 @@ public final class TimeZoneProviderEvent implements Parcelable {
return mFailureCause;
}
- public static final @NonNull Creator<TimeZoneProviderEvent> CREATOR =
- new Creator<TimeZoneProviderEvent>() {
- @Override
- public TimeZoneProviderEvent createFromParcel(Parcel in) {
- int type = in.readInt();
- long creationElapsedMillis = in.readLong();
- TimeZoneProviderSuggestion suggestion =
- in.readParcelable(getClass().getClassLoader(), android.service.timezone.TimeZoneProviderSuggestion.class);
- String failureCause = in.readString8();
- return new TimeZoneProviderEvent(
- type, creationElapsedMillis, suggestion, failureCause);
- }
-
- @Override
- public TimeZoneProviderEvent[] newArray(int size) {
- return new TimeZoneProviderEvent[size];
- }
- };
+ /**
+ * Returns the status of the time zone provider. Populated when {@link #getType()} is {@link
+ * #EVENT_TYPE_UNCERTAIN} or {@link #EVENT_TYPE_SUGGESTION}.
+ */
+ @Nullable
+ public TimeZoneProviderStatus getTimeZoneProviderStatus() {
+ return mTimeZoneProviderStatus;
+ }
+
+ public static final @NonNull Creator<TimeZoneProviderEvent> CREATOR = new Creator<>() {
+ @Override
+ public TimeZoneProviderEvent createFromParcel(Parcel in) {
+ int type = in.readInt();
+ long creationElapsedMillis = in.readLong();
+ TimeZoneProviderSuggestion suggestion = in.readParcelable(
+ getClass().getClassLoader(), TimeZoneProviderSuggestion.class);
+ String failureCause = in.readString8();
+ TimeZoneProviderStatus status = in.readParcelable(
+ getClass().getClassLoader(), TimeZoneProviderStatus.class);
+ return new TimeZoneProviderEvent(
+ type, creationElapsedMillis, suggestion, failureCause, status);
+ }
+
+ @Override
+ public TimeZoneProviderEvent[] newArray(int size) {
+ return new TimeZoneProviderEvent[size];
+ }
+ };
@Override
public int describeContents() {
@@ -164,6 +187,7 @@ public final class TimeZoneProviderEvent implements Parcelable {
parcel.writeLong(mCreationElapsedMillis);
parcel.writeParcelable(mSuggestion, 0);
parcel.writeString8(mFailureCause);
+ parcel.writeParcelable(mTimeZoneProviderStatus, 0);
}
@Override
@@ -173,14 +197,17 @@ public final class TimeZoneProviderEvent implements Parcelable {
+ ", mCreationElapsedMillis=" + Duration.ofMillis(mCreationElapsedMillis).toString()
+ ", mSuggestion=" + mSuggestion
+ ", mFailureCause=" + mFailureCause
+ + ", mTimeZoneProviderStatus=" + mTimeZoneProviderStatus
+ '}';
}
/**
* Similar to {@link #equals} except this methods checks for equivalence, not equality.
- * i.e. two {@link #EVENT_TYPE_UNCERTAIN} and {@link #EVENT_TYPE_PERMANENT_FAILURE} events are
- * always equivalent, two {@link #EVENT_TYPE_SUGGESTION} events are equivalent if they suggest
- * the same time zones.
+ * i.e. two {@link #EVENT_TYPE_SUGGESTION} events are equivalent if they suggest
+ * the same time zones and have the same provider status, two {@link #EVENT_TYPE_UNCERTAIN}
+ * events are equivalent if they have the same provider status, and {@link
+ * #EVENT_TYPE_PERMANENT_FAILURE} events are always equivalent (the nature of the failure is not
+ * considered).
*/
@SuppressWarnings("ReferenceEquality")
public boolean isEquivalentTo(@Nullable TimeZoneProviderEvent other) {
@@ -191,9 +218,10 @@ public final class TimeZoneProviderEvent implements Parcelable {
return false;
}
if (mType == EVENT_TYPE_SUGGESTION) {
- return mSuggestion.isEquivalentTo(other.getSuggestion());
+ return mSuggestion.isEquivalentTo(other.mSuggestion)
+ && Objects.equals(mTimeZoneProviderStatus, other.mTimeZoneProviderStatus);
}
- return true;
+ return Objects.equals(mTimeZoneProviderStatus, other.mTimeZoneProviderStatus);
}
@Override
@@ -208,11 +236,13 @@ public final class TimeZoneProviderEvent implements Parcelable {
return mType == that.mType
&& mCreationElapsedMillis == that.mCreationElapsedMillis
&& Objects.equals(mSuggestion, that.mSuggestion)
- && Objects.equals(mFailureCause, that.mFailureCause);
+ && Objects.equals(mFailureCause, that.mFailureCause)
+ && Objects.equals(mTimeZoneProviderStatus, that.mTimeZoneProviderStatus);
}
@Override
public int hashCode() {
- return Objects.hash(mType, mCreationElapsedMillis, mSuggestion, mFailureCause);
+ return Objects.hash(mType, mCreationElapsedMillis, mSuggestion, mFailureCause,
+ mTimeZoneProviderStatus);
}
}
diff --git a/core/java/android/service/timezone/TimeZoneProviderService.java b/core/java/android/service/timezone/TimeZoneProviderService.java
index 0d215f6d56f1..cd4a30598a9b 100644
--- a/core/java/android/service/timezone/TimeZoneProviderService.java
+++ b/core/java/android/service/timezone/TimeZoneProviderService.java
@@ -203,6 +203,20 @@ public abstract class TimeZoneProviderService extends Service {
* details.
*/
public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion) {
+ reportSuggestion(suggestion, TimeZoneProviderStatus.UNKNOWN);
+ }
+
+ /**
+ * Indicates a successful time zone detection. See {@link TimeZoneProviderSuggestion} for
+ * details.
+ *
+ * @param providerStatus provider status information that can influence detector service
+ * behavior and/or be reported via the device UI
+ *
+ * @hide
+ */
+ public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion,
+ @NonNull TimeZoneProviderStatus providerStatus) {
Objects.requireNonNull(suggestion);
mHandler.post(() -> {
@@ -212,7 +226,7 @@ public abstract class TimeZoneProviderService extends Service {
try {
TimeZoneProviderEvent thisEvent =
TimeZoneProviderEvent.createSuggestionEvent(
- SystemClock.elapsedRealtime(), suggestion);
+ SystemClock.elapsedRealtime(), suggestion, providerStatus);
if (shouldSendEvent(thisEvent)) {
manager.onTimeZoneProviderEvent(thisEvent);
mLastEventSent = thisEvent;
@@ -231,6 +245,21 @@ public abstract class TimeZoneProviderService extends Service {
* to a time zone.
*/
public final void reportUncertain() {
+ reportUncertain(TimeZoneProviderStatus.UNKNOWN);
+ }
+
+ /**
+ * Indicates the time zone is not known because of an expected runtime state or error.
+ *
+ * <p>When the status changes then a certain or uncertain report must be made to move the
+ * detector service to the new status.
+ *
+ * @param providerStatus provider status information that can influence detector service
+ * behavior and/or be reported via the device UI
+ *
+ * @hide
+ */
+ public final void reportUncertain(@NonNull TimeZoneProviderStatus providerStatus) {
mHandler.post(() -> {
synchronized (mLock) {
ITimeZoneProviderManager manager = mManager;
@@ -238,7 +267,7 @@ public abstract class TimeZoneProviderService extends Service {
try {
TimeZoneProviderEvent thisEvent =
TimeZoneProviderEvent.createUncertainEvent(
- SystemClock.elapsedRealtime());
+ SystemClock.elapsedRealtime(), providerStatus);
if (shouldSendEvent(thisEvent)) {
manager.onTimeZoneProviderEvent(thisEvent);
mLastEventSent = thisEvent;
diff --git a/core/java/android/service/timezone/TimeZoneProviderStatus.aidl b/core/java/android/service/timezone/TimeZoneProviderStatus.aidl
new file mode 100644
index 000000000000..91dc7e99fd9a
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderStatus.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 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 android.service.timezone;
+
+/**
+ * @hide
+ */
+parcelable TimeZoneProviderStatus;
diff --git a/core/java/android/service/timezone/TimeZoneProviderStatus.java b/core/java/android/service/timezone/TimeZoneProviderStatus.java
new file mode 100644
index 000000000000..87d7843bacaa
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderStatus.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 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 android.service.timezone;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Objects;
+
+/**
+ * Information about the status of a {@link TimeZoneProviderService}.
+ *
+ * <p>Not all status properties or status values will apply to all provider implementations.
+ * {@code _NOT_APPLICABLE} status can be used to indicate properties that have no meaning for a
+ * given implementation.
+ *
+ * <p>Time zone providers are expected to work in one of two ways:
+ * <ol>
+ * <li>Location: Providers will determine location and then map that location to one or more
+ * time zone IDs.</li>
+ * <li>External signals: Providers could use indirect signals like country code
+ * and/or local offset / DST information provided to the device to infer a time zone, e.g.
+ * signals like MCC and NITZ for telephony devices, IP geo location, or DHCP information
+ * (RFC4833). The time zone ID could also be fed directly to the device by an external service.
+ * </li>
+ * </ol>
+ *
+ * <p>The status properties are:
+ * <ul>
+ * <li>location detection - for location-based providers, the status of the location detection
+ * mechanism</li>
+ * <li>connectivity - connectivity can influence providers directly, for example if they use
+ * a networked service to map location to time zone ID, or use geo IP, or indirectly for
+ * location detection (e.g. for the network location provider.</li>
+ * <li>time zone resolution - the status related to determining a time zone ID or using a
+ * detected time zone ID. For example, a networked service may be reachable (i.e. connectivity
+ * is working) but the service could return errors, a time zone ID detected may not be usable
+ * for a device because of TZDB version skew, or external indirect signals may available but
+ * do not match the properties of a known time zone ID.</li>
+ * </ul>
+ *
+ * @hide
+ */
+public final class TimeZoneProviderStatus implements Parcelable {
+
+ /**
+ * A status code related to a dependency a provider may have.
+ *
+ * @hide
+ */
+ @IntDef(prefix = "DEPENDENCY_STATUS_", value = {
+ DEPENDENCY_STATUS_UNKNOWN,
+ DEPENDENCY_STATUS_NOT_APPLICABLE,
+ DEPENDENCY_STATUS_WORKING,
+ DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE,
+ DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT,
+ DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS,
+ DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS,
+ })
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DependencyStatus {}
+
+ /** The dependency's status is unknown. */
+ 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 used but is temporarily unavailable, e.g. connectivity has been lost for an
+ * unpredictable amount of time.
+ *
+ * <p>This status is considered normal is may be entered many times a day.
+ */
+ public static final @DependencyStatus int DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE = 3;
+
+ /**
+ * The dependency is used by the provider but is blocked by the environment in a way that the
+ * provider has detected and is considered likely to persist for some time, e.g. connectivity
+ * has been lost due to boarding a plane.
+ *
+ * <p>This status is considered unusual and could be used by the system as a trigger to try
+ * other time zone providers / time zone detection mechanisms. The bar for using this status
+ * should therefore be set fairly high to avoid a device bringing up other providers or
+ * switching to a different detection mechanism that may provide a different suggestion.
+ */
+ public static final @DependencyStatus int DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT = 4;
+
+ /**
+ * The dependency is used by the provider but is running in a degraded mode due to the user's
+ * settings. A user can take action to improve this, e.g. by changing a setting.
+ *
+ * <p>This status could be used by the system as a trigger to try other time zone
+ * providers / time zone detection mechanisms. The user may be informed.
+ */
+ public static final @DependencyStatus int DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS = 5;
+
+ /**
+ * The dependency is used by the provider but is completely blocked by the user's settings.
+ * A user can take action to correct this, e.g. by changing a setting.
+ *
+ * <p>This status could be used by the system as a trigger to try other time zone providers /
+ * time zone detection mechanisms. The user may be informed.
+ */
+ public static final @DependencyStatus int DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS = 6;
+
+ /**
+ * A status code related to an operation in a provider's detection algorithm.
+ *
+ * @hide
+ */
+ @IntDef(prefix = "OPERATION_STATUS_", value = {
+ OPERATION_STATUS_UNKNOWN,
+ OPERATION_STATUS_NOT_APPLICABLE,
+ OPERATION_STATUS_WORKING,
+ OPERATION_STATUS_FAILED,
+ })
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OperationStatus {}
+
+ /** The operation's status is unknown. */
+ 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 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 TimeZoneProviderStatus(
+ @DependencyStatus int locationDetectionStatus,
+ @DependencyStatus int connectivityStatus,
+ @OperationStatus int timeZoneResolutionStatus) {
+ mLocationDetectionStatus = requireValidDependencyStatus(locationDetectionStatus);
+ mConnectivityStatus = requireValidDependencyStatus(connectivityStatus);
+ mTimeZoneResolutionStatus = requireValidOperationStatus(timeZoneResolutionStatus);
+ }
+
+ /**
+ * Returns the status of the location detection dependencies used by the provider (where
+ * applicable).
+ */
+ public @DependencyStatus int getLocationDetectionStatus() {
+ return mLocationDetectionStatus;
+ }
+
+ /**
+ * Returns the status of the connectivity dependencies used by the provider (where applicable).
+ */
+ public @DependencyStatus int getConnectivityStatus() {
+ return mConnectivityStatus;
+ }
+
+ /**
+ * Returns the status of the time zone resolution operation used by the provider.
+ */
+ public @OperationStatus int getTimeZoneResolutionStatus() {
+ return mTimeZoneResolutionStatus;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneProviderStatus{"
+ + "mLocationDetectionStatus=" + mLocationDetectionStatus
+ + ", mConnectivityStatus=" + mConnectivityStatus
+ + ", mTimeZoneResolutionStatus=" + mTimeZoneResolutionStatus
+ + '}';
+ }
+
+ public static final @NonNull Creator<TimeZoneProviderStatus> CREATOR = new Creator<>() {
+ @Override
+ public TimeZoneProviderStatus createFromParcel(Parcel in) {
+ @DependencyStatus int locationDetectionStatus = in.readInt();
+ @DependencyStatus int connectivityStatus = in.readInt();
+ @OperationStatus int timeZoneResolutionStatus = in.readInt();
+ return new TimeZoneProviderStatus(
+ locationDetectionStatus, connectivityStatus, timeZoneResolutionStatus);
+ }
+
+ @Override
+ public TimeZoneProviderStatus[] newArray(int size) {
+ return new TimeZoneProviderStatus[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeInt(mLocationDetectionStatus);
+ parcel.writeInt(mConnectivityStatus);
+ parcel.writeInt(mTimeZoneResolutionStatus);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneProviderStatus that = (TimeZoneProviderStatus) o;
+ return mLocationDetectionStatus == that.mLocationDetectionStatus
+ && mConnectivityStatus == that.mConnectivityStatus
+ && mTimeZoneResolutionStatus == that.mTimeZoneResolutionStatus;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mLocationDetectionStatus, mConnectivityStatus, mTimeZoneResolutionStatus);
+ }
+
+ /** 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;
+
+ /**
+ * Creates a new builder instance. At creation time all status properties are set to
+ * their "UNKNOWN" value.
+ */
+ public Builder() {
+ }
+
+ /**
+ * @hide
+ */
+ public Builder(TimeZoneProviderStatus toCopy) {
+ mLocationDetectionStatus = toCopy.mLocationDetectionStatus;
+ mConnectivityStatus = toCopy.mConnectivityStatus;
+ mTimeZoneResolutionStatus = toCopy.mTimeZoneResolutionStatus;
+ }
+
+ /**
+ * Sets the status of the provider's location detection dependency (where applicable).
+ * See the {@code DEPENDENCY_STATUS_} constants for more information.
+ */
+ @NonNull
+ public Builder setLocationDetectionStatus(@DependencyStatus int locationDetectionStatus) {
+ mLocationDetectionStatus = locationDetectionStatus;
+ return this;
+ }
+
+ /**
+ * Sets the status of the provider's connectivity dependency (where applicable).
+ * See the {@code DEPENDENCY_STATUS_} constants for more information.
+ */
+ @NonNull
+ public Builder setConnectivityStatus(@DependencyStatus int connectivityStatus) {
+ mConnectivityStatus = connectivityStatus;
+ return this;
+ }
+
+ /**
+ * Sets the status of the provider's time zone resolution operation.
+ * See the {@code OPERATION_STATUS_} constants for more information.
+ */
+ @NonNull
+ public Builder setTimeZoneResolutionStatus(@OperationStatus int timeZoneResolutionStatus) {
+ mTimeZoneResolutionStatus = timeZoneResolutionStatus;
+ return this;
+ }
+
+ /**
+ * Builds a {@link TimeZoneProviderStatus} instance.
+ */
+ @NonNull
+ public TimeZoneProviderStatus build() {
+ return new TimeZoneProviderStatus(
+ mLocationDetectionStatus, mConnectivityStatus, mTimeZoneResolutionStatus);
+ }
+ }
+
+ private @OperationStatus int requireValidOperationStatus(@OperationStatus int operationStatus) {
+ if (operationStatus < OPERATION_STATUS_UNKNOWN
+ || operationStatus > OPERATION_STATUS_FAILED) {
+ throw new IllegalArgumentException(Integer.toString(operationStatus));
+ }
+ return operationStatus;
+ }
+
+ private static @DependencyStatus int requireValidDependencyStatus(
+ @DependencyStatus int dependencyStatus) {
+ if (dependencyStatus < DEPENDENCY_STATUS_UNKNOWN
+ || dependencyStatus > DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS) {
+ throw new IllegalArgumentException(Integer.toString(dependencyStatus));
+ }
+ return dependencyStatus;
+ }
+}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderEventTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderEventTest.java
index c8de190b30b0..ab63f1475f83 100644
--- a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderEventTest.java
+++ b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderEventTest.java
@@ -17,6 +17,9 @@
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.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -33,6 +36,32 @@ public class TimeZoneProviderEventTest {
@Test
public void isEquivalentToAndEquals() {
+ long creationElapsedMillis = 1111L;
+ TimeZoneProviderEvent failEvent =
+ TimeZoneProviderEvent.createPermanentFailureEvent(creationElapsedMillis, "one");
+ TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
+
+ TimeZoneProviderEvent uncertainEvent =
+ TimeZoneProviderEvent.createUncertainEvent(creationElapsedMillis, providerStatus);
+ TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(creationElapsedMillis)
+ .setTimeZoneIds(Collections.singletonList("Europe/London"))
+ .build();
+ TimeZoneProviderEvent suggestionEvent = TimeZoneProviderEvent.createSuggestionEvent(
+ creationElapsedMillis, suggestion, providerStatus);
+
+ assertNotEquals(failEvent, uncertainEvent);
+ assertNotEquivalentTo(failEvent, uncertainEvent);
+
+ assertNotEquals(failEvent, suggestionEvent);
+ assertNotEquivalentTo(failEvent, suggestionEvent);
+
+ assertNotEquals(uncertainEvent, suggestionEvent);
+ assertNotEquivalentTo(uncertainEvent, suggestionEvent);
+ }
+
+ @Test
+ public void isEquivalentToAndEquals_permanentFailure() {
TimeZoneProviderEvent fail1v1 =
TimeZoneProviderEvent.createPermanentFailureEvent(1111L, "one");
assertEquals(fail1v1, fail1v1);
@@ -51,44 +80,79 @@ public class TimeZoneProviderEventTest {
assertNotEquals(fail1v1, fail2);
assertIsEquivalentTo(fail1v1, fail2);
}
+ }
+
+ @Test
+ public void isEquivalentToAndEquals_uncertain() {
+ TimeZoneProviderStatus status1 = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
+ .build();
+ TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
- TimeZoneProviderEvent uncertain1v1 = TimeZoneProviderEvent.createUncertainEvent(1111L);
+ TimeZoneProviderEvent uncertain1v1 =
+ TimeZoneProviderEvent.createUncertainEvent(1111L, status1);
assertEquals(uncertain1v1, uncertain1v1);
assertIsEquivalentTo(uncertain1v1, uncertain1v1);
assertNotEquals(uncertain1v1, null);
assertNotEquivalentTo(uncertain1v1, null);
{
- TimeZoneProviderEvent uncertain1v2 = TimeZoneProviderEvent.createUncertainEvent(1111L);
+ TimeZoneProviderEvent uncertain1v2 =
+ TimeZoneProviderEvent.createUncertainEvent(1111L, status1);
assertEquals(uncertain1v1, uncertain1v2);
assertIsEquivalentTo(uncertain1v1, uncertain1v2);
- TimeZoneProviderEvent uncertain2 = TimeZoneProviderEvent.createUncertainEvent(2222L);
+ TimeZoneProviderEvent uncertain2 =
+ TimeZoneProviderEvent.createUncertainEvent(2222L, status1);
assertNotEquals(uncertain1v1, uncertain2);
assertIsEquivalentTo(uncertain1v1, uncertain2);
+
+ TimeZoneProviderEvent uncertain3 =
+ TimeZoneProviderEvent.createUncertainEvent(1111L, status2);
+ assertNotEquals(uncertain1v1, uncertain3);
+ assertNotEquivalentTo(uncertain1v1, uncertain3);
}
+ }
+ @Test
+ public void isEquivalentToAndEquals_suggestion() {
+ TimeZoneProviderStatus status1 = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
+ .build();
+ TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
TimeZoneProviderSuggestion suggestion1 = new TimeZoneProviderSuggestion.Builder()
.setElapsedRealtimeMillis(1111L)
.setTimeZoneIds(Collections.singletonList("Europe/London"))
.build();
TimeZoneProviderEvent certain1v1 =
- TimeZoneProviderEvent.createSuggestionEvent(1111L, suggestion1);
+ TimeZoneProviderEvent.createSuggestionEvent(1111L, suggestion1, status1);
assertEquals(certain1v1, certain1v1);
assertIsEquivalentTo(certain1v1, certain1v1);
assertNotEquals(certain1v1, null);
assertNotEquivalentTo(certain1v1, null);
{
- // Same suggestion, same time.
+ // Same time, suggestion, and status.
TimeZoneProviderEvent certain1v2 =
- TimeZoneProviderEvent.createSuggestionEvent(1111L, suggestion1);
+ TimeZoneProviderEvent.createSuggestionEvent(1111L, suggestion1, status1);
assertEquals(certain1v1, certain1v2);
assertIsEquivalentTo(certain1v1, certain1v2);
- // Same suggestion, different time.
+ // Different time, same suggestion and status.
TimeZoneProviderEvent certain1v3 =
- TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion1);
+ TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion1, status1);
assertNotEquals(certain1v1, certain1v3);
assertIsEquivalentTo(certain1v1, certain1v3);
@@ -100,7 +164,7 @@ public class TimeZoneProviderEventTest {
assertNotEquals(suggestion1, suggestion2);
TimeZoneProviderSuggestionTest.assertIsEquivalentTo(suggestion1, suggestion2);
TimeZoneProviderEvent certain2 =
- TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion2);
+ TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion2, status1);
assertNotEquals(certain1v1, certain2);
assertIsEquivalentTo(certain1v1, certain2);
@@ -109,16 +173,15 @@ public class TimeZoneProviderEventTest {
.setTimeZoneIds(Collections.singletonList("Europe/Paris"))
.build();
TimeZoneProviderEvent certain3 =
- TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion3);
+ TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion3, status1);
assertNotEquals(certain1v1, certain3);
assertNotEquivalentTo(certain1v1, certain3);
- }
- assertNotEquals(fail1v1, uncertain1v1);
- assertNotEquivalentTo(fail1v1, uncertain1v1);
-
- assertNotEquals(fail1v1, certain1v1);
- assertNotEquivalentTo(fail1v1, certain1v1);
+ TimeZoneProviderEvent certain4 =
+ TimeZoneProviderEvent.createSuggestionEvent(2222L, suggestion1, status2);
+ assertNotEquals(certain1v1, certain4);
+ assertNotEquivalentTo(certain1v1, certain4);
+ }
}
@Test
@@ -130,7 +193,8 @@ public class TimeZoneProviderEventTest {
@Test
public void testParcelable_uncertain() {
- TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(1111L);
+ TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(
+ 1111L, TimeZoneProviderStatus.UNKNOWN);
assertRoundTripParcelable(event);
}
@@ -139,8 +203,8 @@ public class TimeZoneProviderEventTest {
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
.setTimeZoneIds(Arrays.asList("Europe/London", "Europe/Paris"))
.build();
- TimeZoneProviderEvent event =
- TimeZoneProviderEvent.createSuggestionEvent(1111L, suggestion);
+ TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
+ 1111L, suggestion, TimeZoneProviderStatus.UNKNOWN);
assertRoundTripParcelable(event);
}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java
new file mode 100644
index 000000000000..d61c33c935db
--- /dev/null
+++ b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderStatusTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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.OPERATION_STATUS_FAILED;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+
+public class TimeZoneProviderStatusTest {
+
+ @Test
+ public void testStatusValidation() {
+ TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(DEPENDENCY_STATUS_WORKING)
+ .build();
+
+ assertThrows(IllegalArgumentException.class,
+ () -> new TimeZoneProviderStatus.Builder(status)
+ .setLocationDetectionStatus(-1)
+ .build());
+ assertThrows(IllegalArgumentException.class,
+ () -> new TimeZoneProviderStatus.Builder(status)
+ .setConnectivityStatus(-1)
+ .build());
+ assertThrows(IllegalArgumentException.class,
+ () -> new TimeZoneProviderStatus.Builder(status)
+ .setTimeZoneResolutionStatus(-1)
+ .build());
+ }
+
+ @Test
+ public void testEqualsAndHashcode() {
+ TimeZoneProviderStatus status1_1 = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
+ .build();
+ assertEqualsAndHashcode(status1_1, status1_1);
+ assertNotEquals(status1_1, null);
+
+ {
+ TimeZoneProviderStatus status1_2 =
+ new TimeZoneProviderStatus.Builder(status1_1).build();
+ assertEqualsAndHashcode(status1_1, status1_2);
+ assertNotSame(status1_1, status1_2);
+ }
+
+ {
+ TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
+ .build();
+ assertNotEquals(status1_1, status2);
+ }
+
+ {
+ TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
+ .setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
+ .build();
+ assertNotEquals(status1_1, status2);
+ }
+
+ {
+ TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
+ assertNotEquals(status1_1, status2);
+ }
+ }
+
+ private static void assertEqualsAndHashcode(Object one, Object two) {
+ assertEquals(one, two);
+ assertEquals(two, one);
+ assertEquals(one.hashCode(), two.hashCode());
+ }
+
+ @Test
+ public void testParcelable() {
+ TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
+ .setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
+ .setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
+ assertRoundTripParcelable(status);
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java b/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java
index ff0529f35057..8a6f92750501 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessor.java
@@ -16,10 +16,13 @@
package com.android.server.timezonedetector.location;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
+
import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.infoLog;
import android.annotation.NonNull;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderStatus;
import com.android.i18n.timezone.ZoneInfoDb;
@@ -53,7 +56,12 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessor
// enables immediate failover to a secondary provider, one that might provide valid IDs for
// the same location, which should provide better behavior than just ignoring the event.
if (hasInvalidZones(event)) {
- return TimeZoneProviderEvent.createUncertainEvent(event.getCreationElapsedMillis());
+ TimeZoneProviderStatus providerStatus = new TimeZoneProviderStatus.Builder(
+ event.getTimeZoneProviderStatus())
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
+ return TimeZoneProviderEvent.createUncertainEvent(
+ event.getCreationElapsedMillis(), providerStatus);
}
return event;
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/FakeTimeZoneProviderEventPreProcessor.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/FakeTimeZoneProviderEventPreProcessor.java
index 52e9d3a06fe2..34d008201bb2 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/FakeTimeZoneProviderEventPreProcessor.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/FakeTimeZoneProviderEventPreProcessor.java
@@ -17,6 +17,7 @@
package com.android.server.timezonedetector.location;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderStatus;
/**
* Fake implementation of {@link TimeZoneProviderEventPreProcessor} which assumes that all events
@@ -31,7 +32,8 @@ public final class FakeTimeZoneProviderEventPreProcessor
public TimeZoneProviderEvent preProcess(TimeZoneProviderEvent timeZoneProviderEvent) {
if (mIsUncertain) {
return TimeZoneProviderEvent.createUncertainEvent(
- timeZoneProviderEvent.getCreationElapsedMillis());
+ timeZoneProviderEvent.getCreationElapsedMillis(),
+ TimeZoneProviderStatus.UNKNOWN);
}
return timeZoneProviderEvent;
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index 0257ce0fe7b9..ed426cdc9f7e 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -15,6 +15,12 @@
*/
package com.android.server.timezonedetector.location;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_NOT_APPLICABLE;
+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_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;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
@@ -48,6 +54,7 @@ import android.annotation.Nullable;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderStatus;
import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
@@ -78,8 +85,15 @@ public class LocationTimeZoneProviderControllerTest {
createSuggestionEvent(asList("Europe/London"));
private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
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)
+ .build();
private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
- TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_TIME_MILLIS);
+ TimeZoneProviderEvent.createUncertainEvent(
+ ARBITRARY_TIME_MILLIS, UNCERTAIN_PROVIDER_STATUS);
private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test");
@@ -1390,12 +1404,17 @@ 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)
+ .build();
+ TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+ .setTimeZoneIds(timeZoneIds)
+ .build();
return TimeZoneProviderEvent.createSuggestionEvent(
- ARBITRARY_TIME_MILLIS,
- new TimeZoneProviderSuggestion.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
- .setTimeZoneIds(timeZoneIds)
- .build());
+ ARBITRARY_TIME_MILLIS, suggestion, providerStatus);
}
private static void assertControllerState(LocationTimeZoneProviderController controller,
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderTest.java
index cb2905d2266a..8429fa4d18d1 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderTest.java
@@ -33,6 +33,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.platform.test.annotations.Presubmit;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderStatus;
import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
@@ -120,8 +121,9 @@ public class LocationTimeZoneProviderTest {
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
.setTimeZoneIds(Arrays.asList("Europe/London"))
.build();
+ TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
- ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion);
+ ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, providerStatus);
provider.simulateProviderEventReceived(event);
currentState = assertAndReturnProviderState(
@@ -133,7 +135,8 @@ public class LocationTimeZoneProviderTest {
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_CERTAIN);
// Simulate an uncertain event being received.
- event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+ event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
+ TimeZoneProviderStatus.UNKNOWN);
provider.simulateProviderEventReceived(event);
currentState = assertAndReturnProviderState(
@@ -193,12 +196,13 @@ public class LocationTimeZoneProviderTest {
.setTimeZoneIds(Arrays.asList("Europe/London"))
.build();
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
- ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion);
+ ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, TimeZoneProviderStatus.UNKNOWN);
provider.simulateProviderEventReceived(event);
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_CERTAIN);
// Simulate an uncertain event being received.
- event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+ event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
+ TimeZoneProviderStatus.UNKNOWN);
provider.simulateProviderEventReceived(event);
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_UNCERTAIN);
@@ -235,8 +239,9 @@ public class LocationTimeZoneProviderTest {
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
.setTimeZoneIds(invalidTimeZoneIds)
.build();
+ TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
- ARBITRARY_ELAPSED_REALTIME_MILLIS, invalidIdSuggestion);
+ ARBITRARY_ELAPSED_REALTIME_MILLIS, invalidIdSuggestion, providerStatus);
provider.simulateProviderEventReceived(event);
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_UNCERTAIN);
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java
index ab4fe2938bcf..c4786043cc29 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/ZoneInfoDbTimeZoneProviderEventPreProcessorTest.java
@@ -16,10 +16,15 @@
package com.android.server.timezonedetector.location;
+import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
+import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
+
import static com.google.common.truth.Truth.assertWithMessage;
import android.platform.test.annotations.Presubmit;
import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderStatus;
import android.service.timezone.TimeZoneProviderSuggestion;
import org.junit.Test;
@@ -54,8 +59,14 @@ public class ZoneInfoDbTimeZoneProviderEventPreProcessorTest {
for (String timeZone : nonExistingTimeZones) {
TimeZoneProviderEvent event = timeZoneProviderEvent(timeZone);
+ TimeZoneProviderStatus expectedProviderStatus =
+ new TimeZoneProviderStatus.Builder(event.getTimeZoneProviderStatus())
+ .setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
+ .build();
+
TimeZoneProviderEvent expectedResultEvent =
- TimeZoneProviderEvent.createUncertainEvent(event.getCreationElapsedMillis());
+ TimeZoneProviderEvent.createUncertainEvent(
+ event.getCreationElapsedMillis(), expectedProviderStatus);
assertWithMessage(timeZone + " is not a valid time zone")
.that(mPreProcessor.preProcess(event))
.isEqualTo(expectedResultEvent);
@@ -63,12 +74,17 @@ 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)
+ .build();
+ TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
+ .setTimeZoneIds(Arrays.asList(timeZoneIds))
+ .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+ .build();
return TimeZoneProviderEvent.createSuggestionEvent(
- ARBITRARY_TIME_MILLIS,
- new TimeZoneProviderSuggestion.Builder()
- .setTimeZoneIds(Arrays.asList(timeZoneIds))
- .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
- .build());
+ ARBITRARY_TIME_MILLIS, suggestion, providerStatus);
}
}