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
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index b566eab..61defb5 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -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 @@
 /**
  * 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 @@
  * 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 @@
                 }
             };
 
-    @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 @@
         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 @@
 
     @Override
     public String toString() {
-        return "ExternalTimeSuggestion{"
-                + "mUtcTime=" + mUtcTime
-                + ", mDebugInfo=" + mDebugInfo
+        return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
                 + '}';
     }
 }
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index 262d244..430960f 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -20,6 +20,7 @@
 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 @@
 
     private final Object mLock = new Object();
     private final ITimeZoneDetectorService mITimeZoneDetectorService;
+    private final ITimeDetectorService mITimeDetectorService;
 
     @GuardedBy("mLock")
     private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
@@ -62,6 +64,8 @@
         // 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 @@
             }
         }
     }
+
+    /**
+     * 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();
+        }
+    }
 }
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 76f3785..52016b6 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -19,7 +19,6 @@
 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 @@
      */
     @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);
 }
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index ef818ef..b0aa3c8 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -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 @@
             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();
-        }
-    }
 }
diff --git a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
index 266ff3d..1c6b3cc 100644
--- a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
@@ -33,17 +33,20 @@
 
     @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 @@
 
     @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())
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 5574836..5f86d28 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -287,8 +287,7 @@
     }
 
     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 {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index daa1b25..f7a498b 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -1483,11 +1483,8 @@
          * reference time.
          */
         ExternalTimeSuggestion generateExternalTimeSuggestion(Instant suggestedTime) {
-            TimestampedValue<Long> utcTime =
-                    new TimestampedValue<>(
-                            mFakeEnvironment.peekElapsedRealtimeMillis(),
+            return new ExternalTimeSuggestion(mFakeEnvironment.peekElapsedRealtimeMillis(),
                             suggestedTime.toEpochMilli());
-            return new ExternalTimeSuggestion(utcTime);
         }
 
         /**