diff options
| author | 2023-01-31 17:55:10 +0000 | |
|---|---|---|
| committer | 2023-02-20 10:00:57 +0000 | |
| commit | a6208228515e98ea0fb0642628e2a005f3bc9efb (patch) | |
| tree | d82c136c0349607611ae2f046ff21b0df232019f | |
| parent | fedd356d5c0a138d64d229e8f7bfe4cc7a729851 (diff) | |
Make CTS tests ambivalent to server impl
Implement shell command test support that will work regardless of which
of the two location NetworkTimeHelper implementations is in use at the
time. This is to prevent CTS breaking if OEMs or form factors switch the
implementation to the new one during the next Android release cycle.
New shell commands have been added temporarily to support the new
SystemClockNetworkTimeTest and do the right thing depending on the
implementation in use. This avoids the need for the tests to know which
impl is in use. In a future release cycle, when the old impl is deleted
these shell commands can be removed and the test changed as the new impl
uses the time_detector and suitable commands (mostly) exist for other
reasons.
Bug: 222295093
Test: atest services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
Test: See associated CTS change
Change-Id: Icca02ec263bb20bc02a0dd6dd6cc13342d9e4e7b
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 |