Merge "Move DhcpInfoTest to FrameworksNetCommonTests" into rvc-dev
diff --git a/tests/cts/net/jni/Android.bp b/tests/cts/net/jni/Android.bp
index baed48d..3953aeb 100644
--- a/tests/cts/net/jni/Android.bp
+++ b/tests/cts/net/jni/Android.bp
@@ -16,6 +16,7 @@
     name: "libnativedns_jni",
 
     srcs: ["NativeDnsJni.c"],
+    sdk_version: "current",
 
     shared_libs: [
         "libnativehelper_compat_libc++",
@@ -35,6 +36,7 @@
     name: "libnativemultinetwork_jni",
 
     srcs: ["NativeMultinetworkJni.cpp"],
+    sdk_version: "current",
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/tests/cts/net/jni/NativeDnsJni.c b/tests/cts/net/jni/NativeDnsJni.c
index 6d3d1c3..4ec800e 100644
--- a/tests/cts/net/jni/NativeDnsJni.c
+++ b/tests/cts/net/jni/NativeDnsJni.c
@@ -19,7 +19,12 @@
 #include <netdb.h>
 #include <stdio.h>
 #include <string.h>
-#include <utils/Log.h>
+
+#include <android/log.h>
+
+#define LOG_TAG "NativeDns-JNI"
+#define LOGD(fmt, ...) \
+        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
 
 const char *GoogleDNSIpV4Address="8.8.8.8";
 const char *GoogleDNSIpV4Address2="8.8.4.4";
@@ -33,7 +38,7 @@
     struct addrinfo *answer;
 
     int res = getaddrinfo(node, service, NULL, &answer);
-    ALOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
+    LOGD("getaddrinfo(www.google.com) gave res=%d (%s)", res, gai_strerror(res));
     if (res != 0) return JNI_FALSE;
 
     // check for v4 & v6
@@ -47,12 +52,12 @@
                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
                         buf, sizeof(buf));
                 foundv4 = 1;
-                ALOGD("  %s", buf);
+                LOGD("  %s", buf);
             } else if (current->ai_addr->sa_family == AF_INET6) {
                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
                         buf, sizeof(buf));
                 foundv6 = 1;
-                ALOGD("  %s", buf);
+                LOGD("  %s", buf);
             }
             current = current->ai_next;
         }
@@ -60,14 +65,14 @@
         freeaddrinfo(answer);
         answer = NULL;
         if (foundv4 != 1 && foundv6 != 1) {
-            ALOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
+            LOGD("getaddrinfo(www.google.com) didn't find either v4 or v6 address");
             return JNI_FALSE;
         }
     }
 
     node = "ipv6.google.com";
     res = getaddrinfo(node, service, NULL, &answer);
-    ALOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
+    LOGD("getaddrinfo(ipv6.google.com) gave res=%d", res);
     if (res != 0) return JNI_FALSE;
 
     {
@@ -79,12 +84,12 @@
             if (current->ai_addr->sa_family == AF_INET) {
                 inet_ntop(current->ai_family, &((struct sockaddr_in *)current->ai_addr)->sin_addr,
                         buf, sizeof(buf));
-                ALOGD("  %s", buf);
+                LOGD("  %s", buf);
                 foundv4 = 1;
             } else if (current->ai_addr->sa_family == AF_INET6) {
                 inet_ntop(current->ai_family, &((struct sockaddr_in6 *)current->ai_addr)->sin6_addr,
                         buf, sizeof(buf));
-                ALOGD("  %s", buf);
+                LOGD("  %s", buf);
                 foundv6 = 1;
             }
             current = current->ai_next;
@@ -93,7 +98,7 @@
         freeaddrinfo(answer);
         answer = NULL;
         if (foundv4 == 1 || foundv6 != 1) {
-            ALOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
+            LOGD("getaddrinfo(ipv6.google.com) didn't find only v6");
             return JNI_FALSE;
         }
     }
@@ -116,12 +121,12 @@
 
     res = getnameinfo((const struct sockaddr*)&sa4, sizeof(sa4), buf, sizeof(buf), NULL, 0, flags);
     if (res != 0) {
-        ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
+        LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV4Address, res,
             gai_strerror(res));
         return JNI_FALSE;
     }
     if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
-        ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
+        LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
             GoogleDNSIpV4Address, buf);
         return JNI_FALSE;
     }
@@ -129,12 +134,12 @@
     memset(buf, 0, sizeof(buf));
     res = getnameinfo((const struct sockaddr*)&sa6, sizeof(sa6), buf, sizeof(buf), NULL, 0, flags);
     if (res != 0) {
-        ALOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
+        LOGD("getnameinfo(%s (GoogleDNS) ) gave error %d (%s)", GoogleDNSIpV6Address2,
             res, gai_strerror(res));
         return JNI_FALSE;
     }
     if (strstr(buf, "google.com") == NULL && strstr(buf, "dns.google") == NULL) {
-        ALOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
+        LOGD("getnameinfo(%s (GoogleDNS) ) didn't return google.com or dns.google: %s",
             GoogleDNSIpV6Address2, buf);
         return JNI_FALSE;
     }
