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