diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java index 50a7da1cede57..5ee10a50568d8 100644 --- a/core/java/android/app/timedetector/TimeDetector.java +++ b/core/java/android/app/timedetector/TimeDetector.java @@ -114,6 +114,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}. * diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index 98c0d7f4fbf17..5aa0f59024f8b 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 080929729fe35..a3ba7373b9216 100644 --- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java @@ -180,24 +180,6 @@ public class NetworkTimeUpdateService extends Binder { } } - /** - * Clears the cached NTP time. For use during tests to simulate when no NTP time is available. - * - *
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. * diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java index 410b50f8a88b2..b19ce59dc2f58 100644 --- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java +++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java @@ -36,11 +36,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. */ @@ -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 0da967a3bc006..22f096b11f18a 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 * *
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()}. + * + *
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()}. + * + *
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 cce5709861689..fe0127fc11f28 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