Switch from TimePoint to UnixEpochTime

TimePoint can be replaced by SDK API UnixEpochTime.

Bug: 222295093
Test: treehugger only
Change-Id: I099de6727b9f95e2232ead06abb2735e8af16146
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index a0c898e..96eddd2 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -24,7 +24,6 @@
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
-import android.app.timedetector.TimePoint;
 
 /**
  * Binder APIs to communicate with the time detector service.
@@ -55,5 +54,5 @@
   boolean suggestManualTime(in ManualTimeSuggestion timeSuggestion);
   void suggestTelephonyTime(in TelephonyTimeSuggestion timeSuggestion);
 
-  TimePoint latestNetworkTime();
+  UnixEpochTime latestNetworkTime();
 }
diff --git a/core/java/android/app/timedetector/TimePoint.aidl b/core/java/android/app/timedetector/TimePoint.aidl
deleted file mode 100644
index 80d4bc1..0000000
--- a/core/java/android/app/timedetector/TimePoint.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2022, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.timedetector;
-
-parcelable TimePoint;
diff --git a/core/java/android/app/timedetector/TimePoint.java b/core/java/android/app/timedetector/TimePoint.java
deleted file mode 100644
index aa079a9..0000000
--- a/core/java/android/app/timedetector/TimePoint.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.timedetector;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Data class for passing a Unix epoch time anchored to the elapsed realtime clock.
- *
- * @hide
- */
-public final class TimePoint implements Parcelable {
-
-    private final long mUnixEpochTimeMillis;
-    private final long mElapsedRealtimeMillis;
-
-    public TimePoint(long unixEpochTimeMillis, long elapsedRealtimeMillis) {
-        mUnixEpochTimeMillis = unixEpochTimeMillis;
-        mElapsedRealtimeMillis = elapsedRealtimeMillis;
-    }
-
-    /**
-     * The current Unix epoch time, according to the external source.
-     */
-    public long getUnixEpochTimeMillis() {
-        return mUnixEpochTimeMillis;
-    }
-
-    /**
-     * The elapsed millis since boot when {@link #getUnixEpochTimeMillis} was computed.
-     */
-    public long getElapsedRealtimeMillis() {
-        return mElapsedRealtimeMillis;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeLong(mUnixEpochTimeMillis);
-        out.writeLong(mElapsedRealtimeMillis);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof TimePoint)) {
-            return false;
-        }
-        TimePoint timePoint = (TimePoint) o;
-        return mUnixEpochTimeMillis == timePoint.mUnixEpochTimeMillis
-                && mElapsedRealtimeMillis == timePoint.mElapsedRealtimeMillis;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mUnixEpochTimeMillis, mElapsedRealtimeMillis);
-    }
-
-    @Override
-    public String toString() {
-        return "TimePoint{"
-                + "mUnixEpochTimeMillis=" + mUnixEpochTimeMillis
-                + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
-                + '}';
-    }
-
-    public static final @NonNull Creator<TimePoint> CREATOR =
-            new Creator<TimePoint>() {
-                public TimePoint createFromParcel(Parcel in) {
-                    long unixEpochTime = in.readLong();
-                    long elapsedRealtimeMillis = in.readLong();
-                    return new TimePoint(unixEpochTime, elapsedRealtimeMillis);
-                }
-
-                public TimePoint[] newArray(int size) {
-                    return new TimePoint[size];
-                }
-            };
-}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 2b75a23..831ca86 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.app.IAlarmManager;
+import android.app.time.UnixEpochTime;
 import android.app.timedetector.ITimeDetectorService;
