From 187c975af9b7b48a2602417ba1942db3219a6302 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Thu, 17 Mar 2022 10:02:58 +0000 Subject: [PATCH] Add the ability to configure NTP port for tests Add the ability to configure NTP port for tests via the command line and the associated plumbing / knock-ons. In-progress CTS tests will run a fake NTP server on the device itself. Binding to NTP's default port of 123 is restricted. Therefore, we need to be able to override the port for tests. adb shell cmd network_time_update_service set_server_config --port 9999 adb shell dumpsys network_time_update_service adb shell cmd network_time_update_service force_refresh adb shell cmd network_time_update_service set_server_config adb shell dumpsys network_time_update_service adb shell cmd network_time_update_service force_refresh Bug: 213393821 Test: See above Change-Id: I21e8b735fab268df0d617848b8a562f86560ad16 --- core/java/android/net/SntpClient.java | 9 ++++-- core/java/android/util/NtpTrustedTime.java | 31 ++++++++++++++++--- .../src/android/net/SntpClientTest.java | 3 +- .../server/NetworkTimeUpdateService.java | 6 ++-- .../NetworkTimeUpdateServiceShellCommand.java | 13 ++++++-- .../BandwidthEnforcementTestService.java | 6 ++-- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java index 0eb4cf3ecadf9..b05f7cf241e37 100644 --- a/core/java/android/net/SntpClient.java +++ b/core/java/android/net/SntpClient.java @@ -60,7 +60,7 @@ public class SntpClient { private static final int TRANSMIT_TIME_OFFSET = 40; private static final int NTP_PACKET_SIZE = 48; - private static final int NTP_PORT = 123; + public static final int STANDARD_NTP_PORT = 123; private static final int NTP_MODE_CLIENT = 3; private static final int NTP_MODE_SERVER = 4; private static final int NTP_MODE_BROADCAST = 5; @@ -108,18 +108,21 @@ public class SntpClient { * Sends an SNTP request to the given host and processes the response. * * @param host host name of the server. + * @param port port of the server. * @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup * time, and it applies to each individual query to the resolved addresses of * the NTP server. * @param network network over which to send the request. * @return true if the transaction was successful. */ - public boolean requestTime(String host, int timeout, Network network) { + public boolean requestTime(String host, int port, int timeout, Network network) { final Network networkForResolv = network.getPrivateDnsBypassingCopy(); try { final InetAddress[] addresses = networkForResolv.getAllByName(host); for (int i = 0; i < addresses.length; i++) { - if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true; + if (requestTime(addresses[i], port, timeout, networkForResolv)) { + return true; + } } } catch (UnknownHostException e) { Log.w(TAG, "Unknown host: " + host); diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java index aebc5e86605a9..01a037ae34950 100644 --- a/core/java/android/util/NtpTrustedTime.java +++ b/core/java/android/util/NtpTrustedTime.java @@ -138,6 +138,10 @@ public class NtpTrustedTime implements TrustedTime { @Nullable private String mHostnameForTests; + /** An in-memory config override for use during tests. */ + @Nullable + private Integer mPortForTests; + /** An in-memory config override for use during tests. */ @Nullable private Duration mTimeoutForTests; @@ -163,9 +167,11 @@ public class NtpTrustedTime implements TrustedTime { * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the * test value, i.e. so the normal value will be used next time. */ - public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) { + public void setServerConfigForTests( + @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) { synchronized (this) { mHostnameForTests = hostname; + mPortForTests = port; mTimeoutForTests = timeout; } } @@ -195,8 +201,9 @@ public class NtpTrustedTime implements TrustedTime { if (LOGD) Log.d(TAG, "forceRefresh() from cache miss"); final SntpClient client = new SntpClient(); final String serverName = connectionInfo.getServer(); + final int port = connectionInfo.getPort(); final int timeoutMillis = connectionInfo.getTimeoutMillis(); - if (client.requestTime(serverName, timeoutMillis, network)) { + if (client.requestTime(serverName, port, timeoutMillis, network)) { long ntpCertainty = client.getRoundTripTime() / 2; mTimeResult = new TimeResult( client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty); @@ -297,10 +304,12 @@ public class NtpTrustedTime implements TrustedTime { private static class NtpConnectionInfo { @NonNull private final String mServer; + private final int mPort; private final int mTimeoutMillis; - NtpConnectionInfo(@NonNull String server, int timeoutMillis) { + NtpConnectionInfo(@NonNull String server, int port, int timeoutMillis) { mServer = Objects.requireNonNull(server); + mPort = port; mTimeoutMillis = timeoutMillis; } @@ -309,6 +318,11 @@ public class NtpTrustedTime implements TrustedTime { return mServer; } + @NonNull + public int getPort() { + return mPort; + } + int getTimeoutMillis() { return mTimeoutMillis; } @@ -317,6 +331,7 @@ public class NtpTrustedTime implements TrustedTime { public String toString() { return "NtpConnectionInfo{" + "mServer='" + mServer + '\'' + + ", mPort='" + mPort + '\'' + ", mTimeoutMillis=" + mTimeoutMillis + '}'; } @@ -341,6 +356,13 @@ public class NtpTrustedTime implements TrustedTime { } } + final Integer port; + if (mPortForTests != null) { + port = mPortForTests; + } else { + port = SntpClient.STANDARD_NTP_PORT; + } + final int timeoutMillis; if (mTimeoutForTests != null) { timeoutMillis = (int) mTimeoutForTests.toMillis(); @@ -350,7 +372,8 @@ public class NtpTrustedTime implements TrustedTime { timeoutMillis = Settings.Global.getInt( resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis); } - return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis); + return TextUtils.isEmpty(hostname) ? null : + new NtpConnectionInfo(hostname, port, timeoutMillis); } /** Prints debug information. */ diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java index b400b9bf41dd1..1299d7ff2daea 100644 --- a/core/tests/coretests/src/android/net/SntpClientTest.java +++ b/core/tests/coretests/src/android/net/SntpClientTest.java @@ -293,7 +293,8 @@ public class SntpClientTest { @Test public void testDnsResolutionFailure() throws Exception { - assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork)); + assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", + SntpClient.STANDARD_NTP_PORT, 5000, mNetwork)); } @Test diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java index e0adee9fcb324..18306609acdff 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java @@ -196,13 +196,15 @@ public class NetworkTimeUpdateService extends Binder { * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the * test value, i.e. so the normal value will be used next time. */ - void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) { + void setServerConfigForTests( + @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) { mContext.enforceCallingPermission( android.Manifest.permission.SET_TIME, "set NTP server config for tests"); mLocalLog.log("Setting server config for tests: hostname=" + hostname + + ", port=" + port + ", timeout=" + timeout); - mTime.setServerConfigForTests(hostname, timeout); + mTime.setServerConfigForTests(hostname, port, timeout); } private void onPollNetworkTime(int event) { diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java index 464af01a009a1..d7504ceb9d4de 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java @@ -46,6 +46,7 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { */ private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config"; private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname"; + private static final String SET_SERVER_CONFIG_PORT_ARG = "--port"; private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis"; @NonNull @@ -87,6 +88,7 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { private int runSetServerConfig() { String hostname = null; + Integer port = null; Duration timeout = null; String opt; while ((opt = getNextArg()) != null) { @@ -95,6 +97,10 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { hostname = getNextArgRequired(); break; } + case SET_SERVER_CONFIG_PORT_ARG: { + port = Integer.parseInt(getNextArgRequired()); + break; + } case SET_SERVER_CONFIG_TIMEOUT_ARG: { timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired())); break; @@ -104,7 +110,7 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { } } } - mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout); + mNetworkTimeUpdateService.setServerConfigForTests(hostname, port, timeout); return 0; } @@ -120,8 +126,9 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand { pw.printf(" Refreshes the latest time. Prints whether it was successful.\n"); pw.printf(" %s\n", SHELL_COMMAND_SET_SERVER_CONFIG); pw.printf(" Sets the NTP server config for tests. The config is not persisted.\n"); - pw.printf(" Options: [%s ] [%s ]\n", - SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG); + pw.printf(" Options: [%s ] [%s ] [%s ]\n", + SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_PORT_ARG, + SET_SERVER_CONFIG_TIMEOUT_ARG); pw.printf(" Each key/value is optional and must be specified to override the\n"); pw.printf(" normal value, not specifying a key causes it to reset to the original.\n"); pw.println(); diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java index 35f1e585931bd..644d450a7a881 100644 --- a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java +++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java @@ -24,6 +24,8 @@ import android.net.SntpClient; import android.os.Environment; import android.util.Log; +import libcore.io.Streams; + import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; @@ -37,8 +39,6 @@ import java.net.InetAddress; import java.net.URL; import java.util.Random; -import libcore.io.Streams; - /* * Test Service that tries to connect to the web via different methods and outputs the results to * the log and a output file. @@ -146,7 +146,7 @@ public class BandwidthEnforcementTestService extends IntentService { final ConnectivityManager mCM = context.getSystemService(ConnectivityManager.class); final Network network = mCM.getActiveNetwork(); - if (client.requestTime("0.pool.ntp.org", 10000, network)) { + if (client.requestTime("0.pool.ntp.org", SntpClient.STANDARD_NTP_PORT, 10000, network)) { return true; } return false;