@@ -142,11 +147,11 @@
     // gethostbyname
     struct hostent *my_hostent = gethostbyname("www.youtube.com");
     if (my_hostent == NULL) {
-        ALOGD("gethostbyname(www.youtube.com) gave null response");
+        LOGD("gethostbyname(www.youtube.com) gave null response");
         return JNI_FALSE;
     }
     if ((my_hostent->h_addr_list == NULL) || (*my_hostent->h_addr_list == NULL)) {
-        ALOGD("gethostbyname(www.youtube.com) gave 0 addresses");
+        LOGD("gethostbyname(www.youtube.com) gave 0 addresses");
         return JNI_FALSE;
     }
     {
@@ -154,7 +159,7 @@
         while (*current != NULL) {
             char buf[256];
             inet_ntop(my_hostent->h_addrtype, *current, buf, sizeof(buf));
-            ALOGD("gethostbyname(www.youtube.com) gave %s", buf);
+            LOGD("gethostbyname(www.youtube.com) gave %s", buf);
             current++;
         }
     }
@@ -164,11 +169,11 @@
     inet_pton(AF_INET6, GoogleDNSIpV6Address, addr6);
     my_hostent = gethostbyaddr(addr6, sizeof(addr6), AF_INET6);
     if (my_hostent == NULL) {
-        ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
+        LOGD("gethostbyaddr(%s (GoogleDNS) ) gave null response", GoogleDNSIpV6Address);
         return JNI_FALSE;
     }
 
-    ALOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
+    LOGD("gethostbyaddr(%s (GoogleDNS) ) gave %s for name", GoogleDNSIpV6Address,
         my_hostent->h_name ? my_hostent->h_name : "null");
 
     if (my_hostent->h_name == NULL) return JNI_FALSE;
diff --git a/tests/cts/net/jni/NativeMultinetworkJni.cpp b/tests/cts/net/jni/NativeMultinetworkJni.cpp
index 2832c3d..cd94709 100644
--- a/tests/cts/net/jni/NativeMultinetworkJni.cpp
+++ b/tests/cts/net/jni/NativeMultinetworkJni.cpp
@@ -16,7 +16,6 @@
 
 
 #define LOG_TAG "MultinetworkApiTest"
-#include <utils/Log.h>
 
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
@@ -34,9 +33,13 @@
 
 #include <string>
 
+#include <android/log.h>
 #include <android/multinetwork.h>
 #include <nativehelper/JNIHelp.h>
 
