diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl index a0c898ed2904f..96eddd201afa8 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.TimeState; 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 @@ interface ITimeDetectorService { 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 80d4bc1c34b52..0000000000000 --- 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 aa079a9b1159b..0000000000000 --- 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 CREATOR = - new Creator() { - 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 2b75a23505d64..831ca86504afe 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -18,8 +18,8 @@ package android.os; 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 @@ public final class SystemClock { 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 9d098c6fc94b6..1be9074e079a9 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.time.UnixEpochTime; 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 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub 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); @@ -376,19 +403,6 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal)); } - @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) { @@ -421,7 +435,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub 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 4b417ba367ae6..a8572381208d0 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 com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWOR 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.TimeState; 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 @@ public class TimeDetectorServiceTest { 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()); } @@ -396,6 +396,25 @@ public class TimeDetectorServiceTest { assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime()); } + @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());