Merge "Tidy up changes before API change"

This commit is contained in:
TreeHugger Robot
2022-11-08 21:05:24 +00:00
committed by Android (Google) Code Review
11 changed files with 504 additions and 187 deletions

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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);
}
}
}

View File

@@ -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);
}

View File

@@ -18,9 +18,10 @@ package android.service.timezone;
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_WORKING;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_FAILED;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_WORKING;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -31,34 +32,45 @@ import org.junit.Test;
public class TimeZoneProviderStatusTest {
@Test
public void parseProviderStatus() {
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
.build();
assertEquals(status, TimeZoneProviderStatus.parseProviderStatus(status.toString()));
}
@Test
public void testStatusValidation() {
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
.setTimeZoneResolutionStatus(DEPENDENCY_STATUS_WORKING)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
.build();
assertThrows(IllegalArgumentException.class,
() -> new TimeZoneProviderStatus.Builder(status)
.setLocationDetectionStatus(-1)
.setLocationDetectionDependencyStatus(-1)
.build());
assertThrows(IllegalArgumentException.class,
() -> new TimeZoneProviderStatus.Builder(status)
.setConnectivityStatus(-1)
.setConnectivityDependencyStatus(-1)
.build());
assertThrows(IllegalArgumentException.class,
() -> new TimeZoneProviderStatus.Builder(status)
.setTimeZoneResolutionStatus(-1)
.setTimeZoneResolutionOperationStatus(-1)
.build());
}
@Test
public void testEqualsAndHashcode() {
TimeZoneProviderStatus status1_1 = new TimeZoneProviderStatus.Builder()
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
.setConnectivityStatus(DEPENDENCY_STATUS_WORKING)
.setTimeZoneResolutionStatus(OPERATION_STATUS_WORKING)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
.build();
assertEqualsAndHashcode(status1_1, status1_1);
assertNotEquals(status1_1, null);
@@ -72,21 +84,21 @@ public class TimeZoneProviderStatusTest {
{
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
.setLocationDetectionStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.build();
assertNotEquals(status1_1, status2);
}
{
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
.setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.build();
assertNotEquals(status1_1, status2);
}
{
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
.build();
assertNotEquals(status1_1, status2);
}
@@ -101,9 +113,9 @@ public class TimeZoneProviderStatusTest {
@Test
public void testParcelable() {
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
.setLocationDetectionStatus(DEPENDENCY_STATUS_WORKING)
.setConnectivityStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.setTimeZoneResolutionStatus(OPERATION_STATUS_FAILED)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
.build();
assertRoundTripParcelable(status);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -15,6 +15,9 @@
*/
package com.android.server.timezonedetector.location;
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_OK;
import static android.service.timezone.TimeZoneProviderStatus.OPERATION_STATUS_OK;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
@@ -57,6 +60,12 @@ import java.util.List;
public class LocationTimeZoneProviderTest {
private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 123456789L;
private static final TimeZoneProviderStatus ARBITRARY_PROVIDER_STATUS =
new TimeZoneProviderStatus.Builder()
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
.build();
private TestThreadingDomain mTestThreadingDomain;
private TestProviderListener mProviderListener;
@@ -80,91 +89,108 @@ public class LocationTimeZoneProviderTest {
mTimeZoneProviderEventPreProcessor);
// initialize()
provider.initialize(mProviderListener);
provider.assertOnInitializeCalled();
{
provider.initialize(mProviderListener);
provider.assertOnInitializeCalled();
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED);
assertNull(currentState.currentUserConfiguration);
assertSame(provider, currentState.provider);
mTestThreadingDomain.assertQueueEmpty();
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED,
/*expectedReportedStatus=*/null);
assertNull(currentState.currentUserConfiguration);
assertSame(provider, currentState.provider);
mTestThreadingDomain.assertQueueEmpty();
}
ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
// startUpdates()
ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
Duration arbitraryEventFilteringAgeThreshold = Duration.ofMinutes(3);
provider.startUpdates(config, arbitraryInitializationTimeout,
arbitraryInitializationTimeoutFuzz, arbitraryEventFilteringAgeThreshold);
{
Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
Duration arbitraryEventFilteringAgeThreshold = Duration.ofMinutes(3);
provider.startUpdates(config, arbitraryInitializationTimeout,
arbitraryInitializationTimeoutFuzz, arbitraryEventFilteringAgeThreshold);
provider.assertOnStartCalled(
arbitraryInitializationTimeout, arbitraryEventFilteringAgeThreshold);
provider.assertOnStartCalled(
arbitraryInitializationTimeout, arbitraryEventFilteringAgeThreshold);
currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_INITIALIZING);
assertSame(provider, currentState.provider);
assertEquals(config, currentState.currentUserConfiguration);
assertNull(currentState.event);
// The initialization timeout should be queued.
Duration expectedInitializationTimeout =
arbitraryInitializationTimeout.plus(arbitraryInitializationTimeoutFuzz);
mTestThreadingDomain.assertSingleDelayedQueueItem(expectedInitializationTimeout);
// We don't intend to trigger the timeout, so clear it.
mTestThreadingDomain.removeAllQueuedRunnables();
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_INITIALIZING,
/*expectedReportedStatus=*/null);
assertSame(provider, currentState.provider);
assertEquals(config, currentState.currentUserConfiguration);
assertNull(currentState.event);
// The initialization timeout should be queued.
Duration expectedInitializationTimeout =
arbitraryInitializationTimeout.plus(arbitraryInitializationTimeoutFuzz);
mTestThreadingDomain.assertSingleDelayedQueueItem(expectedInitializationTimeout);
// We don't intend to trigger the timeout, so clear it.
mTestThreadingDomain.removeAllQueuedRunnables();
// Entering started does not trigger an onProviderStateChanged() as it is requested by the
// controller.
mProviderListener.assertProviderChangeNotReported();
// Entering started does not trigger an onProviderStateChanged() as it is requested by
// the controller.
mProviderListener.assertProviderChangeNotReported();
}
// Simulate a suggestion event being received.
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
.setTimeZoneIds(Arrays.asList("Europe/London"))
.build();
TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, providerStatus);
provider.simulateProviderEventReceived(event);
{
TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
.setTimeZoneIds(Arrays.asList("Europe/London"))
.build();
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, ARBITRARY_PROVIDER_STATUS);
provider.simulateProviderEventReceived(event);
currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_CERTAIN);
assertSame(provider, currentState.provider);
assertEquals(event, currentState.event);
assertEquals(config, currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_CERTAIN);
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_CERTAIN,
ARBITRARY_PROVIDER_STATUS);
assertSame(provider, currentState.provider);
assertEquals(event, currentState.event);
assertEquals(config, currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_CERTAIN);
}
// Simulate an uncertain event being received.
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
TimeZoneProviderStatus.UNKNOWN);
provider.simulateProviderEventReceived(event);
{
TimeZoneProviderEvent event = TimeZoneProviderEvent.createUncertainEvent(
ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_PROVIDER_STATUS);
provider.simulateProviderEventReceived(event);
currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_UNCERTAIN);
assertSame(provider, currentState.provider);
assertEquals(event, currentState.event);
assertEquals(config, currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_UNCERTAIN);
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STARTED_UNCERTAIN,
ARBITRARY_PROVIDER_STATUS);
assertSame(provider, currentState.provider);
assertEquals(event, currentState.event);
assertEquals(config, currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
mProviderListener.assertProviderChangeReported(PROVIDER_STATE_STARTED_UNCERTAIN);
}
// stopUpdates()
provider.stopUpdates();
provider.assertOnStopUpdatesCalled();
{
provider.stopUpdates();
provider.assertOnStopUpdatesCalled();
currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED);
assertSame(provider, currentState.provider);
assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
assertNull(currentState.event);
assertNull(currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
// Entering stopped does not trigger an onProviderStateChanged() as it is requested by the
// controller.
mProviderListener.assertProviderChangeNotReported();
ProviderState currentState = assertAndReturnProviderState(
provider, providerMetricsLogger, PROVIDER_STATE_STOPPED,
/*expectedReportedStatus=*/null);
assertSame(provider, currentState.provider);
assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
assertNull(currentState.event);
assertNull(currentState.currentUserConfiguration);
mTestThreadingDomain.assertQueueEmpty();
// Entering stopped does not trigger an onProviderStateChanged() as it is requested by
// the controller.
mProviderListener.assertProviderChangeNotReported();
}
// destroy()
provider.destroy();
provider.assertOnDestroyCalled();
{
provider.destroy();
provider.assertOnDestroyCalled();
}
}
@Test
@@ -196,13 +222,12 @@ public class LocationTimeZoneProviderTest {
.setTimeZoneIds(Arrays.asList("Europe/London"))
.build();
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, TimeZoneProviderStatus.UNKNOWN);
ARBITRARY_ELAPSED_REALTIME_MILLIS, suggestion, null);
provider.simulateProviderEventReceived(event);
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_CERTAIN);
// Simulate an uncertain event being received.
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS,
TimeZoneProviderStatus.UNKNOWN);
event = TimeZoneProviderEvent.createUncertainEvent(ARBITRARY_ELAPSED_REALTIME_MILLIS, null);
provider.simulateProviderEventReceived(event);
provider.assertLatestRecordedState(PROVIDER_STATE_STARTED_UNCERTAIN);
@@ -239,7 +264,7 @@ public class LocationTimeZoneProviderTest {
.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
.setTimeZoneIds(invalidTimeZoneIds)
.build();
TimeZoneProviderStatus providerStatus = TimeZoneProviderStatus.UNKNOWN;
TimeZoneProviderStatus providerStatus = null;
TimeZoneProviderEvent event = TimeZoneProviderEvent.createSuggestionEvent(
ARBITRARY_ELAPSED_REALTIME_MILLIS, invalidIdSuggestion, providerStatus);
provider.simulateProviderEventReceived(event);
@@ -275,9 +300,11 @@ public class LocationTimeZoneProviderTest {
*/
private static ProviderState assertAndReturnProviderState(
TestLocationTimeZoneProvider provider,
RecordingProviderMetricsLogger providerMetricsLogger, int expectedStateEnum) {
RecordingProviderMetricsLogger providerMetricsLogger, int expectedStateEnum,
TimeZoneProviderStatus expectedReportedStatus) {
ProviderState currentState = provider.getCurrentState();
assertEquals(expectedStateEnum, currentState.stateEnum);
assertEquals(expectedReportedStatus, currentState.getReportedStatus());
providerMetricsLogger.assertChangeLoggedAndRemove(expectedStateEnum);
providerMetricsLogger.assertNoMoreLogEntries();
return currentState;

View File

@@ -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))