+#define LOGD(fmt, ...) \
+        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
+
 #define EXPECT_GE(env, actual, expected, msg)                        \
     do {                                                             \
         if (actual < expected) {                                     \
@@ -138,7 +141,7 @@
     uint8_t buf[MAXPACKET] = {};
     int res = getAsyncResponse(env, fd, TIMEOUT_MS, &rcode, buf, MAXPACKET);
     if (res != expectedErrno) {
-        ALOGD("res:%d, expectedErrno = %d", res, expectedErrno);
+        LOGD("res:%d, expectedErrno = %d", res, expectedErrno);
         return (res > 0) ? -EREMOTEIO : res;
     }
     return 0;
@@ -326,7 +329,7 @@
     const int saved_errno = errno;
     freeaddrinfo(res);
 
-    ALOGD("android_getaddrinfofornetwork(%" PRIu64 ", %s) returned rval=%d errno=%d",
+    LOGD("android_getaddrinfofornetwork(%" PRIu64 ", %s) returned rval=%d errno=%d",
           handle, kHostname, rval, saved_errno);
     return rval == 0 ? 0 : -saved_errno;
 }
@@ -339,7 +342,7 @@
     errno = 0;
     int rval = android_setprocnetwork(handle);
     const int saved_errno = errno;
-    ALOGD("android_setprocnetwork(%" PRIu64 ") returned rval=%d errno=%d",
+    LOGD("android_setprocnetwork(%" PRIu64 ") returned rval=%d errno=%d",
           handle, rval, saved_errno);
     return rval == 0 ? 0 : -saved_errno;
 }
@@ -352,14 +355,14 @@
     errno = 0;
     int fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
     if (fd < 0) {
-        ALOGD("socket() failed, errno=%d", errno);
+        LOGD("socket() failed, errno=%d", errno);
         return -errno;
     }
 
     errno = 0;
     int rval = android_setsocknetwork(handle, fd);
     const int saved_errno = errno;
-    ALOGD("android_setprocnetwork(%" PRIu64 ", %d) returned rval=%d errno=%d",
+    LOGD("android_setprocnetwork(%" PRIu64 ", %d) returned rval=%d errno=%d",
           handle, fd, rval, saved_errno);
     close(fd);
     return rval == 0 ? 0 : -saved_errno;
@@ -404,7 +407,7 @@
     static const char kPort[] = "443";
     int rval = android_getaddrinfofornetwork(handle, kHostname, kPort, &kHints, &res);
     if (rval != 0) {
-        ALOGD("android_getaddrinfofornetwork(%llu, %s) returned rval=%d errno=%d",
+        LOGD("android_getaddrinfofornetwork(%llu, %s) returned rval=%d errno=%d",
               handle, kHostname, rval, errno);
         freeaddrinfo(res);
         return -errno;
@@ -413,14 +416,14 @@
     // Rely upon getaddrinfo sorting the best destination to the front.
     int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     if (fd < 0) {
-        ALOGD("socket(%d, %d, %d) failed, errno=%d",
+        LOGD("socket(%d, %d, %d) failed, errno=%d",
               res->ai_family, res->ai_socktype, res->ai_protocol, errno);
         freeaddrinfo(res);
         return -errno;
     }
 
     rval = android_setsocknetwork(handle, fd);
-    ALOGD("android_setprocnetwork(%llu, %d) returned rval=%d errno=%d",
+    LOGD("android_setprocnetwork(%llu, %d) returned rval=%d errno=%d",
           handle, fd, rval, errno);
     if (rval != 0) {
         close(fd);
@@ -430,7 +433,7 @@
 
     char addrstr[kSockaddrStrLen+1];
     sockaddr_ntop(res->ai_addr, res->ai_addrlen, addrstr, sizeof(addrstr));
-    ALOGD("Attempting connect() to %s ...", addrstr);
+    LOGD("Attempting connect() to %s ...", addrstr);
 
     rval = connect(fd, res->ai_addr, res->ai_addrlen);
     if (rval != 0) {
@@ -447,7 +450,7 @@
         return -errno;
     }
     sockaddr_ntop((const struct sockaddr *)&src_addr, sizeof(src_addr), addrstr, sizeof(addrstr));
-    ALOGD("... from %s", addrstr);
+    LOGD("... from %s", addrstr);
 
     // Don't let reads or writes block indefinitely.
     const struct timeval timeo = { 2, 0 };  // 2 seconds
@@ -479,7 +482,7 @@
         sent = send(fd, quic_packet, sizeof(quic_packet), 0);
         if (sent < (ssize_t)sizeof(quic_packet)) {
             errnum = errno;
-            ALOGD("send(QUIC packet) returned sent=%zd, errno=%d", sent, errnum);
+            LOGD("send(QUIC packet) returned sent=%zd, errno=%d", sent, errnum);
             close(fd);
             return -errnum;
         }
@@ -489,14 +492,14 @@
             break;
         } else {
             errnum = errno;
-            ALOGD("[%d/%d] recv(QUIC response) returned rcvd=%zd, errno=%d",
+            LOGD("[%d/%d] recv(QUIC response) returned rcvd=%zd, errno=%d",
                   i + 1, MAX_RETRIES, rcvd, errnum);
         }
     }
     if (rcvd < 9) {
-        ALOGD("QUIC UDP %s: sent=%zd but rcvd=%zd, errno=%d", kPort, sent, rcvd, errnum);
+        LOGD("QUIC UDP %s: sent=%zd but rcvd=%zd, errno=%d", kPort, sent, rcvd, errnum);
         if (rcvd <= 0) {
-            ALOGD("Does this network block UDP port %s?", kPort);
+            LOGD("Does this network block UDP port %s?", kPort);
         }
         close(fd);
         return -EPROTO;
@@ -504,7 +507,7 @@
 
     int conn_id_cmp = memcmp(quic_packet + 1, response + 1, 8);
     if (conn_id_cmp != 0) {
-        ALOGD("sent and received connection IDs do not match");
+        LOGD("sent and received connection IDs do not match");
         close(fd);
         return -EPROTO;
     }
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
index 0a80047..9d35705 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityDiagnosticsManagerTest.java
@@ -18,15 +18,17 @@
 
 import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
 
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.net.ConnectivityDiagnosticsManager;
 import android.net.NetworkRequest;
+import android.os.Build;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DevSdkIgnoreRunner;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -34,7 +36,8 @@
 
 import java.util.concurrent.Executor;
 
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
+@IgnoreUpTo(Build.VERSION_CODES.Q) // ConnectivityDiagnosticsManager did not exist in Q
 public class ConnectivityDiagnosticsManagerTest {
     private static final Executor INLINE_EXECUTOR = x -> x.run();
     private static final NetworkRequest DEFAULT_REQUEST = new NetworkRequest.Builder().build();
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index fa7e138..1ee08ff 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -639,11 +639,14 @@
         }
     }
 
-    private void waitForActiveNetworkMetered(boolean requestedMeteredness) throws Exception {
+    private void waitForActiveNetworkMetered(int targetTransportType, boolean requestedMeteredness)
+            throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         final NetworkCallback networkCallback = new NetworkCallback() {
             @Override
             public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
+                if (!nc.hasTransport(targetTransportType)) return;
+
                 final boolean metered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
                 if (metered == requestedMeteredness) {
                     latch.countDown();
@@ -709,7 +712,7 @@
     @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
     public void testGetMultipathPreference() throws Exception {
         final ContentResolver resolver = mContext.getContentResolver();
-        final Network network = ensureWifiConnected();
+        ensureWifiConnected();
         final String ssid = unquoteSSID(mWifiManager.getConnectionInfo().getSSID());
         final String oldMeteredSetting = getWifiMeteredStatus(ssid);
         final String oldMeteredMultipathPreference = Settings.Global.getString(
@@ -720,7 +723,11 @@
             Settings.Global.putString(resolver, NETWORK_METERED_MULTIPATH_PREFERENCE,
                     Integer.toString(newMeteredPreference));
             setWifiMeteredStatus(ssid, "true");
-            waitForActiveNetworkMetered(true);
+            waitForActiveNetworkMetered(TRANSPORT_WIFI, true);
+            // Wifi meterness changes from unmetered to metered will disconnect and reconnect since
+            // R.
+            final Network network = ensureWifiConnected();
+            assertEquals(ssid, unquoteSSID(mWifiManager.getConnectionInfo().getSSID()));
             assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
                     NET_CAPABILITY_NOT_METERED), false);
             assertMultipathPreferenceIsEventually(network, initialMeteredPreference,
@@ -736,7 +743,8 @@
                     oldMeteredPreference, newMeteredPreference);
 
             setWifiMeteredStatus(ssid, "false");
-            waitForActiveNetworkMetered(false);
+            // No disconnect from unmetered to metered.
+            waitForActiveNetworkMetered(TRANSPORT_WIFI, false);
             assertEquals(mCm.getNetworkCapabilities(network).hasCapability(
                     NET_CAPABILITY_NOT_METERED), true);
             assertMultipathPreferenceIsEventually(network, newMeteredPreference,
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 89d3dff..03b961b 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -180,7 +180,7 @@
     }
 
     private open class TestableNetworkAgent(
-        val looper: Looper,
+        looper: Looper,
         val nc: NetworkCapabilities,
         val lp: LinkProperties,
         conf: NetworkAgentConfig
diff --git a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
index 7514186..5e92b41 100644
--- a/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkRequestTest.java
@@ -29,11 +29,14 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
 import android.net.wifi.WifiNetworkSpecifier;
 import android.os.Build;
+import android.os.Process;
 import android.os.PatternMatcher;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -62,6 +65,18 @@
                 .hasCapability(NET_CAPABILITY_MMS));
         assertFalse(new NetworkRequest.Builder().removeCapability(NET_CAPABILITY_MMS).build()
                 .hasCapability(NET_CAPABILITY_MMS));
+
+        final NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
+        // Verify request has no capabilities
+        verifyNoCapabilities(nr);
+    }
+
+    private void verifyNoCapabilities(NetworkRequest nr) {
+        // NetworkCapabilities.mNetworkCapabilities is defined as type long
+        final int MAX_POSSIBLE_CAPABILITY = Long.SIZE;
+        for(int bit = 0; bit < MAX_POSSIBLE_CAPABILITY; bit++) {
+            assertFalse(nr.hasCapability(bit));
+        }
     }
 
     @Test
@@ -86,43 +101,96 @@
                 .build()
                 .getNetworkSpecifier();
         assertEquals(obtainedSpecifier, specifier);
+
+        assertNull(new NetworkRequest.Builder()
+                .clearCapabilities()
+                .build()
+                .getNetworkSpecifier());
+    }
+
+    @Test
+    @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testRequestorPackageName() {
+        assertNull(new NetworkRequest.Builder().build().getRequestorPackageName());
+        final String pkgName = "android.net.test";
+        final NetworkCapabilities nc = new NetworkCapabilities.Builder()
+                .setRequestorPackageName(pkgName)
+                .build();
+        final NetworkRequest nr = new NetworkRequest.Builder()
+                .setCapabilities(nc)
+                .build();
+        assertEquals(pkgName, nr.getRequestorPackageName());
+        assertNull(new NetworkRequest.Builder()
+                .clearCapabilities()
+                .build()
+                .getRequestorPackageName());
     }
 
     @Test
     @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testCanBeSatisfiedBy() {
-        final WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_LITERAL))
-                .setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
+        final TelephonyNetworkSpecifier specifier1 = new TelephonyNetworkSpecifier.Builder()
+                .setSubscriptionId(1234 /* subId */)
                 .build();
-        final WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
-                .setSsidPattern(new PatternMatcher(OTHER_SSID, PatternMatcher.PATTERN_LITERAL))
-                .setBssidPattern(ARBITRARY_ADDRESS, ARBITRARY_ADDRESS)
+        final TelephonyNetworkSpecifier specifier2 = new TelephonyNetworkSpecifier.Builder()
+                .setSubscriptionId(5678 /* subId */)
                 .build();
         final NetworkCapabilities cap = new NetworkCapabilities()
-                .addTransportType(TRANSPORT_WIFI)
-                .addCapability(NET_CAPABILITY_INTERNET);
-        final NetworkCapabilities capWithSp =
-                new NetworkCapabilities(cap).setNetworkSpecifier(specifier1);
-        final NetworkCapabilities cellCap = new NetworkCapabilities()
                 .addTransportType(TRANSPORT_CELLULAR)
                 .addCapability(NET_CAPABILITY_MMS)
                 .addCapability(NET_CAPABILITY_INTERNET);
-        final NetworkRequest request = new NetworkRequest.Builder()
-                .addTransportType(TRANSPORT_WIFI)
+        final NetworkCapabilities capDualTransport = new NetworkCapabilities(cap)
+                .addTransportType(TRANSPORT_VPN);
+        final NetworkCapabilities capWithSpecifier1 =
+                new NetworkCapabilities(cap).setNetworkSpecifier(specifier1);
+        final NetworkCapabilities capDiffTransportWithSpecifier1 = new NetworkCapabilities()
+                .addCapability(NET_CAPABILITY_INTERNET)
+                .addTransportType(TRANSPORT_VPN)
+                .setNetworkSpecifier(specifier1);
+
+        final NetworkRequest requestWithSpecifier1 = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_CELLULAR)
                 .addCapability(NET_CAPABILITY_INTERNET)
                 .setNetworkSpecifier(specifier1)
                 .build();
-        assertFalse(request.canBeSatisfiedBy(null));
-        assertFalse(request.canBeSatisfiedBy(new NetworkCapabilities()));
-        assertTrue(request.canBeSatisfiedBy(cap));
-        assertTrue(request.canBeSatisfiedBy(
-                new NetworkCapabilities(cap).addTransportType(TRANSPORT_VPN)));
-        assertTrue(request.canBeSatisfiedBy(capWithSp));
-        assertFalse(request.canBeSatisfiedBy(
+        assertFalse(requestWithSpecifier1.canBeSatisfiedBy(null));
+        assertFalse(requestWithSpecifier1.canBeSatisfiedBy(new NetworkCapabilities()));
+        assertTrue(requestWithSpecifier1.canBeSatisfiedBy(new NetworkCapabilities(cap)
+                .setNetworkSpecifier(new MatchAllNetworkSpecifier())));
+        assertTrue(requestWithSpecifier1.canBeSatisfiedBy(cap));
+        assertTrue(requestWithSpecifier1.canBeSatisfiedBy(capWithSpecifier1));
+        assertTrue(requestWithSpecifier1.canBeSatisfiedBy(capDualTransport));
+        assertFalse(requestWithSpecifier1.canBeSatisfiedBy(
                 new NetworkCapabilities(cap).setNetworkSpecifier(specifier2)));
-        assertFalse(request.canBeSatisfiedBy(cellCap));
-        assertEquals(request.canBeSatisfiedBy(capWithSp),
-                new NetworkCapabilities(capWithSp).satisfiedByNetworkCapabilities(capWithSp));
+
+        final NetworkRequest request = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_CELLULAR)
+                .addCapability(NET_CAPABILITY_INTERNET)
+                .build();
+        assertTrue(request.canBeSatisfiedBy(cap));
+        assertTrue(request.canBeSatisfiedBy(capWithSpecifier1));
+        assertTrue(request.canBeSatisfiedBy(
+                new NetworkCapabilities(cap).setNetworkSpecifier(specifier2)));
+        assertFalse(request.canBeSatisfiedBy(capDiffTransportWithSpecifier1));
+        assertTrue(request.canBeSatisfiedBy(capDualTransport));
+
+        assertEquals(requestWithSpecifier1.canBeSatisfiedBy(capWithSpecifier1),
+                new NetworkCapabilities(capWithSpecifier1)
+                    .satisfiedByNetworkCapabilities(capWithSpecifier1));
+    }
+
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+    public void testRequestorUid() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        // Verify default value is INVALID_UID
+        assertEquals(Process.INVALID_UID, new NetworkRequest.Builder()
+                 .setCapabilities(nc).build().getRequestorUid());
+
+        nc.setRequestorUid(1314);
+        final NetworkRequest nr = new NetworkRequest.Builder().setCapabilities(nc).build();
+        assertEquals(1314, nr.getRequestorUid());
+
+        assertEquals(Process.INVALID_UID, new NetworkRequest.Builder()
+                .clearCapabilities().build().getRequestorUid());
     }
 }
diff --git a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java b/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
index 577e24a..37bdd44 100755
--- a/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
+++ b/tests/cts/net/src/android/net/cts/TrafficStatsTest.java
@@ -16,11 +16,9 @@
 
 package android.net.cts;
 
-import android.content.pm.PackageManager;
 import android.net.NetworkStats;
 import android.net.TrafficStats;
 import android.os.Process;
-import android.os.SystemProperties;
 import android.platform.test.annotations.AppModeFull;
 import android.test.AndroidTestCase;
 import android.util.Log;
@@ -267,28 +265,6 @@
         assertTrue("ifrxp: " + ifaceRxPacketsBefore + " -> " + ifaceRxPacketsAfter,
                 totalRxPacketsAfter >= totalRxPacketsBefore + ifaceRxDeltaPackets);
 
-        // If the adb TCP port is opened, this test may be run by adb over network.
-        // Huge amount of data traffic might go through the network and accounted into total packets
-        // stats. The upper bound check would be meaningless.
-        // TODO: Consider precisely calculate the traffic accounted due to adb over network and
-        //       subtract it when checking upper bound instead of skip checking.
-        final PackageManager pm = mContext.getPackageManager();
-        if (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
-                || SystemProperties.getInt("service.adb.tcp.port", -1) > -1
-                || !pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY)) {
-            Log.i(LOG_TAG, "adb is running over the network, skip the upper bound check");
-        } else {
-            // Fudge by 132 packets of 1500 bytes not related to the test.
-            assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter,
-                    totalTxPacketsAfter <= totalTxPacketsBefore + uidTxDeltaPackets + 132);
-            assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter,
-                    totalRxPacketsAfter <= totalRxPacketsBefore + uidRxDeltaPackets + 132);
-            assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter,
-                    totalTxBytesAfter <= totalTxBytesBefore + uidTxDeltaBytes + 132 * 1500);
-            assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter,
-                    totalRxBytesAfter <= totalRxBytesBefore + uidRxDeltaBytes + 132 * 1500);
-        }
-
         // Localhost traffic should *not* count against mobile stats,
         // There might be some other traffic, but nowhere near 1MB.
         assertInRange("mtxp", mobileTxPacketsAfter, mobileTxPacketsBefore,
diff --git a/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java b/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java
index 82b3b14..5a70928 100644
--- a/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java
+++ b/tests/cts/net/src/android/net/cts/UrlQuerySanitizerTest.java
@@ -16,16 +16,38 @@
 
 package android.net.cts;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import android.net.UrlQuerySanitizer;
 import android.net.UrlQuerySanitizer.IllegalCharacterValueSanitizer;
 import android.net.UrlQuerySanitizer.ParameterValuePair;
 import android.net.UrlQuerySanitizer.ValueSanitizer;
-import android.test.AndroidTestCase;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.List;
 import java.util.Set;
 
-public class UrlQuerySanitizerTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UrlQuerySanitizerTest {
+    @Rule
+    public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
     private static final int ALL_OK = IllegalCharacterValueSanitizer.ALL_OK;
 
     // URL for test.
@@ -42,6 +64,7 @@
     private static final String AGE = "age";
     private static final String HEIGHT = "height";
 
+    @Test
     public void testUrlQuerySanitizer() {
         MockUrlQuerySanitizer uqs = new MockUrlQuerySanitizer();
         assertFalse(uqs.getAllowUnregisteredParamaters());
@@ -210,12 +233,14 @@
 
     }
 
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q) // Only fixed in R
     public void testScriptUrlOk_73822755() {
         ValueSanitizer sanitizer = new UrlQuerySanitizer.IllegalCharacterValueSanitizer(
                 UrlQuerySanitizer.IllegalCharacterValueSanitizer.SCRIPT_URL_OK);
         assertEquals("javascript:alert()", sanitizer.sanitize("javascript:alert()"));
     }
 
+    @Test @IgnoreUpTo(Build.VERSION_CODES.Q) // Only fixed in R
     public void testScriptUrlBlocked_73822755() {
         ValueSanitizer sanitizer = UrlQuerySanitizer.getUrlAndSpaceLegal();
         assertEquals("", sanitizer.sanitize("javascript:alert()"));
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 63de301..9f32403 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -25,8 +25,10 @@
     ],
 
     static_libs: [
+        "TetheringCommonTests",
         "TetheringIntegrationTestsLib",
         "compatibility-device-util-axt",
+        "net-tests-utils",
         "ctstestrunner-axt",
         "junit",
         "junit-params",
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index ccad14c..60f9400 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -15,20 +15,24 @@
  */
 package android.tethering.test;
 
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
-import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
 import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
+import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
+import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.app.UiAutomation;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -48,6 +52,8 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.ArrayTrackRecord;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -77,11 +83,21 @@
 
     private static final int DEFAULT_TIMEOUT_MS = 60_000;
 
+    private void adoptShellPermissionIdentity() {
+        final UiAutomation uiAutomation =
+                InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        uiAutomation.adoptShellPermissionIdentity();
+    }
+
+    private void dropShellPermissionIdentity() {
+        final UiAutomation uiAutomation =
+                InstrumentationRegistry.getInstrumentation().getUiAutomation();
+        uiAutomation.dropShellPermissionIdentity();
+    }
+
     @Before
     public void setUp() throws Exception {
-        InstrumentationRegistry.getInstrumentation()
-                .getUiAutomation()
-                .adoptShellPermissionIdentity();
+        adoptShellPermissionIdentity();
         mContext = InstrumentationRegistry.getContext();
         mTM = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE);
         mTetherChangeReceiver = new TetherChangeReceiver();
@@ -93,10 +109,9 @@
 
     @After
     public void tearDown() throws Exception {
+        mTM.stopAllTethering();
         mContext.unregisterReceiver(mTetherChangeReceiver);
-        InstrumentationRegistry.getInstrumentation()
-                .getUiAutomation()
-                .dropShellPermissionIdentity();
+        dropShellPermissionIdentity();
     }
 
     private class TetherChangeReceiver extends BroadcastReceiver {
@@ -202,15 +217,54 @@
         }
     }
 
-    private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
+    private static class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
+        private static int TIMEOUT_MS = 30_000;
+        public static class CallbackValue {
+            public final int error;
+
+            private CallbackValue(final int e) {
+                error = e;
+            }
+
+            public static class OnTetheringStarted extends CallbackValue {
+                OnTetheringStarted() { super(TETHER_ERROR_NO_ERROR); }
+            }
+
+            public static class OnTetheringFailed extends CallbackValue {
+                OnTetheringFailed(final int error) { super(error); }
+            }
+
+            @Override
+            public String toString() {
+                return String.format("%s(%d)", getClass().getSimpleName(), error);
+            }
+        }
+
+        private final ArrayTrackRecord<CallbackValue>.ReadHead mHistory =
+                new ArrayTrackRecord<CallbackValue>().newReadHead();
+
         @Override
         public void onTetheringStarted() {
-            // Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
+            mHistory.add(new CallbackValue.OnTetheringStarted());
         }
 
         @Override
         public void onTetheringFailed(final int error) {
-            fail("startTethering fail: " + error);
+            mHistory.add(new CallbackValue.OnTetheringFailed(error));
+        }
+
+        public void verifyTetheringStarted() {
+            final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
+            assertNotNull("No onTetheringStarted after " + TIMEOUT_MS + " ms", cv);
+            assertTrue("Fail start tethering:" + cv,
+                    cv instanceof CallbackValue.OnTetheringStarted);
+        }
+
+        public void expectTetheringFailed(final int expected) throws InterruptedException {
+            final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
+            assertNotNull("No onTetheringFailed after " + TIMEOUT_MS + " ms", cv);
+            assertTrue("Expect fail with error code " + expected + ", but received: " + cv,
+                (cv instanceof CallbackValue.OnTetheringFailed) && (cv.error == expected));
         }
     }
 
