Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9429d4dc authored by Neil Fuller's avatar Neil Fuller
Browse files

Tidy up changes before API change

Extract non-API changes to make the API change commit smaller / more
focused. These changes are mostly naming, comment and some improved
validation. There's some toString() / parsing toString() changes and
associated tests for manual testing support used in later commits.

Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/location/
Test: atest core/tests/coretests/src/android/service/timezone/
Bug: 236624675
Change-Id: I8f74e4bd0ad1a34b593afdf89b3e4840420a5d10
parent 35f7d0a3
Loading
Loading
Loading
Loading
+23 −9
Original line number Diff line number Diff line
@@ -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() {
+15 −2
Original line number Diff line number Diff line
@@ -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;
+195 −52
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+118 −17

File changed.

Preview size limit exceeded, changes collapsed.

+29 −17

File changed.

Preview size limit exceeded, changes collapsed.

Loading