Merge "bpf: Add interface index to BPF devmap"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 4eafc2a..79c2b9d 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -30,6 +30,7 @@
         ":services-tethering-shared-srcs",
     ],
     static_libs: [
+        "NetworkStackApiStableShims",
         "androidx.annotation_annotation",
         "modules-utils-build",
         "netlink-client",
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index df9e12a..0e8b2b5 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -2040,8 +2040,7 @@
     }
 
     private void startTrackDefaultNetwork() {
-        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest(),
-                mEntitlementMgr);
+        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mEntitlementMgr);
     }
 
     /** Get the latest value of the tethering entitlement check. */
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 45b9141..7df9475 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -20,7 +20,6 @@
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.net.INetd;
-import android.net.NetworkRequest;
 import android.net.ip.IpServer;
 import android.net.util.SharedLog;
 import android.os.Handler;
@@ -99,11 +98,6 @@
     }
 
     /**
-     * Get the NetworkRequest that should be fulfilled by the default network.
-     */
-    public abstract NetworkRequest getDefaultNetworkRequest();
-
-    /**
      * Get a reference to the EntitlementManager to be used by tethering.
      */
     public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 745ebd0..5ab3401 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -35,8 +35,6 @@
 import android.net.INetworkStackConnector;
 import android.net.ITetheringConnector;
 import android.net.ITetheringEventCallback;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
 import android.net.NetworkStack;
 import android.net.TetheringRequestParcel;
 import android.net.dhcp.DhcpServerCallbacks;
