Move suggestExternalTime to TimeManager
This CL moves suggestExternalTime method from TimeDetector to TimeManager. Eventual goal is to make suggestExternalTime a System API. Ideally all time related system APIs live in android.app.time hence the move. Test: atest android.app.time Change-Id: I464545e77fdf68c35c8a338bfe5ac8b7535bc3e6 Bug: 177079827
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package android.app.time;
|
||||
|
||||
import android.annotation.CurrentTimeMillisLong;
|
||||
import android.annotation.ElapsedRealtimeLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
@@ -31,9 +33,9 @@ import java.util.Objects;
|
||||
/**
|
||||
* A time signal from an External source.
|
||||
*
|
||||
* External time suggestions are for use in situations where the Android device is part of a wider
|
||||
* network of devices that are required to use a single time source, and where authority for the
|
||||
* time is external to the Android device. For example, for the Android Auto use case where the
|
||||
* <p>External time suggestions are for use in situations where the Android device is part of a
|
||||
* wider network of devices that are required to use a single time source, and where authority for
|
||||
* the time is external to the Android device. For example, for the Android Auto use case where the
|
||||
* Android device is part of a wider in-car network of devices that should display the same time.
|
||||
*
|
||||
* <p>Android allows for a single external source for time. If there are several external sources
|
||||
@@ -49,19 +51,19 @@ import java.util.Objects;
|
||||
* capture the elapsed realtime reference clock, e.g. via {@link SystemClock#elapsedRealtime()},
|
||||
* when the UTC time is first obtained (usually under a wakelock). This enables Android to adjust
|
||||
* for latency introduced between suggestion creation and eventual use. Adjustments for other
|
||||
* sources of latency, i.e. those before the external time suggestion is created, must be handled
|
||||
* by the creator.
|
||||
* sources of latency, i.e. those before the external time suggestion is created, must be handled by
|
||||
* the creator.
|
||||
*
|
||||
* <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
|
||||
* elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
|
||||
* elapsed realtime clock when the {@code utcTime.value} was established.
|
||||
* Note that the elapsed realtime clock is considered accurate but it is volatile, so time
|
||||
* suggestions cannot be persisted across device resets.
|
||||
* <p>{@code elapsedRealtimeMillis} and {@code suggestionMillis} represent the suggested time.
|
||||
* {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC.
|
||||
* {@code elapsedRealtimeMillis} is the value of the elapsed realtime clock when {@code
|
||||
* suggestionMillis} was established. Note that the elapsed realtime clock is considered accurate
|
||||
* but it is volatile, so time suggestions cannot be persisted across device resets.
|
||||
*
|
||||
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
|
||||
* record why the suggestion exists and how it was entered. This information exists only to aid in
|
||||
* debugging and therefore is used by {@link #toString()}, but it is not for use in detection
|
||||
* logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
* debugging and therefore is used by {@link #toString()}, but it is not for use in detection logic
|
||||
* and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@@ -78,17 +80,28 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull private final TimestampedValue<Long> mUtcTime;
|
||||
@Nullable private ArrayList<String> mDebugInfo;
|
||||
@NonNull
|
||||
private final TimestampedValue<Long> mUtcTime;
|
||||
@Nullable
|
||||
private ArrayList<String> mDebugInfo;
|
||||
|
||||
public ExternalTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
|
||||
mUtcTime = Objects.requireNonNull(utcTime);
|
||||
Objects.requireNonNull(utcTime.getValue());
|
||||
/**
|
||||
* Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
|
||||
* ExternalTimeSuggestion} for more details.
|
||||
*
|
||||
* @param elapsedRealtimeMillis the elapsed realtime clock reference for the suggestion
|
||||
* @param suggestionMillis the suggested UTC time in milliseconds since the start of the
|
||||
* Unix epoch
|
||||
*/
|
||||
public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
|
||||
@CurrentTimeMillisLong long suggestionMillis) {
|
||||
mUtcTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
|
||||
}
|
||||
|
||||
private static ExternalTimeSuggestion createFromParcel(Parcel in) {
|
||||
TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
|
||||
ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(utcTime);
|
||||
ExternalTimeSuggestion suggestion =
|
||||
new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
|
||||
suggestion.mDebugInfo = debugInfo;
|
||||
@@ -106,23 +119,31 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
dest.writeList(mDebugInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
@NonNull
|
||||
public TimestampedValue<Long> getUtcTime() {
|
||||
return mUtcTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
|
||||
* {@hide}
|
||||
*/
|
||||
@NonNull
|
||||
public List<String> getDebugInfo() {
|
||||
return mDebugInfo == null
|
||||
? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
|
||||
? Collections.emptyList()
|
||||
: Collections.unmodifiableList(mDebugInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates information with the instance that can be useful for debugging / logging. The
|
||||
* information is present in {@link #toString()} but is not considered for
|
||||
* {@link #equals(Object)} and {@link #hashCode()}.
|
||||
* information is present in {@link #toString()} but is not considered for {@link
|
||||
* #equals(Object)} and {@link #hashCode()}.
|
||||
*/
|
||||
public void addDebugInfo(String... debugInfos) {
|
||||
public void addDebugInfo(@NonNull String... debugInfos) {
|
||||
if (mDebugInfo == null) {
|
||||
mDebugInfo = new ArrayList<>();
|
||||
}
|
||||
@@ -148,9 +169,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExternalTimeSuggestion{"
|
||||
+ "mUtcTime=" + mUtcTime
|
||||
+ ", mDebugInfo=" + mDebugInfo
|
||||
return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.app.timedetector.ITimeDetectorService;
|
||||
import android.app.timezonedetector.ITimeZoneDetectorService;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
@@ -45,6 +46,7 @@ public final class TimeManager {
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final ITimeZoneDetectorService mITimeZoneDetectorService;
|
||||
private final ITimeDetectorService mITimeDetectorService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
|
||||
@@ -62,6 +64,8 @@ public final class TimeManager {
|
||||
// internal refactoring.
|
||||
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
|
||||
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
|
||||
mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
|
||||
ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,4 +218,23 @@ public final class TimeManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests the current time from an external time source. For example, a form factor-specific
|
||||
* HAL. This time <em>may</em> be used to set the device system clock, depending on the device
|
||||
* configuration and user settings. This method call is processed asynchronously.
|
||||
* See {@link ExternalTimeSuggestion} for more details.
|
||||
* {@hide}
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.SET_TIME)
|
||||
public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
|
||||
}
|
||||
try {
|
||||
mITimeDetectorService.suggestExternalTime(timeSuggestion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package android.app.timedetector;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemService;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.os.TimestampedValue;
|
||||
@@ -80,12 +79,4 @@ public interface TimeDetector {
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.SET_TIME)
|
||||
void suggestGnssTime(GnssTimeSuggestion timeSuggestion);
|
||||
|
||||
/**
|
||||
* Suggests the time according to an external time source (form factor specific HAL, etc).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.SET_TIME)
|
||||
void suggestExternalTime(ExternalTimeSuggestion timeSuggestion);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package android.app.timedetector;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.time.ExternalTimeSuggestion;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
@@ -87,16 +86,4 @@ public final class TimeDetectorImpl implements TimeDetector {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggestExternalTime(ExternalTimeSuggestion timeSuggestion) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
|
||||
}
|
||||
try {
|
||||
mITimeDetectorService.suggestExternalTime(timeSuggestion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,17 +33,20 @@ public class ExternalTimeSuggestionTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
ExternalTimeSuggestion one = new ExternalTimeSuggestion(ARBITRARY_TIME);
|
||||
ExternalTimeSuggestion one = new ExternalTimeSuggestion(
|
||||
ARBITRARY_TIME.getReferenceTimeMillis(),
|
||||
ARBITRARY_TIME.getValue());
|
||||
assertEquals(one, one);
|
||||
|
||||
ExternalTimeSuggestion two = new ExternalTimeSuggestion(ARBITRARY_TIME);
|
||||
ExternalTimeSuggestion two = new ExternalTimeSuggestion(
|
||||
ARBITRARY_TIME.getReferenceTimeMillis(),
|
||||
ARBITRARY_TIME.getValue());
|
||||
assertEquals(one, two);
|
||||
assertEquals(two, one);
|
||||
|
||||
TimestampedValue<Long> differentTime = new TimestampedValue<>(
|
||||
ExternalTimeSuggestion three = new ExternalTimeSuggestion(
|
||||
ARBITRARY_TIME.getReferenceTimeMillis() + 1,
|
||||
ARBITRARY_TIME.getValue());
|
||||
ExternalTimeSuggestion three = new ExternalTimeSuggestion(differentTime);
|
||||
assertNotEquals(one, three);
|
||||
assertNotEquals(three, one);
|
||||
|
||||
@@ -55,7 +58,9 @@ public class ExternalTimeSuggestionTest {
|
||||
|
||||
@Test
|
||||
public void testParcelable() {
|
||||
ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(ARBITRARY_TIME);
|
||||
ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(
|
||||
ARBITRARY_TIME.getReferenceTimeMillis(),
|
||||
ARBITRARY_TIME.getValue());
|
||||
assertRoundTripParcelable(suggestion);
|
||||
|
||||
// DebugInfo should also be stored (but is not checked by equals())
|
||||
|
||||
@@ -287,8 +287,7 @@ public class TimeDetectorServiceTest {
|
||||
}
|
||||
|
||||
private static ExternalTimeSuggestion createExternalTimeSuggestion() {
|
||||
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
|
||||
return new ExternalTimeSuggestion(timeValue);
|
||||
return new ExternalTimeSuggestion(100L, 1_000_000L);
|
||||
}
|
||||
|
||||
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
|
||||
|
||||
@@ -1483,11 +1483,8 @@ public class TimeDetectorStrategyImplTest {
|
||||
* reference time.
|
||||
*/
|
||||
ExternalTimeSuggestion generateExternalTimeSuggestion(Instant suggestedTime) {
|
||||
TimestampedValue<Long> utcTime =
|
||||
new TimestampedValue<>(
|
||||
mFakeEnvironment.peekElapsedRealtimeMillis(),
|
||||
return new ExternalTimeSuggestion(mFakeEnvironment.peekElapsedRealtimeMillis(),
|
||||
suggestedTime.toEpochMilli());
|
||||
return new ExternalTimeSuggestion(utcTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user