@@ -244,8 +298,10 @@
         mTetherChangeReceiver.expectNoActiveTethering(0 /** timeout */);
 
         final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
-        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), c -> c.run(),
-                startTetheringCallback);
+        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
+                c -> c.run() /* executor */, startTetheringCallback);
+        startTetheringCallback.verifyTetheringStarted();
+
         mTetherChangeReceiver.expectActiveTethering(wifiRegexs);
 
         mTM.stopTethering(TETHERING_WIFI);
@@ -277,6 +333,7 @@
 
     // Must poll the callback before looking at the member.
     private static class TestTetheringEventCallback implements TetheringEventCallback {
+        private static final int TIMEOUT_MS = 30_000;
         public enum CallbackType {
             ON_SUPPORTED,
             ON_UPSTREAM,
@@ -299,7 +356,10 @@
                 this.callbackParam2 = param2;
             }
         }
-        private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
+
+        private final ArrayTrackRecord<CallbackValue>.ReadHead mHistory =
+                new ArrayTrackRecord<CallbackValue>().newReadHead();
+
 
         private TetheringInterfaceRegexps mTetherableRegex;
         private List<String> mTetherableIfaces;
@@ -307,108 +367,96 @@
 
         @Override
         public void onTetheringSupported(boolean supported) {
-            mCallbacks.add(new CallbackValue(CallbackType.ON_SUPPORTED, null, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_SUPPORTED, null, 0));
         }
 
         @Override
         public void onUpstreamChanged(Network network) {
-            mCallbacks.add(new CallbackValue(CallbackType.ON_UPSTREAM, network, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_UPSTREAM, network, 0));
         }
 
         @Override
         public void onTetherableInterfaceRegexpsChanged(TetheringInterfaceRegexps reg) {
             mTetherableRegex = reg;
-            mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERABLE_REGEX, reg, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_REGEX, reg, 0));
         }
 
         @Override
         public void onTetherableInterfacesChanged(List<String> interfaces) {
             mTetherableIfaces = interfaces;
-            mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_TETHERABLE_IFACES, interfaces, 0));
         }
 
         @Override
         public void onTetheredInterfacesChanged(List<String> interfaces) {
             mTetheredIfaces = interfaces;
-            mCallbacks.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_TETHERED_IFACES, interfaces, 0));
         }
 
         @Override
         public void onError(String ifName, int error) {
-            mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
+            mHistory.add(new CallbackValue(CallbackType.ON_ERROR, ifName, error));
         }
 
         @Override
         public void onClientsChanged(Collection<TetheredClient> clients) {
-            mCallbacks.add(new CallbackValue(CallbackType.ON_CLIENTS, clients, 0));
+            mHistory.add(new CallbackValue(CallbackType.ON_CLIENTS, clients, 0));
         }
 
         @Override
         public void onOffloadStatusChanged(int status) {
-            mCallbacks.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
-        }
-
-        public CallbackValue pollCallback() {
-            try {
-                return mCallbacks.poll(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-                fail("Callback not seen");
-            }
-            return null;
+            mHistory.add(new CallbackValue(CallbackType.ON_OFFLOAD_STATUS, status, 0));
         }
 
         public void expectTetherableInterfacesChanged(@NonNull List<String> regexs) {
-            while (true) {
-                final CallbackValue cv = pollCallback();
-                if (cv == null) fail("No expected tetherable ifaces callback");
-                if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) continue;
-
-                final List<String> interfaces = (List<String>) cv.callbackParam;
-                if (isIfaceMatch(regexs, interfaces)) break;
-            }
+            assertNotNull("No expected tetherable ifaces callback", mHistory.poll(TIMEOUT_MS,
+                (cv) -> {
+                    if (cv.callbackType != CallbackType.ON_TETHERABLE_IFACES) return false;
+                    final List<String> interfaces = (List<String>) cv.callbackParam;
+                    return isIfaceMatch(regexs, interfaces);
+                }));
         }
 
         public void expectTetheredInterfacesChanged(@NonNull List<String> regexs) {
-            while (true) {
-                final CallbackValue cv = pollCallback();
-                if (cv == null) fail("No expected tethered ifaces callback");
-                if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) continue;
+            assertNotNull("No expected tethered ifaces callback", mHistory.poll(TIMEOUT_MS,
+                (cv) -> {
+                    if (cv.callbackType != CallbackType.ON_TETHERED_IFACES) return false;
 
-                final List<String> interfaces = (List<String>) cv.callbackParam;
+                    final List<String> interfaces = (List<String>) cv.callbackParam;
 
-                // Null regexs means no active tethering.
-                if (regexs == null) {
-                    if (interfaces.size() == 0) break;
-                } else if (isIfaceMatch(regexs, interfaces)) {
-                    break;
-                }
-            }
+                    // Null regexs means no active tethering.
+                    if (regexs == null) return interfaces.isEmpty();
+
+                    return isIfaceMatch(regexs, interfaces);
+                }));
         }
 
         public void expectCallbackStarted() {
+            int receivedBitMap = 0;
             // The each bit represent a type from CallbackType.ON_*.
             // Expect all of callbacks except for ON_ERROR.
-            final int expectedBitMap = 0x7f ^ (1 << CallbackType.ON_ERROR.ordinal());
-            int receivedBitMap = 0;
-            while (receivedBitMap != expectedBitMap) {
-                final CallbackValue cv = pollCallback();
+            final int expectedBitMap = 0xff ^ (1 << CallbackType.ON_ERROR.ordinal());
+            // Receive ON_ERROR on started callback is not matter. It just means tethering is
+            // failed last time, should able to continue the test this time.
+            while ((receivedBitMap & expectedBitMap) != expectedBitMap) {
+                final CallbackValue cv = mHistory.poll(TIMEOUT_MS, c -> true);
                 if (cv == null) {
                     fail("No expected callbacks, " + "expected bitmap: "
                             + expectedBitMap + ", actual: " + receivedBitMap);
                 }
-                receivedBitMap = receivedBitMap | (1 << cv.callbackType.ordinal());
+                receivedBitMap |= (1 << cv.callbackType.ordinal());
             }
         }
 
         public void expectOneOfOffloadStatusChanged(int... offloadStatuses) {
-            while (true) {
-                final CallbackValue cv = pollCallback();
-                if (cv == null) fail("No expected offload status change callback");
-                if (cv.callbackType != CallbackType.ON_OFFLOAD_STATUS) continue;
+            assertNotNull("No offload status changed", mHistory.poll(TIMEOUT_MS, (cv) -> {
+                if (cv.callbackType != CallbackType.ON_OFFLOAD_STATUS) return false;
 
                 final int status = (int) cv.callbackParam;
-                for (int offloadStatus : offloadStatuses) if (offloadStatus == status) return;
-            }
+                for (int offloadStatus : offloadStatuses) if (offloadStatus == status) return true;
+
+                return false;
+            }));
         }
 
         public TetheringInterfaceRegexps getTetheringInterfaceRegexps() {
@@ -424,52 +472,78 @@
         }
     }
 
