Loading core/java/android/app/time/ExternalTimeSuggestion.java +44 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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 */ Loading @@ -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; Loading @@ -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<>(); } Loading @@ -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 + '}'; } } core/java/android/app/time/TimeManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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)); } /** Loading Loading @@ -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(); } } } core/java/android/app/timedetector/TimeDetector.java +0 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } core/java/android/app/timedetector/TimeDetectorImpl.java +0 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } } } core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java +10 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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()) Loading Loading
core/java/android/app/time/ExternalTimeSuggestion.java +44 −25 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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 */ Loading @@ -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; Loading @@ -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<>(); } Loading @@ -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 + '}'; } }
core/java/android/app/time/TimeManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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)); } /** Loading Loading @@ -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(); } } }
core/java/android/app/timedetector/TimeDetector.java +0 −9 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); }
core/java/android/app/timedetector/TimeDetectorImpl.java +0 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); } } }
core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java +10 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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()) Loading