@@ -307,19 +305,6 @@
     public TetheringDependencies makeTetheringDependencies() {
         return new TetheringDependencies() {
             @Override
-            public NetworkRequest getDefaultNetworkRequest() {
-                // TODO: b/147280869, add a proper system API to replace this.
-                final NetworkRequest trackDefaultRequest = new NetworkRequest.Builder()
-                        .clearCapabilities()
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                        .build();
-                return trackDefaultRequest;
-            }
-
-            @Override
             public Looper getTetheringLooper() {
                 final HandlerThread tetherThread = new HandlerThread("android.tethering");
                 tetherThread.start();
diff --git a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 9de4c87..e615334 100644
--- a/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -47,6 +47,9 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.StateMachine;
+import com.android.networkstack.apishim.ConnectivityManagerShimImpl;
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -142,33 +145,28 @@
         mWhat = what;
         mLocalPrefixes = new HashSet<>();
         mIsDefaultCellularUpstream = false;
-    }
-
-    @VisibleForTesting
-    public UpstreamNetworkMonitor(
-            ConnectivityManager cm, StateMachine tgt, SharedLog log, int what) {
-        this((Context) null, tgt, log, what);
-        mCM = cm;
+        mCM = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     /**
-     * Tracking the system default network. This method should be called when system is ready.
+     * Tracking the system default network. This method should be only called once when system is
+     * ready, and the callback is never unregistered.
      *
-     * @param defaultNetworkRequest should be the same as ConnectivityService default request
      * @param entitle a EntitlementManager object to communicate between EntitlementManager and
      * UpstreamNetworkMonitor
      */
-    public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest,
-            EntitlementManager entitle) {
-
-        // defaultNetworkRequest is not really a "request", just a way of tracking the system
-        // default network. It's guaranteed not to actually bring up any networks because it's
-        // the should be the same request as the ConnectivityService default request, and thus
-        // shares fate with it. We can't use registerDefaultNetworkCallback because it will not
-        // track the system default network if there is a VPN that applies to our UID.
-        if (mDefaultNetworkCallback == null) {
-            mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
-            cm().requestNetwork(defaultNetworkRequest, mDefaultNetworkCallback, mHandler);
+    public void startTrackDefaultNetwork(EntitlementManager entitle) {
+        if (mDefaultNetworkCallback != null) {
+            Log.wtf(TAG, "default network callback is already registered");
+            return;
+        }
+        ConnectivityManagerShim mCmShim = ConnectivityManagerShimImpl.newInstance(mContext);
+        mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
+        try {
+            mCmShim.registerSystemDefaultNetworkCallback(mDefaultNetworkCallback, mHandler);
+        } catch (UnsupportedApiLevelException e) {
+            Log.wtf(TAG, "registerSystemDefaultNetworkCallback is not supported");
+            return;
         }
         if (mEntitlementMgr == null) {
             mEntitlementMgr = entitle;
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index fe4e696..de94cba 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
 import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.TETHER_PRIVILEGED;
@@ -121,7 +122,7 @@
         // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive
         // tethered client callbacks.
         mUiAutomation.adoptShellPermissionIdentity(
-                MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED);
+                MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, TETHER_PRIVILEGED, ACCESS_NETWORK_STATE);
         mRunTests = mTm.isTetheringSupported() && mEm != null;
         assumeTrue(mRunTests);
 
diff --git a/Tethering/tests/jarjar-rules.txt b/Tethering/tests/jarjar-rules.txt
index c99ff7f..9cb143e 100644
--- a/Tethering/tests/jarjar-rules.txt
+++ b/Tethering/tests/jarjar-rules.txt
@@ -1,8 +1,8 @@
 # Don't jar-jar the entire package because this test use some
 # internal classes (like ArrayUtils in com.android.internal.util)
 rule com.android.internal.util.BitUtils* com.android.networkstack.tethering.util.BitUtils@1
-rule com.android.internal.util.IndentingPrintWriter.java* com.android.networkstack.tethering.util.IndentingPrintWriter.java@1
-rule com.android.internal.util.IState.java* com.android.networkstack.tethering.util.IState.java@1
+rule com.android.internal.util.IndentingPrintWriter* com.android.networkstack.tethering.util.IndentingPrintWriter@1
+rule com.android.internal.util.IState* com.android.networkstack.tethering.util.IState@1
 rule com.android.internal.util.MessageUtils* com.android.networkstack.tethering.util.MessageUtils@1
 rule com.android.internal.util.State* com.android.networkstack.tethering.util.State@1
 rule com.android.internal.util.StateMachine* com.android.networkstack.tethering.util.StateMachine@1
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index ce52ae2..9bd82f9 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -177,87 +177,65 @@
         return offload;
     }
 
-    @Test
-    public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
+    @NonNull
+    private OffloadController startOffloadController(boolean expectStart)
+            throws Exception {
         setupFunctioningHardwareInterface();
-        when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
-        assertThrows(SettingNotFoundException.class, () ->
-                Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
         final OffloadController offload = makeOffloadController();
         offload.start();
 
         final InOrder inOrder = inOrder(mHardware);
         inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
-        inOrder.verify(mHardware, never()).initOffloadConfig();
-        inOrder.verify(mHardware, never()).initOffloadControl(
+        inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadConfig();
+        inOrder.verify(mHardware, times(expectStart ? 1 : 0)).initOffloadControl(
                 any(OffloadHardwareInterface.ControlCallback.class));
         inOrder.verifyNoMoreInteractions();
+        // Clear counters only instead of whole mock to preserve the mocking setup.
+        clearInvocations(mHardware);
+        return offload;
+    }
+
+    private void stopOffloadController(final OffloadController offload) throws Exception {
+        final InOrder inOrder = inOrder(mHardware);
+        offload.stop();
+        inOrder.verify(mHardware, times(1)).stopOffloadControl();
+        inOrder.verifyNoMoreInteractions();
+        reset(mHardware);
+    }
+
+    @Test
+    public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
+        when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
+        assertThrows(SettingNotFoundException.class, () ->
+                Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
+        startOffloadController(false /*expectStart*/);
     }
 
     @Test
     public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
-        setupFunctioningHardwareInterface();
         when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
         assertThrows(SettingNotFoundException.class, () ->
                 Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
-
-        final InOrder inOrder = inOrder(mHardware);
-        inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
-        inOrder.verify(mHardware, times(1)).initOffloadConfig();
-        inOrder.verify(mHardware, times(1)).initOffloadControl(
-                any(OffloadHardwareInterface.ControlCallback.class));
-        inOrder.verifyNoMoreInteractions();
+        startOffloadController(true /*expectStart*/);
     }
 
     @Test
     public void testSettingsAllowsStart() throws Exception {
-        setupFunctioningHardwareInterface();
         Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
-
-        final InOrder inOrder = inOrder(mHardware);
-        inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
-        inOrder.verify(mHardware, times(1)).initOffloadConfig();
-        inOrder.verify(mHardware, times(1)).initOffloadControl(
-                any(OffloadHardwareInterface.ControlCallback.class));
-        inOrder.verifyNoMoreInteractions();
+        startOffloadController(true /*expectStart*/);
     }
 
     @Test
     public void testSettingsDisablesStart() throws Exception {
-        setupFunctioningHardwareInterface();
         Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1);
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
-
-        final InOrder inOrder = inOrder(mHardware);
-        inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
-        inOrder.verify(mHardware, never()).initOffloadConfig();
-        inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
-        inOrder.verifyNoMoreInteractions();
+        startOffloadController(false /*expectStart*/);
     }
 
     @Test
     public void testSetUpstreamLinkPropertiesWorking() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
-
-        final InOrder inOrder = inOrder(mHardware);
-        inOrder.verify(mHardware, times(1)).getDefaultTetherOffloadDisabled();
-        inOrder.verify(mHardware, times(1)).initOffloadConfig();
-        inOrder.verify(mHardware, times(1)).initOffloadControl(
-                any(OffloadHardwareInterface.ControlCallback.class));
-        inOrder.verifyNoMoreInteractions();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         // In reality, the UpstreamNetworkMonitor would have passed down to us
         // a covering set of local prefixes representing a minimum essential
@@ -271,6 +249,7 @@
             minimumLocalPrefixes.add(new IpPrefix(s));
         }
         offload.setLocalPrefixes(minimumLocalPrefixes);
+        final InOrder inOrder = inOrder(mHardware);
         inOrder.verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
         ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
         assertEquals(4, localPrefixes.size());
@@ -425,11 +404,9 @@
 
     @Test
     public void testGetForwardedStats() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         final String ethernetIface = "eth1";
         final String mobileIface = "rmnet_data0";
@@ -439,7 +416,7 @@
         when(mHardware.getForwardedStats(eq(mobileIface))).thenReturn(
                 new ForwardedStats(999, 99999));
 
-        InOrder inOrder = inOrder(mHardware);
+        final InOrder inOrder = inOrder(mHardware);
 
         final LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(ethernetIface);
@@ -517,11 +494,9 @@
 
     @Test
     public void testSetInterfaceQuota() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         final String ethernetIface = "eth1";
         final String mobileIface = "rmnet_data0";
@@ -581,11 +556,9 @@
 
     @Test
     public void testDataLimitCallback() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
         callback.onStoppedLimitReached();
@@ -594,17 +567,10 @@
 
     @Test
     public void testAddRemoveDownstreams() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
-
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
         final InOrder inOrder = inOrder(mHardware);
-        inOrder.verify(mHardware, times(1)).initOffloadConfig();
-        inOrder.verify(mHardware, times(1)).initOffloadControl(
-                any(OffloadHardwareInterface.ControlCallback.class));
-        inOrder.verifyNoMoreInteractions();
 
         // Tethering makes several calls to setLocalPrefixes() before add/remove
         // downstream calls are made. This is not tested here; only the behavior
@@ -668,11 +634,9 @@
 
     @Test
     public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         // Pretend to set a few different upstreams (only the interface name
         // matters for this test; we're ignoring IP and route information).
@@ -701,11 +665,9 @@
     @Test
     public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters()
             throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
-
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         // Pretend to set a few different upstreams (only the interface name
         // matters for this test; we're ignoring IP and route information).
@@ -780,11 +742,10 @@
 
     @Test
     public void testOnSetAlert() throws Exception {
-        setupFunctioningHardwareInterface();
         enableOffload();
         setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
-        final OffloadController offload = makeOffloadController();
-        offload.start();
+        final OffloadController offload =
+                startOffloadController(true /*expectStart*/);
 
         // Initialize with fake eth upstream.
         final String ethernetIface = "eth1";
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
index df82d7c..6090213 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TestConnectivityManager.java
@@ -16,6 +16,10 @@
 
 package com.android.networkstack.tethering;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
@@ -64,12 +68,13 @@
     public static final boolean CALLBACKS_FIRST = true;
 
     final Map<NetworkCallback, NetworkRequestInfo> mAllCallbacks = new ArrayMap<>();
+    // This contains the callbacks tracking the system default network, whether it's registered
+    // with registerSystemDefaultNetworkCallback (S+) or with a custom request (R-).
     final Map<NetworkCallback, NetworkRequestInfo> mTrackingDefault = new ArrayMap<>();
     final Map<NetworkCallback, NetworkRequestInfo> mListening = new ArrayMap<>();
     final Map<NetworkCallback, NetworkRequestInfo> mRequested = new ArrayMap<>();
     final Map<NetworkCallback, Integer> mLegacyTypeMap = new ArrayMap<>();
 
-    private final NetworkRequest mDefaultRequest;
     private final Context mContext;
 
     private int mNetworkId = 100;
@@ -80,13 +85,10 @@
      * @param ctx the context to use. Must be a fake or a mock because otherwise the test will
      *            attempt to send real broadcasts and resulting in permission denials.
      * @param svc an IConnectivityManager. Should be a fake or a mock.
-     * @param defaultRequest the default NetworkRequest that will be used by Tethering.
      */
-    public TestConnectivityManager(Context ctx, IConnectivityManager svc,
-            NetworkRequest defaultRequest) {
+    public TestConnectivityManager(Context ctx, IConnectivityManager svc) {
         super(ctx, svc);
         mContext = ctx;
-        mDefaultRequest = defaultRequest;
     }
 
     class NetworkRequestInfo {
@@ -181,11 +183,19 @@
         makeDefaultNetwork(agent, BROADCAST_FIRST, null /* inBetween */);
     }
 
+    static boolean looksLikeDefaultRequest(NetworkRequest req) {
+        return req.hasCapability(NET_CAPABILITY_INTERNET)
+                && !req.hasCapability(NET_CAPABILITY_DUN)
+                && !req.hasTransport(TRANSPORT_CELLULAR);
+    }
+
     @Override
     public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
         assertFalse(mAllCallbacks.containsKey(cb));
         mAllCallbacks.put(cb, new NetworkRequestInfo(req, h));
-        if (mDefaultRequest.equals(req)) {
+        // For R- devices, Tethering will invoke this function in 2 cases, one is to request mobile
+        // network, the other is to track system default network.
+        if (looksLikeDefaultRequest(req)) {
             assertFalse(mTrackingDefault.containsKey(cb));
             mTrackingDefault.put(cb, new NetworkRequestInfo(req, h));
         } else {
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index fedeeeb..2bc7fc4 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -26,7 +26,6 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
-import static android.net.ConnectivityManager.TYPE_NONE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -73,7 +72,6 @@
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.argThat;
@@ -274,8 +272,6 @@
     private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
 
     private TestConnectivityManager mCm;
-    private NetworkRequest mNetworkRequest;
-    private NetworkCallback mDefaultNetworkCallback;
 
     private class TestContext extends BroadcastInterceptingContext {
         TestContext(Context base) {
@@ -450,11 +446,6 @@
         }
 
         @Override
-        public NetworkRequest getDefaultNetworkRequest() {
-            return mNetworkRequest;
-        }
-
-        @Override
         public EntitlementManager getEntitlementManager(Context ctx, Handler h, SharedLog log,
                 Runnable callback) {
             mEntitleMgr = spy(super.getEntitlementManager(ctx, h, log, callback));
@@ -645,15 +636,7 @@
         mServiceContext.registerReceiver(mBroadcastReceiver,
                 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
 
-        // TODO: add NOT_VCN_MANAGED here, but more importantly in the production code.
-        // TODO: even better, change TetheringDependencies.getDefaultNetworkRequest() to use
-        // registerSystemDefaultNetworkCallback() on S and above.
-        NetworkCapabilities defaultCaps = new NetworkCapabilities()
-                .addCapability(NET_CAPABILITY_INTERNET);
-        mNetworkRequest = new NetworkRequest(defaultCaps, TYPE_NONE, 1 /* requestId */,
-                NetworkRequest.Type.REQUEST);
-        mCm = spy(new TestConnectivityManager(mServiceContext, mock(IConnectivityManager.class),
-                mNetworkRequest));
+        mCm = spy(new TestConnectivityManager(mServiceContext, mock(IConnectivityManager.class)));
 
         mTethering = makeTethering();
         verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any());
@@ -793,15 +776,13 @@
     }
 
     private void verifyDefaultNetworkRequestFiled() {
-        ArgumentCaptor<NetworkCallback> captor = ArgumentCaptor.forClass(NetworkCallback.class);
-        verify(mCm, times(1)).requestNetwork(eq(mNetworkRequest),
-                captor.capture(), any(Handler.class));
-        mDefaultNetworkCallback = captor.getValue();
-        assertNotNull(mDefaultNetworkCallback);
-
+        ArgumentCaptor<NetworkRequest> reqCaptor = ArgumentCaptor.forClass(NetworkRequest.class);
+        verify(mCm, times(1)).requestNetwork(reqCaptor.capture(),
+                any(NetworkCallback.class), any(Handler.class));
+        assertTrue(TestConnectivityManager.looksLikeDefaultRequest(reqCaptor.getValue()));
         // The default network request is only ever filed once.
         verifyNoMoreInteractions(mCm);
-        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mNetworkRequest, mEntitleMgr);
+        mUpstreamNetworkMonitor.startTrackDefaultNetwork(mEntitleMgr);
         verifyNoMoreInteractions(mCm);
     }
 
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
index cee0365..ce4ba85 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/UpstreamNetworkMonitorTest.java
@@ -29,10 +29,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
-import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -66,6 +66,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -83,10 +84,6 @@
     private static final boolean INCLUDES = true;
     private static final boolean EXCLUDES = false;
 
-    // Actual contents of the request don't matter for this test. The lack of
-    // any specific TRANSPORT_* is sufficient to identify this request.
-    private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build();
-
     private static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities.Builder()
             .addTransportType(TRANSPORT_CELLULAR).addCapability(NET_CAPABILITY_INTERNET).build();
     private static final NetworkCapabilities DUN_CAPABILITIES = new NetworkCapabilities.Builder()
@@ -113,9 +110,10 @@
         when(mLog.forSubComponent(anyString())).thenReturn(mLog);
         when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
 
-        mCM = spy(new TestConnectivityManager(mContext, mCS, sDefaultRequest));
+        mCM = spy(new TestConnectivityManager(mContext, mCS));
+        when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))).thenReturn(mCM);
         mSM = new TestStateMachine(mLooper.getLooper());
-        mUNM = new UpstreamNetworkMonitor(mCM, mSM, mLog, EVENT_UNM_UPDATE);
+        mUNM = new UpstreamNetworkMonitor(mContext, mSM, mLog, EVENT_UNM_UPDATE);
     }
 
     @After public void tearDown() throws Exception {
@@ -146,7 +144,7 @@
     @Test
     public void testDefaultNetworkIsTracked() throws Exception {
         assertTrue(mCM.hasNoCallbacks());
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
 
         mUNM.startObserveAllNetworks();
         assertEquals(1, mCM.mTrackingDefault.size());
@@ -159,7 +157,7 @@
     public void testListensForAllNetworks() throws Exception {
         assertTrue(mCM.mListening.isEmpty());
 
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
         mUNM.startObserveAllNetworks();
         assertFalse(mCM.mListening.isEmpty());
         assertTrue(mCM.isListeningForAll());
@@ -170,9 +168,17 @@
 
     @Test
     public void testCallbacksRegistered() {
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
+        // Verify the fired default request matches expectation.
+        final ArgumentCaptor<NetworkRequest> requestCaptor =
+                ArgumentCaptor.forClass(NetworkRequest.class);
         verify(mCM, times(1)).requestNetwork(
-                eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class));
+                requestCaptor.capture(), any(NetworkCallback.class), any(Handler.class));
+        // For R- devices, Tethering will invoke this function in 2 cases, one is to
+        // request mobile network, the other is to track system default network. Verify
+        // the request is the one tracks default network.
+        assertTrue(TestConnectivityManager.looksLikeDefaultRequest(requestCaptor.getValue()));
+
         mUNM.startObserveAllNetworks();
         verify(mCM, times(1)).registerNetworkCallback(
                 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
@@ -293,7 +299,7 @@
         final Collection<Integer> preferredTypes = new ArrayList<>();
         preferredTypes.add(TYPE_WIFI);
 
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
         mUNM.startObserveAllNetworks();
         // There are no networks, so there is nothing to select.
         assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
@@ -366,7 +372,7 @@
 
     @Test
     public void testGetCurrentPreferredUpstream() throws Exception {
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
         mUNM.startObserveAllNetworks();
         mUNM.setUpstreamConfig(true /* autoUpstream */, false /* dunRequired */);
         mUNM.setTryCell(true);
@@ -438,7 +444,7 @@
 
     @Test
     public void testLocalPrefixes() throws Exception {
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
         mUNM.startObserveAllNetworks();
 
         // [0] Test minimum set of local prefixes.
@@ -549,7 +555,7 @@
         // Mobile has higher pirority than wifi.
         preferredTypes.add(TYPE_MOBILE_HIPRI);
         preferredTypes.add(TYPE_WIFI);
-        mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
+        mUNM.startTrackDefaultNetwork(mEntitleMgr);
         mUNM.startObserveAllNetworks();
         // Setup wifi and make wifi as default network.
         final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index fda128c..3fd4d33 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -102,6 +102,7 @@
 import android.net.NetworkInfo.State;
 import android.net.NetworkRequest;
 import android.net.NetworkUtils;
+import android.net.ProxyInfo;
 import android.net.SocketKeepalive;
 import android.net.TestNetworkInterface;
 import android.net.TestNetworkManager;
@@ -1912,4 +1913,12 @@
         assertNull(NetworkInformationShimImpl.newInstance()
                 .getCapabilityCarrierName(ConstantsShim.NET_CAPABILITY_NOT_VCN_MANAGED));
     }
+
+    @Test
+    public void testSetGlobalProxy() {
+        assumeTrue(TestUtils.shouldTestSApis());
+        // Behavior is verified in gts. Verify exception thrown w/o permission.
+        assertThrows(SecurityException.class, () -> mCm.setGlobalProxy(
+                ProxyInfo.buildDirectProxy("example.com" /* host */, 8080 /* port */)));
+    }
 }
diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
index 88172d7..d5a26c4 100644
--- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
+++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java
@@ -18,7 +18,6 @@
 
 import static android.Manifest.permission.ACCESS_WIFI_STATE;
 import static android.Manifest.permission.NETWORK_SETTINGS;
-import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
@@ -87,6 +86,7 @@
 
     private static final int PRIVATE_DNS_SETTING_TIMEOUT_MS = 10_000;
     private static final int CONNECTIVITY_CHANGE_TIMEOUT_SECS = 30;
+    private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
     public static final int HTTP_PORT = 80;
     public static final String TEST_HOST = "connectivitycheck.gstatic.com";
     public static final String HTTP_REQUEST =