-    @Test
-    public void testRegisterTetheringEventCallback() throws Exception {
-        if (!mTM.isTetheringSupported()) return;
-
+    private TestTetheringEventCallback registerTetheringEventCallback() {
         final TestTetheringEventCallback tetherEventCallback = new TestTetheringEventCallback();
 
-        mTM.registerTetheringEventCallback(c -> c.run(), tetherEventCallback);
+        mTM.registerTetheringEventCallback(c -> c.run() /* executor */, tetherEventCallback);
         tetherEventCallback.expectCallbackStarted();
-        tetherEventCallback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
 
-        final TetheringInterfaceRegexps tetherableRegexs =
-                tetherEventCallback.getTetheringInterfaceRegexps();
-        final List<String> wifiRegexs = tetherableRegexs.getTetherableWifiRegexs();
-        if (wifiRegexs.size() == 0) return;
+        return tetherEventCallback;
+    }
 
+    private void unregisterTetheringEventCallback(final TestTetheringEventCallback callback) {
+        mTM.unregisterTetheringEventCallback(callback);
+    }
+
+    private List<String> getWifiTetherableInterfaceRegexps(
+            final TestTetheringEventCallback callback) {
+        return callback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
+    }
+
+    private boolean isWifiTetheringSupported(final TestTetheringEventCallback callback) {
+        return !getWifiTetherableInterfaceRegexps(callback).isEmpty();
+    }
+
+    private void startWifiTethering(final TestTetheringEventCallback callback)
+            throws InterruptedException {
+        final List<String> wifiRegexs = getWifiTetherableInterfaceRegexps(callback);
         final boolean isIfaceAvailWhenNoTethering =
-                isIfaceMatch(wifiRegexs, tetherEventCallback.getTetherableInterfaces());
+                isIfaceMatch(wifiRegexs, callback.getTetherableInterfaces());
 
-        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), c -> c.run(),
-                new StartTetheringCallback());
+        final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
+        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
+                c -> c.run() /* executor */, startTetheringCallback);
+        startTetheringCallback.verifyTetheringStarted();
 
         // If interface is already available before starting tethering, the available callback may
         // not be sent after tethering enabled.
         if (!isIfaceAvailWhenNoTethering) {
-            tetherEventCallback.expectTetherableInterfacesChanged(wifiRegexs);
+            callback.expectTetherableInterfacesChanged(wifiRegexs);
         }
 
