diff options
author | 2022-10-24 17:13:02 +0000 | |
---|---|---|
committer | 2022-10-24 17:13:02 +0000 | |
commit | 153f08e8aed7ae656ae16302d031a6ceb50b6ffd (patch) | |
tree | 84e4d49bb81ac1e90da9c85bd6b337b7949e7d44 | |
parent | 314aec320b26b2f231579dfdb9115974d4f2618a (diff) | |
parent | 13c1a5cf4f00f0f80ae017c0cf53ce82a6120530 (diff) |
Merge "Changes to support time zone provider status APIs"
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); } } |