diff options
7 files changed, 153 insertions, 85 deletions
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java index 50a7da1cede5..5ee10a50568d 100644 --- a/core/java/android/app/timedetector/TimeDetector.java +++ b/core/java/android/app/timedetector/TimeDetector.java @@ -115,6 +115,20 @@ public interface TimeDetector { String SHELL_COMMAND_CONFIRM_TIME = "confirm_time"; /** + * A shell command that clears the network time signal used by {@link + * SystemClock#currentNetworkTimeClock()}. + * @hide + */ + String SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME = "clear_system_clock_network_time"; + + /** + * A shell command that sets the network time signal used by {@link + * SystemClock#currentNetworkTimeClock()}. + * @hide + */ + String SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME = "set_system_clock_network_time"; + + /** * A shared utility method to create a {@link ManualTimeSuggestion}. * * @hide diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 98c0d7f4fbf1..5aa0f59024f8 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -477,7 +477,14 @@ public abstract class NtpTrustedTime implements TrustedTime { return mTimeResult; } - /** Clears the last received NTP. Intended for use during tests. */ + /** Sets the last received NTP time. Intended for use during tests. */ + public void setCachedTimeResult(TimeResult timeResult) { + synchronized (this) { + mTimeResult = timeResult; + } + } + + /** Clears the last received NTP time. Intended for use during tests. */ public void clearCachedTimeResult() { synchronized (this) { mTimeResult = null; diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java index 080929729fe3..a3ba7373b921 100644 --- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java @@ -181,24 +181,6 @@ public class NetworkTimeUpdateService extends Binder { } /** - * Clears the cached NTP time. For use during tests to simulate when no NTP time is available. - * - * <p>This operation takes place in the calling thread rather than the service's handler thread. - */ - @RequiresPermission(android.Manifest.permission.SET_TIME) - void clearTimeForTests() { - mContext.enforceCallingPermission( - android.Manifest.permission.SET_TIME, "clear latest network time"); - - final long token = Binder.clearCallingIdentity(); - try { - mNtpTrustedTime.clearCachedTimeResult(); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - /** * Forces the service to refresh the NTP time. * * <p>This operation takes place in the calling thread rather than the service's handler thread. diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java index 410b50f8a88b..b19ce59dc2f5 100644 --- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java +++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java @@ -37,11 +37,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { private static final String SHELL_COMMAND_SERVICE_NAME = "network_time_update_service"; /** - * A shell command that clears the time signal received from the network. - */ - private static final String SHELL_COMMAND_CLEAR_TIME = "clear_time"; - - /** * A shell command that forces the time signal to be refreshed from the network. */ private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh"; @@ -73,8 +68,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { } switch (cmd) { - case SHELL_COMMAND_CLEAR_TIME: - return runClearTime(); case SHELL_COMMAND_FORCE_REFRESH: return runForceRefresh(); case SHELL_COMMAND_SET_SERVER_CONFIG: @@ -87,11 +80,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { } } - private int runClearTime() { - mNetworkTimeUpdateService.clearTimeForTests(); - return 0; - } - private int runForceRefresh() { boolean success = mNetworkTimeUpdateService.forceRefreshForTests(); getOutPrintWriter().println(success); @@ -147,8 +135,6 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME); pw.printf(" help\n"); pw.printf(" Print this help text.\n"); - pw.printf(" %s\n", SHELL_COMMAND_CLEAR_TIME); - pw.printf(" Clears the latest time.\n"); pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH); pw.printf(" Refreshes the latest time. Prints whether it was successful.\n"); pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG); diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java index 0da967a3bc00..22f096b11f18 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java @@ -37,6 +37,7 @@ import android.os.ParcelableException; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; +import android.os.SystemClock; import android.util.ArrayMap; import android.util.IndentingPrintWriter; import android.util.NtpTrustedTime; @@ -53,6 +54,7 @@ import com.android.server.timezonedetector.CurrentUserIdentityInjector; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.net.InetSocketAddress; import java.time.DateTimeException; import java.util.Objects; @@ -377,7 +379,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub * * <p>This operation takes place in the calling thread. */ - void clearNetworkTime() { + void clearLatestNetworkTime() { enforceSuggestNetworkTimePermission(); final long token = Binder.clearCallingIdentity(); @@ -390,12 +392,29 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub @Override public UnixEpochTime latestNetworkTime() { - NetworkTimeSuggestion suggestion = getLatestNetworkSuggestion(); - if (suggestion != null) { - return suggestion.getUnixEpochTime(); + NetworkTimeSuggestion latestNetworkTime; + // TODO(b/222295093): Remove this condition once we can be sure that all uses of + // NtpTrustedTime result in a suggestion being made to the time detector. + // mNtpTrustedTime can be removed once this happens. + if (TimeDetectorNetworkTimeHelper.isInUse()) { + // The new implementation. + latestNetworkTime = mTimeDetectorStrategy.getLatestNetworkSuggestion(); } else { + // The old implementation. + NtpTrustedTime.TimeResult ntpResult = mNtpTrustedTime.getCachedTimeResult(); + if (ntpResult != null) { + latestNetworkTime = new NetworkTimeSuggestion( + new UnixEpochTime( + ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis()), + ntpResult.getUncertaintyMillis()); + } else { + latestNetworkTime = null; + } + } + if (latestNetworkTime == null) { throw new ParcelableException(new DateTimeException("Missing network time fix")); } + return latestNetworkTime.getUnixEpochTime(); } /** @@ -403,23 +422,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub */ @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. - if (TimeDetectorNetworkTimeHelper.isInUse()) { - // The new implementation. - return mTimeDetectorStrategy.getLatestNetworkSuggestion(); - } else { - // The old implementation. - 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; - } - } + return mTimeDetectorStrategy.getLatestNetworkSuggestion(); } /** @@ -440,6 +443,57 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub mHandler.post(() -> mTimeDetectorStrategy.suggestExternalTime(timeSignal)); } + /** + * Sets the network time for testing {@link SystemClock#currentNetworkTimeClock()}. + * + * <p>This operation takes place in the calling thread. + */ + void setNetworkTimeForSystemClockForTests( + @NonNull UnixEpochTime unixEpochTime, int uncertaintyMillis) { + enforceSuggestNetworkTimePermission(); + + // TODO(b/222295093): Remove this condition once we can be sure that all uses of + // NtpTrustedTime result in a suggestion being made to the time detector. + // mNtpTrustedTime can be removed once this happens. + if (TimeDetectorNetworkTimeHelper.isInUse()) { + NetworkTimeSuggestion suggestion = + new NetworkTimeSuggestion(unixEpochTime, uncertaintyMillis); + suggestion.addDebugInfo("Injected for tests"); + mTimeDetectorStrategy.suggestNetworkTime(suggestion); + } else { + NtpTrustedTime.TimeResult timeResult = new NtpTrustedTime.TimeResult( + unixEpochTime.getUnixEpochTimeMillis(), + unixEpochTime.getElapsedRealtimeMillis(), + uncertaintyMillis, + InetSocketAddress.createUnresolved("time.set.for.tests", 123)); + mNtpTrustedTime.setCachedTimeResult(timeResult); + } + } + + /** + * Clears the network time for testing {@link SystemClock#currentNetworkTimeClock()}. + * + * <p>This operation takes place in the calling thread. + */ + void clearNetworkTimeForSystemClockForTests() { + enforceSuggestNetworkTimePermission(); + + final long token = Binder.clearCallingIdentity(); + try { + // TODO(b/222295093): Remove this condition once we can be sure that all uses of + // NtpTrustedTime result in a suggestion being made to the time detector. + // mNtpTrustedTime can be removed once this happens. + if (TimeDetectorNetworkTimeHelper.isInUse()) { + // Clear the latest network suggestion. Done in all c + mTimeDetectorStrategy.clearLatestNetworkSuggestion(); + } else { + mNtpTrustedTime.clearCachedTimeResult(); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + @Override protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @Nullable String[] args) { diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java index cce570986168..fe0127fc11f2 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorShellCommand.java @@ -16,12 +16,14 @@ package com.android.server.timedetector; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_NETWORK_TIME; +import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_CONFIRM_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_NETWORK_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_GET_TIME_STATE; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SERVICE_NAME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED; +import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SET_TIME_STATE; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_EXTERNAL_TIME; import static android.app.timedetector.TimeDetector.SHELL_COMMAND_SUGGEST_GNSS_TIME; @@ -73,9 +75,9 @@ class TimeDetectorShellCommand extends ShellCommand { case SHELL_COMMAND_SUGGEST_NETWORK_TIME: return runSuggestNetworkTime(); case SHELL_COMMAND_GET_NETWORK_TIME: - return runGetNetworkTime(); + return runGetLatestNetworkTime(); case SHELL_COMMAND_CLEAR_NETWORK_TIME: - return runClearNetworkTime(); + return runClearLatestNetworkTime(); case SHELL_COMMAND_SUGGEST_GNSS_TIME: return runSuggestGnssTime(); case SHELL_COMMAND_SUGGEST_EXTERNAL_TIME: @@ -86,6 +88,10 @@ class TimeDetectorShellCommand extends ShellCommand { return runSetTimeState(); case SHELL_COMMAND_CONFIRM_TIME: return runConfirmTime(); + case SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME: + return runClearSystemClockNetworkTime(); + case SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME: + return runSetSystemClockNetworkTime(); default: { return handleDefaultCommands(cmd); } @@ -128,15 +134,15 @@ class TimeDetectorShellCommand extends ShellCommand { mInterface::suggestNetworkTime); } - private int runGetNetworkTime() { + private int runGetLatestNetworkTime() { NetworkTimeSuggestion networkTimeSuggestion = mInterface.getLatestNetworkSuggestion(); final PrintWriter pw = getOutPrintWriter(); pw.println(networkTimeSuggestion); return 0; } - private int runClearNetworkTime() { - mInterface.clearNetworkTime(); + private int runClearLatestNetworkTime() { + mInterface.clearLatestNetworkTime(); return 0; } @@ -187,6 +193,20 @@ class TimeDetectorShellCommand extends ShellCommand { return 0; } + private int runClearSystemClockNetworkTime() { + mInterface.clearNetworkTimeForSystemClockForTests(); + return 0; + } + + private int runSetSystemClockNetworkTime() { + NetworkTimeSuggestion networkTimeSuggestion = + NetworkTimeSuggestion.parseCommandLineArg(this); + mInterface.setNetworkTimeForSystemClockForTests( + networkTimeSuggestion.getUnixEpochTime(), + networkTimeSuggestion.getUncertaintyMillis()); + return 0; + } + @Override public void onHelp() { final PrintWriter pw = getOutPrintWriter(); @@ -218,6 +238,16 @@ class TimeDetectorShellCommand extends ShellCommand { pw.printf(" Prints the network time information held by the detector.\n"); pw.printf(" %s\n", SHELL_COMMAND_CLEAR_NETWORK_TIME); pw.printf(" Clears the network time information held by the detector.\n"); + // TODO(b/222295093) Remove these "system_clock" commands when + // SystemClock.currentNetworkTimeClock() is guaranteed to use the latest network + // suggestion. Then, commands above can be used instead. + pw.printf(" %s <network suggestion opts>\n", + SHELL_COMMAND_SET_SYSTEM_CLOCK_NETWORK_TIME); + pw.printf(" Sets the network time information used for" + + " SystemClock.currentNetworkTimeClock().\n"); + pw.printf(" %s\n", SHELL_COMMAND_CLEAR_SYSTEM_CLOCK_NETWORK_TIME); + pw.printf(" Clears the network time information used for" + + " SystemClock.currentNetworkTimeClock().\n"); pw.println(); ManualTimeSuggestion.printCommandLineOpts(pw); pw.println(); 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 5a0867f8f584..daa682342836 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -386,16 +386,16 @@ public class TimeDetectorServiceTest { .when(mMockContext).enforceCallingPermission(anyString(), any()); assertThrows(SecurityException.class, - () -> mTimeDetectorService.clearNetworkTime()); + () -> mTimeDetectorService.clearLatestNetworkTime()); verify(mMockContext).enforceCallingPermission( eq(android.Manifest.permission.SET_TIME), anyString()); } @Test - public void testClearNetworkTime() throws Exception { + public void testClearLatestNetworkSuggestion() throws Exception { doNothing().when(mMockContext).enforceCallingPermission(anyString(), any()); - mTimeDetectorService.clearNetworkTime(); + mTimeDetectorService.clearLatestNetworkTime(); verify(mMockContext).enforceCallingPermission( eq(android.Manifest.permission.SET_TIME), anyString()); @@ -403,53 +403,48 @@ public class TimeDetectorServiceTest { } @Test - public void testLatestNetworkTime() { - NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult( - 1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123)); - when(mMockNtpTrustedTime.getCachedTimeResult()) - .thenReturn(latestNetworkTime); - UnixEpochTime expected = new UnixEpochTime( - latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis()); - assertEquals(expected, mTimeDetectorService.latestNetworkTime()); + public void testGetLatestNetworkSuggestion() { + NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion(); + mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion); + + assertEquals(latestNetworkSuggestion, mTimeDetectorService.getLatestNetworkSuggestion()); } @Test - public void testLatestNetworkTime_noTimeAvailable() { - when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null); - assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime()); + public void testGetLatestNetworkSuggestion_noTimeAvailable() { + mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null); + + assertNull(mTimeDetectorService.getLatestNetworkSuggestion()); } @Test - public void testGetLatestNetworkSuggestion() { + public void testLatestNetworkTime() { if (TimeDetectorNetworkTimeHelper.isInUse()) { - NetworkTimeSuggestion latestNetworkTime = createNetworkTimeSuggestion(); - mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkTime); + NetworkTimeSuggestion latestNetworkSuggestion = createNetworkTimeSuggestion(); + mFakeTimeDetectorStrategySpy.setLatestNetworkTime(latestNetworkSuggestion); - assertEquals(latestNetworkTime, mTimeDetectorService.getLatestNetworkSuggestion()); + assertEquals(latestNetworkSuggestion.getUnixEpochTime(), + mTimeDetectorService.latestNetworkTime()); } else { NtpTrustedTime.TimeResult latestNetworkTime = new NtpTrustedTime.TimeResult( 1234L, 54321L, 999, InetSocketAddress.createUnresolved("test.timeserver", 123)); when(mMockNtpTrustedTime.getCachedTimeResult()) .thenReturn(latestNetworkTime); - UnixEpochTime expectedUnixEpochTime = new UnixEpochTime( + UnixEpochTime expected = new UnixEpochTime( latestNetworkTime.getElapsedRealtimeMillis(), latestNetworkTime.getTimeMillis()); - NetworkTimeSuggestion expected = new NetworkTimeSuggestion( - expectedUnixEpochTime, latestNetworkTime.getUncertaintyMillis()); - assertEquals(expected, mTimeDetectorService.getLatestNetworkSuggestion()); + assertEquals(expected, mTimeDetectorService.latestNetworkTime()); } } @Test - public void testGetLatestNetworkSuggestion_noTimeAvailable() { + public void testLatestNetworkTime_noTimeAvailable() { if (TimeDetectorNetworkTimeHelper.isInUse()) { mFakeTimeDetectorStrategySpy.setLatestNetworkTime(null); - - assertNull(mTimeDetectorService.getLatestNetworkSuggestion()); } else { when(mMockNtpTrustedTime.getCachedTimeResult()).thenReturn(null); - assertNull(mTimeDetectorService.getLatestNetworkSuggestion()); } + assertThrows(ParcelableException.class, () -> mTimeDetectorService.latestNetworkTime()); } @Test |