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(""