-import android.app.timedetector.TimePoint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.location.ILocationManager;
@@ -300,7 +300,7 @@
         ITimeDetectorService timeDetectorService = ITimeDetectorService.Stub
                 .asInterface(ServiceManager.getService(Context.TIME_DETECTOR_SERVICE));
         if (timeDetectorService != null) {
-            TimePoint time;
+            UnixEpochTime time;
             try {
                 time = timeDetectorService.latestNetworkTime();
             } catch (ParcelableException e) {
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 9d098c6..1be9074 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -29,7 +29,6 @@
 import android.app.timedetector.ITimeDetectorService;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
-import android.app.timedetector.TimePoint;
 import android.content.Context;
 import android.os.Binder;
 import android.os.Handler;
@@ -361,6 +360,34 @@
         mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
     }
 
+    @Override
+    public UnixEpochTime latestNetworkTime() {
+        NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion();
+        if (suggestion != null) {
+            return suggestion.getUnixEpochTime();
+        } else {
+            throw new ParcelableException(new DateTimeException("Missing network time fix"));
+        }
+    }
+
+    /**
+     * Returns the latest network suggestion accepted. For use by {@link TimeDetectorShellCommand}.
+     */
+    @Nullable
+    NetworkTimeSuggestion getLatestNetworkSuggestion() {
+        // TODO(b/222295093): Return the latest network time from mTimeDetectorStrategy once we can
+        //  be sure that all uses of NtpTrustedTime results in a suggestion being made to the time
+        //  detector. mNtpTrustedTime can be removed once this happens.
+        NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
+        if (ntpResult != null) {
+            UnixEpochTime unixEpochTime = new UnixEpochTime(
+                    ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
+            return new NetworkTimeSuggestion(unixEpochTime, ntpResult.getUncertaintyMillis());
+        } else {
+            return null;
+        }
+    }
+
     void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) {
         enforceSuggestGnssTimePermission();
         Objects.requireNonNull(timeSignal);
@@ -377,19 +404,6 @@
     }
 
     @Override
-    public TimePoint latestNetworkTime() {
-        // TODO(b/222295093): Return the latest network time from mTimeDetectorStrategy once we can
-        //  be sure that all uses of NtpTrustedTime results in a suggestion being made to the time
-        //  detector. mNtpTrustedTime can be removed once this happens.
-        NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult();
-        if (ntpResult != null) {
-            return new TimePoint(ntpResult.getTimeMillis(), ntpResult.getElapsedRealtimeMillis());
-        } else {
-            throw new ParcelableException(new DateTimeException("Missing network time fix"));
-        }
-    }
-
-    @Override
     protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
             @Nullable String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -421,7 +435,7 @@
     private void enforceSuggestNetworkTimePermission() {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.SET_TIME,
-                "set time");
+                "suggest network time");
     }
 
     private void enforceSuggestGnssTimePermission() {
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 4b417ba..a857238 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -20,6 +20,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -44,7 +45,6 @@
 import android.app.time.UnixEpochTime;
 import android.app.timedetector.ManualTimeSuggestion;
 import android.app.timedetector.TelephonyTimeSuggestion;
-import android.app.timedetector.TimePoint;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.HandlerThread;
@@ -385,8 +385,8 @@
                 1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
         when(mMockNtpTrustedTime.getCachedTimeResult())
                 .thenReturn(latestNetworkTime);
-        TimePoint expected = new TimePoint(latestNetworkTime.getTimeMillis(),
-                latestNetworkTime.getElapsedRealtimeMillis());
+        UnixEpochTime expected = new UnixEpochTime(
+                latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis());
         assertEquals(expected, mTimeDetectorService.latestNetworkTime());
     }
 
@@ -397,6 +397,25 @@
     }
 
     @Test
+    public void testGetLatestNetworkSuggestion() {
+        NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult(
+                1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123));
+        when(mMockNtpTrustedTime.getCachedTimeResult())
+                .thenReturn(latestNetworkTime);
+        UnixEpochTime expectedUnixEpochTime = new UnixEpochTime(
+                latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis());
+        NetworkTimeSuggestion expected = new NetworkTimeSuggestion(
+                expectedUnixEpochTime, latestNetworkTime.getUncertaintyMillis());
+        assertEquals(expected, mTimeDetectorService.getLatestNetworkSuggestion());
+    }
+
+    @Test
+    public void testGetLatestNetworkSuggestion_noTimeAvailable() {
+        when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null);
+        assertNull(mTimeDetectorService.getLatestNetworkSuggestion());
+    }
+
+    @Test
     public void testGetTimeState() {
         doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
         TimeState fakeState = new TimeState(new UnixEpochTime(12345L, 98765L), true);