Merge "Set dialog background activity start mode on U+"
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index 9d0476e..33bd884 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -184,6 +184,23 @@
}
}
+ private static Set<String> setOf(@Nullable final String item) {
+ if (item == null) {
+ // Set.of will throw if item is null
+ final Set<String> set = new HashSet<>();
+ set.add(null);
+ return Collections.unmodifiableSet(set);
+ } else {
+ return Set.of(item);
+ }
+ }
+
+ private static void throwAtLeastU() {
+ if (SdkLevel.isAtLeastU()) {
+ throw new UnsupportedOperationException("Method not supported on Android U or above");
+ }
+ }
+
/**
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI.
@@ -195,22 +212,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
publicAlternatives = "Use {@code Builder} instead.")
public static NetworkTemplate buildTemplateMobileAll(@NonNull String subscriberId) {
- final Set<String> set;
- // Prevent from crash for b/273963543, where the OEMs still call into this method
- // with null subscriberId and get crashed.
- final int firstSdk = Build.VERSION.DEVICE_INITIAL_SDK_INT;
- if (firstSdk > Build.VERSION_CODES.TIRAMISU && subscriberId == null) {
- throw new IllegalArgumentException("buildTemplateMobileAll does not accept null"
- + " subscriberId on Android U devices or above");
- }
- if (subscriberId == null) {
- set = new HashSet<>();
- set.add(null);
- } else {
- set = Set.of(subscriberId);
- }
return new NetworkTemplate.Builder(MATCH_MOBILE).setMeteredness(METERED_YES)
- .setSubscriberIds(set).build();
+ .setSubscriberIds(setOf(subscriberId)).build();
}
/**
@@ -274,10 +277,9 @@
// TODO(b/270089918): Remove this method. This can only be done after there are no more callers,
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateBluetooth() {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "buildTemplateBluetooth is not supported on Android U devices or above");
- }
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
return new NetworkTemplate.Builder(MATCH_BLUETOOTH).build();
}
@@ -290,10 +292,9 @@
// TODO(b/270089918): Remove this method. This can only be done after there are no more callers,
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateProxy() {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "buildTemplateProxy is not supported on Android U devices or above");
- }
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
return new NetworkTemplate(MATCH_PROXY, null, null);
}
@@ -305,12 +306,10 @@
// TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "buildTemplateCarrierMetered is not supported on Android U devices or above");
- }
+ throwAtLeastU();
return new NetworkTemplate.Builder(MATCH_CARRIER)
- // Set.of will throw if subscriberId is null
+ // Set.of will throw if subscriberId is null, which is the historical
+ // behavior and should be preserved.
.setSubscriberIds(Set.of(subscriberId))
.setMeteredness(METERED_YES)
.build();
@@ -327,10 +326,7 @@
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
int ratType, int metered) {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException("buildTemplateMobileWithRatType is not "
- + "supported on Android U devices or above");
- }
+ throwAtLeastU();
return new NetworkTemplate.Builder(MATCH_MOBILE)
.setSubscriberIds(TextUtils.isEmpty(subscriberId)
? Collections.emptySet()
@@ -340,7 +336,6 @@
.build();
}
-
/**
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
* given key of the wifi network.
@@ -352,12 +347,12 @@
// TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException("buildTemplateWifi is not "
- + "supported on Android U devices or above");
- }
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
return new NetworkTemplate.Builder(MATCH_WIFI)
- // Set.of will throw if wifiNetworkKey is null
+ // Set.of will throw if wifiNetworkKey is null, which is the historical
+ // behavior and should be preserved.
.setWifiNetworkKeys(Set.of(wifiNetworkKey))
.build();
}
@@ -379,14 +374,9 @@
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey,
@Nullable String subscriberId) {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException("buildTemplateWifi is not "
- + "supported on Android U devices or above");
- }
+ throwAtLeastU();
return new NetworkTemplate.Builder(MATCH_WIFI)
- .setSubscriberIds(subscriberId == null
- ? Collections.emptySet()
- : Set.of(subscriberId))
+ .setSubscriberIds(setOf(subscriberId))
.setWifiNetworkKeys(wifiNetworkKey == null
? Collections.emptySet()
: Set.of(wifiNetworkKey))
@@ -471,10 +461,6 @@
if (matchRule == 6 || matchRule == 7) {
Log.e(TAG, "Use MATCH_MOBILE with empty subscriberIds or MATCH_WIFI with empty "
+ "wifiNetworkKeys instead of template with matchRule=" + matchRule);
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "Wildcard templates are not supported on Android U devices or above");
- }
}
}
@@ -508,10 +494,9 @@
getMeterednessForBackwardsCompatibility(matchRule),
ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
OEM_MANAGED_ALL);
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "This constructor is not supported on Android U devices or above");
- }
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
}
/** @hide */
@@ -526,10 +511,7 @@
this(getBackwardsCompatibleMatchRule(matchRule),
matchSubscriberIds == null ? new String[]{} : matchSubscriberIds,
matchWifiNetworkKeys, metered, roaming, defaultNetwork, ratType, oemManaged);
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "This constructor is not supported on Android U devices or above");
- }
+ throwAtLeastU();
}
/** @hide */
@@ -636,10 +618,9 @@
// including in OEM code which can access this by linking against the framework.
/** @hide */
public boolean isMatchRuleMobile() {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "isMatchRuleMobile is not supported on Android U devices or above");
- }
+ // TODO : this is part of hidden-o txt, does that mean it should be annotated with
+ // @UnsupportedAppUsage(maxTargetSdk = O) ? If yes, can't throwAtLeastU() lest apps
+ // targeting O- crash on those devices.
switch (mMatchRule) {
case MATCH_MOBILE:
// Old MATCH_MOBILE_WILDCARD
@@ -981,10 +962,7 @@
// TODO(b/273963543): Remove this method. This can only be done after there are no more callers,
// including in OEM code which can access this by linking against the framework.
public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
- if (SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException(
- "normalize is not supported on Android U devices or above");
- }
+ throwAtLeastU();
return normalizeImpl(template, mergedList);
}
diff --git a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
index dc5732f..6aa0fb4 100644
--- a/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
+++ b/service-t/native/libs/libnetworkstats/NetworkTraceHandler.cpp
@@ -101,6 +101,11 @@
void NetworkTraceHandler::InitPerfettoTracing() {
perfetto::TracingInitArgs args = {};
args.backends |= perfetto::kSystemBackend;
+ // The following line disables the Perfetto system consumer. Perfetto inlines
+ // the call to `Initialize` which allows the compiler to see that the branch
+ // with the SystemConsumerTracingBackend is not used. With LTO enabled, this
+ // strips the Perfetto consumer code and reduces the size of this binary by
+ // around 270KB total. Be careful when changing this value.
args.enable_system_consumer = false;
perfetto::Tracing::Initialize(args);
NetworkTraceHandler::RegisterDataSource();
diff --git a/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp
index 5cf6262..3de9897 100644
--- a/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp
+++ b/service-t/native/libs/libnetworkstats/NetworkTracePoller.cpp
@@ -99,9 +99,14 @@
ALOGW("Failed to disable tracing: %s", res.error().message().c_str());
}
- // make sure everything in the system has actually seen the 'false' we just wrote
+ // Make sure everything in the system has actually seen the 'false' we just
+ // wrote, things should now be well and truly disabled.
synchronizeKernelRCU();
- // things should now be well and truly disabled
+
+ // Drain remaining events from the ring buffer now that tracing is disabled.
+ // This prevents the next trace from seeing stale events and allows writing
+ // the last batch of events to Perfetto.
+ ConsumeAllLocked();
mTaskRunner.reset();
mRingBuffer.reset();
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index ad4596d..dfc9ffc 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -26,9 +26,14 @@
#include <nativehelper/JNIHelp.h>
#include <net/if.h>
#include <spawn.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/xattr.h>
#include <string>
+#include <unistd.h>
+#include <android-modules-utils/sdk_level.h>
#include <bpf/BpfMap.h>
#include <bpf/BpfUtils.h>
#include <netjniutils/netjniutils.h>
@@ -45,7 +50,97 @@
#define DEVICEPREFIX "v4-"
namespace android {
-static const char* kClatdPath = "/apex/com.android.tethering/bin/for-system/clatd";
+
+#define ALOGF(s ...) do { ALOGE(s); } while(0)
+
+enum verify { VERIFY_DIR, VERIFY_BIN, VERIFY_PROG, VERIFY_MAP_RO, VERIFY_MAP_RW };
+
+static void verifyPerms(const char * const path,
+ const mode_t mode, const uid_t uid, const gid_t gid,
+ const char * const ctxt,
+ const verify vtype) {
+ struct stat s = {};
+
+ if (lstat(path, &s)) ALOGF("lstat '%s' errno=%d", path, errno);
+ if (s.st_mode != mode) ALOGF("'%s' mode is 0%o != 0%o", path, s.st_mode, mode);
+ if (s.st_uid != uid) ALOGF("'%s' uid is %d != %d", path, s.st_uid, uid);
+ if (s.st_gid != gid) ALOGF("'%s' gid is %d != %d", path, s.st_gid, gid);
+
+ char b[255] = {};
+ int v = lgetxattr(path, "security.selinux", &b, sizeof(b));
+ if (v < 0) ALOGF("lgetxattr '%s' errno=%d", path, errno);
+ if (strncmp(ctxt, b, sizeof(b))) ALOGF("context of '%s' is '%s' != '%s'", path, b, ctxt);
+
+ int fd = -1;
+
+ switch (vtype) {
+ case VERIFY_DIR: return;
+ case VERIFY_BIN: return;
+ case VERIFY_PROG: fd = bpf::retrieveProgram(path); break;
+ case VERIFY_MAP_RO: fd = bpf::mapRetrieveRO(path); break;
+ case VERIFY_MAP_RW: fd = bpf::mapRetrieveRW(path); break;
+ }
+
+ if (fd < 0) ALOGF("bpf_obj_get '%s' failed, errno=%d", path, errno);
+
+ if (fd >= 0) close(fd);
+}
+
+#undef ALOGF
+
+bool isGsiImage() {
+ // this implementation matches 2 other places in the codebase (same function name too)
+ return !access("/system/system_ext/etc/init/init.gsi.rc", F_OK);
+}
+
+static const char* kClatdDir = "/apex/com.android.tethering/bin/for-system";
+static const char* kClatdBin = "/apex/com.android.tethering/bin/for-system/clatd";
+
+#define V(path, md, uid, gid, ctx, vtype) \
+ verifyPerms((path), (md), AID_ ## uid, AID_ ## gid, "u:object_r:" ctx ":s0", VERIFY_ ## vtype)
+
+static void verifyClatPerms() {
+ // We might run as part of tests instead of as part of system server
+ if (getuid() != AID_SYSTEM) return;
+
+ // First verify the clatd directory and binary,
+ // since this is built into the apex file system image,
+ // failures here are 99% likely to be build problems.
+ V(kClatdDir, S_IFDIR|0750, ROOT, SYSTEM, "system_file", DIR);
+ V(kClatdBin, S_IFREG|S_ISUID|S_ISGID|0755, CLAT, CLAT, "clatd_exec", BIN);
+
+ // Move on to verifying that the bpf programs and maps are as expected.
+ // This relies on the kernel and bpfloader.
+
+ // Clat BPF was only mainlined during T.
+ if (!modules::sdklevel::IsAtLeastT()) return;
+
+ // HACK: some old vendor kernels lack ~5.10 backport of 'bpffs selinux genfscon' support.
+ // This is *NOT* supported, but let's allow, at least for now, U+ GSI to boot on them.
+ // (without this hack pixel5 R vendor + U gsi breaks)
+ if (isGsiImage() && !bpf::isAtLeastKernelVersion(5, 10, 0)) return;
+
+ V("/sys/fs/bpf", S_IFDIR|S_ISVTX|0777, ROOT, ROOT, "fs_bpf", DIR);
+ V("/sys/fs/bpf/net_shared", S_IFDIR|S_ISVTX|0777, ROOT, ROOT, "fs_bpf_net_shared", DIR);
+
+ // pre-U we do not have selinux privs to getattr on bpf maps/progs
+ // so while the below *should* be as listed, we have no way to actually verify
+ if (!modules::sdklevel::IsAtLeastU()) return;
+
+#define V2(path, md, vtype) \
+ V("/sys/fs/bpf/net_shared/" path, (md), ROOT, SYSTEM, "fs_bpf_net_shared", vtype)
+
+ V2("prog_clatd_schedcls_egress4_clat_rawip", S_IFREG|0440, PROG);
+ V2("prog_clatd_schedcls_ingress6_clat_rawip", S_IFREG|0440, PROG);
+ V2("prog_clatd_schedcls_ingress6_clat_ether", S_IFREG|0440, PROG);
+ V2("map_clatd_clat_egress4_map", S_IFREG|0660, MAP_RW);
+ V2("map_clatd_clat_ingress6_map", S_IFREG|0660, MAP_RW);
+
+#undef V2
+
+}
+
+#undef V
static void throwIOException(JNIEnv* env, const char* msg, int error) {
jniThrowExceptionFmt(env, "java/io/IOException", "%s: %s", msg, strerror(error));
@@ -365,7 +460,7 @@
// 5. actually perform vfork/dup2/execve
pid_t pid;
- if (int ret = posix_spawn(&pid, kClatdPath, &fa, &attr, (char* const*)args, nullptr)) {
+ if (int ret = posix_spawn(&pid, kClatdBin, &fa, &attr, (char* const*)args, nullptr)) {
posix_spawnattr_destroy(&attr);
posix_spawn_file_actions_destroy(&fa);
throwIOException(env, "posix_spawn failed", ret);
@@ -484,6 +579,7 @@
};
int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env) {
+ verifyClatPerms();
return jniRegisterNativeMethods(env,
"android/net/connectivity/com/android/server/connectivity/ClatCoordinator",
gMethods, NELEM(gMethods));
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index 7e288c6..acce95d 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -52,6 +52,7 @@
import android.system.Os;
import android.system.OsConstants;
import android.system.StructTimeval;
+import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;
@@ -152,6 +153,9 @@
// TODO: Remove this when TCP polling design is replaced with callback.
private long mTestLowTcpPollingTimerUntilMs = 0;
+ private static final int MAX_EVENTS_LOGS = 40;
+ private final LocalLog mEventLog = new LocalLog(MAX_EVENTS_LOGS);
+
/**
* Information about a managed keepalive.
*
@@ -230,6 +234,7 @@
@Override
public void binderDied() {
+ mEventLog.log("Binder died : " + mCallback);
mConnectivityServiceHandler.post(() -> cleanupAutoOnOffKeepalive(this));
}
@@ -332,6 +337,7 @@
* @param autoKi the keepalive to resume
*/
public void handleMaybeResumeKeepalive(@NonNull AutomaticOnOffKeepalive autoKi) {
+ mEventLog.log("Resume keepalive " + autoKi.mCallback + " on " + autoKi.getNetwork());
// Might happen if the automatic keepalive was removed by the app just as the alarm fires.
if (!mAutomaticOnOffKeepalives.contains(autoKi)) return;
if (STATE_ALWAYS_ON == autoKi.mAutomaticOnOffState) {
@@ -377,6 +383,7 @@
* Handle stop all keepalives on the specific network.
*/
public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
+ mEventLog.log("Stop all keepalives on " + nai.network + " because " + reason);
mKeepaliveTracker.handleStopAllKeepalives(nai, reason);
final List<AutomaticOnOffKeepalive> matches =
CollectionUtils.filter(mAutomaticOnOffKeepalives, it -> it.mKi.getNai() == nai);
@@ -392,6 +399,7 @@
*/
public void handleStartKeepalive(Message message) {
final AutomaticOnOffKeepalive autoKi = (AutomaticOnOffKeepalive) message.obj;
+ mEventLog.log("Start keepalive " + autoKi.mCallback + " on " + autoKi.getNetwork());
mKeepaliveTracker.handleStartKeepalive(autoKi.mKi);
// Add automatic on/off request into list to track its life cycle.
@@ -410,9 +418,11 @@
private void handleResumeKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
mKeepaliveTracker.handleStartKeepalive(ki);
+ mEventLog.log("Resumed successfully keepalive " + ki.mCallback + " on " + ki.mNai);
}
private void handlePauseKeepalive(@NonNull final KeepaliveTracker.KeepaliveInfo ki) {
+ mEventLog.log("Suspend keepalive " + ki.mCallback + " on " + ki.mNai);
// TODO : mKT.handleStopKeepalive should take a KeepaliveInfo instead
mKeepaliveTracker.handleStopKeepalive(ki.getNai(), ki.getSlot(), SUCCESS_PAUSED);
}
@@ -421,6 +431,7 @@
* Handle stop keepalives on the specific network with given slot.
*/
public void handleStopKeepalive(@NonNull final AutomaticOnOffKeepalive autoKi, int reason) {
+ mEventLog.log("Stop keepalive " + autoKi.mCallback + " because " + reason);
// Stop the keepalive unless it was suspended. This includes the case where it's managed
// but enabled, and the case where it's always on.
if (autoKi.mAutomaticOnOffState != STATE_SUSPENDED) {
@@ -466,6 +477,11 @@
try {
final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
automaticOnOffKeepalives, underpinnedNetwork);
+ mEventLog.log("Start natt keepalive " + cb + " on " + nai.network
+ + " " + srcAddrString + ":" + srcPort
+ + " → " + dstAddrString + ":" + dstPort
+ + " auto=" + autoKi
+ + " underpinned=" + underpinnedNetwork);
mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
// TODO : move ConnectivityService#encodeBool to a static lib.
automaticOnOffKeepalives ? 1 : 0, 0, autoKi).sendToTarget();
@@ -496,6 +512,11 @@
try {
final AutomaticOnOffKeepalive autoKi = new AutomaticOnOffKeepalive(ki,
automaticOnOffKeepalives, underpinnedNetwork);
+ mEventLog.log("Start natt keepalive " + cb + " on " + nai.network
+ + " " + srcAddrString
+ + " → " + dstAddrString + ":" + dstPort
+ + " auto=" + autoKi
+ + " underpinned=" + underpinnedNetwork);
mConnectivityServiceHandler.obtainMessage(NetworkAgent.CMD_START_SOCKET_KEEPALIVE,
// TODO : move ConnectivityService#encodeBool to a static lib.
automaticOnOffKeepalives ? 1 : 0, 0, autoKi).sendToTarget();
@@ -550,6 +571,11 @@
pw.println(autoKi.toString());
}
pw.decreaseIndent();
+
+ pw.println("Events (most recent first):");
+ pw.increaseIndent();
+ mEventLog.reverseDump(pw);
+ pw.decreaseIndent();
}
/**
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 469fdba..db7f38c 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -403,6 +403,13 @@
// Wait until the link-local address can be used. Address flags are not available without
// elevated permissions, so check that bindSocket works.
PollingCheck.check("No usable v6 address on interface after $TIMEOUT_MS ms", TIMEOUT_MS) {
+ // To avoid race condition between socket connection succeeding and interface returning
+ // a non-empty address list. Verify that interface returns a non-empty list, before
+ // trying the socket connection.
+ if (NetworkInterface.getByName(ifaceName).interfaceAddresses.isEmpty()) {
+ return@check false
+ }
+
val sock = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
tryTest {
network.bindSocket(sock)
diff --git a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index cbe54f8..1a780a7 100644
--- a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -66,7 +66,6 @@
InetAddress[] addresses;
try {
addresses = InetAddress.getAllByName(TEST_HOST);
- mTestHostAddress = addresses[0];
} catch (UnknownHostException uhe) {
throw new AssertionError(
"Unable to test SSLCertificateSocketFactory: cannot resolve " + TEST_HOST, uhe);
@@ -76,10 +75,11 @@
.map(addr -> new InetSocketAddress(addr, HTTPS_PORT))
.collect(Collectors.toList());
- // Find the local IP address which will be used to connect to TEST_HOST.
+ // Find the local and remote IP addresses which will be used to connect to TEST_HOST.
try {
Socket testSocket = new Socket(TEST_HOST, HTTPS_PORT);
mLocalAddress = testSocket.getLocalAddress();
+ mTestHostAddress = testSocket.getInetAddress();
testSocket.close();
} catch (IOException ioe) {
throw new AssertionError(""