Add LTZP status APIs to the SDK
Give TimeZoneProviderService implementations the ability to supply (optional) status information. This status information can be used for two purposes: 1) To help report status to users in the SettingsUI (once plumbed through). 2) To influence higher-level time zone detection behavior, i.e. so that the time zone detection can understand that a TZP is unable to perform its duties, perhaps something the platform cannot detect for itself. Test: atest core/tests/coretests/src/android/service/timezone/ Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/location/ Bug: 236624675 Change-Id: Ifa66b8c968c0bdf31b6bdf55ead34b3fa1d9e6fa
This commit is contained in:
@@ -11889,11 +11889,39 @@ package android.service.timezone {
|
||||
method public abstract void onStopUpdates();
|
||||
method public final void reportPermanentFailure(@NonNull Throwable);
|
||||
method public final void reportSuggestion(@NonNull android.service.timezone.TimeZoneProviderSuggestion);
|
||||
method public final void reportSuggestion(@NonNull android.service.timezone.TimeZoneProviderSuggestion, @NonNull android.service.timezone.TimeZoneProviderStatus);
|
||||
method public final void reportUncertain();
|
||||
method public final void reportUncertain(@NonNull android.service.timezone.TimeZoneProviderStatus);
|
||||
field public static final String PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.PrimaryLocationTimeZoneProviderService";
|
||||
field public static final String SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.SecondaryLocationTimeZoneProviderService";
|
||||
}
|
||||
|
||||
public final class TimeZoneProviderStatus implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getConnectivityDependencyStatus();
|
||||
method public int getLocationDetectionDependencyStatus();
|
||||
method public int getTimeZoneResolutionOperationStatus();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.timezone.TimeZoneProviderStatus> CREATOR;
|
||||
field public static final int DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT = 4; // 0x4
|
||||
field public static final int DEPENDENCY_STATUS_BLOCKED_BY_SETTINGS = 6; // 0x6
|
||||
field public static final int DEPENDENCY_STATUS_DEGRADED_BY_SETTINGS = 5; // 0x5
|
||||
field public static final int DEPENDENCY_STATUS_NOT_APPLICABLE = 1; // 0x1
|
||||
field public static final int DEPENDENCY_STATUS_OK = 2; // 0x2
|
||||
field public static final int DEPENDENCY_STATUS_TEMPORARILY_UNAVAILABLE = 3; // 0x3
|
||||
field public static final int OPERATION_STATUS_FAILED = 3; // 0x3
|
||||
field public static final int OPERATION_STATUS_NOT_APPLICABLE = 1; // 0x1
|
||||
field public static final int OPERATION_STATUS_OK = 2; // 0x2
|
||||
}
|
||||
|
||||
public static final class TimeZoneProviderStatus.Builder {
|
||||
ctor public TimeZoneProviderStatus.Builder();
|
||||
method @NonNull public android.service.timezone.TimeZoneProviderStatus build();
|
||||
method @NonNull public android.service.timezone.TimeZoneProviderStatus.Builder setConnectivityDependencyStatus(int);
|
||||
method @NonNull public android.service.timezone.TimeZoneProviderStatus.Builder setLocationDetectionDependencyStatus(int);
|
||||
method @NonNull public android.service.timezone.TimeZoneProviderStatus.Builder setTimeZoneResolutionOperationStatus(int);
|
||||
}
|
||||
|
||||
public final class TimeZoneProviderSuggestion implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public long getElapsedRealtimeMillis();
|
||||
|
||||
@@ -44,8 +44,8 @@ import java.util.Objects;
|
||||
*
|
||||
* <p>Once started, providers are expected to detect the time zone if possible, and report the
|
||||
* result via {@link #reportSuggestion(TimeZoneProviderSuggestion)} or {@link
|
||||
* #reportUncertain()}. Providers may also report that they have permanently failed
|
||||
* by calling {@link #reportPermanentFailure(Throwable)}. See the javadocs for each
|
||||
* #reportUncertain(TimeZoneProviderStatus)}. Providers may also report that they have permanently
|
||||
* failed by calling {@link #reportPermanentFailure(Throwable)}. See the javadocs for each
|
||||
* method for details.
|
||||
*
|
||||
* <p>After starting, providers are expected to issue their first callback within the timeout
|
||||
@@ -213,8 +213,6 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
*
|
||||
* @param providerStatus provider status information that can influence detector service
|
||||
* behavior and/or be reported via the device UI
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion,
|
||||
@NonNull TimeZoneProviderStatus providerStatus) {
|
||||
@@ -248,8 +246,9 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
|
||||
/**
|
||||
* Indicates the time zone is not known because of an expected runtime state or error, e.g. when
|
||||
* the provider is unable to detect location, or there was a problem when resolving the location
|
||||
* to a time zone.
|
||||
* the provider is unable to detect location, or there was connectivity issue.
|
||||
*
|
||||
* <p>See {@link #reportUncertain(TimeZoneProviderStatus)} for a more expressive version
|
||||
*/
|
||||
public final void reportUncertain() {
|
||||
TimeZoneProviderStatus providerStatus = null;
|
||||
@@ -264,8 +263,6 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
*
|
||||
* @param providerStatus provider status information that can influence detector service
|
||||
* behavior and/or be reported via the device UI
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final void reportUncertain(@NonNull TimeZoneProviderStatus providerStatus) {
|
||||
Objects.requireNonNull(providerStatus);
|
||||
@@ -362,8 +359,8 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
* <p>Between {@link #onStartUpdates(long)} and {@link #onStopUpdates()} calls, the Android
|
||||
* system server holds the latest report from the provider in memory. After an initial report,
|
||||
* provider implementations are only required to send a report via {@link
|
||||
* #reportSuggestion(TimeZoneProviderSuggestion)} or via {@link #reportUncertain()} when it
|
||||
* differs from the previous report.
|
||||
* #reportSuggestion(TimeZoneProviderSuggestion, TimeZoneProviderStatus)} or via {@link
|
||||
* #reportUncertain(TimeZoneProviderStatus)} when it differs from the previous report.
|
||||
*
|
||||
* <p>{@link #reportPermanentFailure(Throwable)} can also be called by provider implementations
|
||||
* in rare cases, after which the provider should consider itself stopped and not make any
|
||||
@@ -375,7 +372,8 @@ public abstract class TimeZoneProviderService extends Service {
|
||||
* Android system server may move on to use other providers or detection methods. Providers
|
||||
* should therefore make best efforts during this time to generate a report, which could involve
|
||||
* increased power usage. Providers should preferably report an explicit {@link
|
||||
* #reportUncertain()} if the time zone(s) cannot be detected within the initialization timeout.
|
||||
* #reportUncertain(TimeZoneProviderStatus)} if the time zone(s) cannot be detected within the
|
||||
* initialization timeout.
|
||||
*
|
||||
* @see #onStopUpdates() for the signal from the system server to stop sending reports
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ package android.service.timezone;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
@@ -65,6 +66,7 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class TimeZoneProviderStatus implements Parcelable {
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,20 +16,15 @@
|
||||
|
||||
package android.service.timezone;
|
||||
|
||||
import static android.app.time.ParcelableTestSupport.assertRoundTripParcelable;
|
||||
import static android.service.timezone.TimeZoneProviderStatus.DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT;
|
||||
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_OK;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/** Non-SDK tests. See CTS for SDK API tests. */
|
||||
public class TimeZoneProviderStatusTest {
|
||||
|
||||
@Test
|
||||
@@ -42,81 +37,4 @@ public class TimeZoneProviderStatusTest {
|
||||
|
||||
assertEquals(status, TimeZoneProviderStatus.parseProviderStatus(status.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStatusValidation() {
|
||||
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setLocationDetectionDependencyStatus(-1)
|
||||
.build());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setConnectivityDependencyStatus(-1)
|
||||
.build());
|
||||
assertThrows(IllegalArgumentException.class,
|
||||
() -> new TimeZoneProviderStatus.Builder(status)
|
||||
.setTimeZoneResolutionOperationStatus(-1)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsAndHashcode() {
|
||||
TimeZoneProviderStatus status1_1 = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_OK)
|
||||
.build();
|
||||
assertEqualsAndHashcode(status1_1, status1_1);
|
||||
assertNotEquals(status1_1, null);
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status1_2 =
|
||||
new TimeZoneProviderStatus.Builder(status1_1).build();
|
||||
assertEqualsAndHashcode(status1_1, status1_2);
|
||||
assertNotSame(status1_1, status1_2);
|
||||
}
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
|
||||
{
|
||||
TimeZoneProviderStatus status2 = new TimeZoneProviderStatus.Builder(status1_1)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
assertNotEquals(status1_1, status2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertEqualsAndHashcode(Object one, Object two) {
|
||||
assertEquals(one, two);
|
||||
assertEquals(two, one);
|
||||
assertEquals(one.hashCode(), two.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParcelable() {
|
||||
TimeZoneProviderStatus status = new TimeZoneProviderStatus.Builder()
|
||||
.setLocationDetectionDependencyStatus(DEPENDENCY_STATUS_OK)
|
||||
.setConnectivityDependencyStatus(DEPENDENCY_STATUS_BLOCKED_BY_ENVIRONMENT)
|
||||
.setTimeZoneResolutionOperationStatus(OPERATION_STATUS_FAILED)
|
||||
.build();
|
||||
assertRoundTripParcelable(status);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user