-        tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
-        tetherEventCallback.expectOneOfOffloadStatusChanged(
+        callback.expectTetheredInterfacesChanged(wifiRegexs);
+
+        callback.expectOneOfOffloadStatusChanged(
                 TETHER_HARDWARE_OFFLOAD_STARTED,
                 TETHER_HARDWARE_OFFLOAD_FAILED);
+    }
 
+    private void stopWifiTethering(final TestTetheringEventCallback callback) {
         mTM.stopTethering(TETHERING_WIFI);
+        callback.expectTetheredInterfacesChanged(null);
+        callback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
+    }
 
-        tetherEventCallback.expectTetheredInterfacesChanged(null);
-        tetherEventCallback.expectOneOfOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED);
-        mTM.unregisterTetheringEventCallback(tetherEventCallback);
+    @Test
+    public void testRegisterTetheringEventCallback() throws Exception {
+        if (!mTM.isTetheringSupported()) return;
+
+        final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
+
+        if (!isWifiTetheringSupported(tetherEventCallback)) return;
+
+        startWifiTethering(tetherEventCallback);
+
+        stopWifiTethering(tetherEventCallback);
+
+        unregisterTetheringEventCallback(tetherEventCallback);
     }
 
     @Test
     public void testGetTetherableInterfaceRegexps() {
         if (!mTM.isTetheringSupported()) return;
 
-        final TestTetheringEventCallback tetherEventCallback = new TestTetheringEventCallback();
-        mTM.registerTetheringEventCallback(c -> c.run(), tetherEventCallback);
-        tetherEventCallback.expectCallbackStarted();
+        final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
 
         final TetheringInterfaceRegexps tetherableRegexs =
                 tetherEventCallback.getTetheringInterfaceRegexps();
@@ -486,7 +560,35 @@
         wifiRegexs.forEach(s -> assertFalse(btRegexs.contains(s)));
         usbRegexs.forEach(s -> assertFalse(btRegexs.contains(s)));
 
-        mTM.unregisterTetheringEventCallback(tetherEventCallback);
+        unregisterTetheringEventCallback(tetherEventCallback);
+    }
+
+    @Test
+    public void testStopAllTethering() throws Exception {
+        if (!mTM.isTetheringSupported()) return;
+
+        final TestTetheringEventCallback tetherEventCallback = registerTetheringEventCallback();
+
+        if (!isWifiTetheringSupported(tetherEventCallback)) return;
+
+        // TODO: start ethernet tethering here when TetheringManagerTest is moved to
+        // TetheringIntegrationTest.
+
+        startWifiTethering(tetherEventCallback);
+
+        mTM.stopAllTethering();
+        tetherEventCallback.expectTetheredInterfacesChanged(null);
+
+        unregisterTetheringEventCallback(tetherEventCallback);
+    }
+
+    @Test
+    public void testEnableTetheringPermission() throws Exception {
+        dropShellPermissionIdentity();
+        final StartTetheringCallback startTetheringCallback = new StartTetheringCallback();
+        mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(),
+                c -> c.run() /* executor */, startTetheringCallback);
+        startTetheringCallback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
     }
 
     private class EntitlementResultListener implements OnTetheringEntitlementResultListener {