Merge "Add MainlineTestModuleController to CtsNetTestCases" into tm-dev
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index d79edb4..9076dca 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -70,9 +70,9 @@
     canned_fs_config: "canned_fs_config",
     bpfs: [
         "block.o",
-        "clatd.o_mainline",
+        "clatd.o",
         "dscp_policy.o",
-        "netd.o_mainline",
+        "netd.o",
         "offload.o",
         "test.o",
     ],
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 1fe0e9a..0e7b22d 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -97,7 +97,7 @@
 }
 
 bpf {
-    name: "clatd.o_mainline",
+    name: "clatd.o",
     srcs: ["clatd.c"],
     cflags: [
         "-Wall",
@@ -110,7 +110,7 @@
 }
 
 bpf {
-    name: "netd.o_mainline",
+    name: "netd.o",
     srcs: ["netd.c"],
     cflags: [
         "-Wall",
diff --git a/bpf_progs/bpf_tethering.h b/bpf_progs/bpf_tethering.h
index b0ec8f6..f9ef6ef 100644
--- a/bpf_progs/bpf_tethering.h
+++ b/bpf_progs/bpf_tethering.h
@@ -73,10 +73,6 @@
 #define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.")
 
 
-#define BPF_PATH_TETHER BPF_PATH "tethering/"
-
-#define TETHER_STATS_MAP_PATH BPF_PATH_TETHER "map_offload_tether_stats_map"
-
 typedef uint32_t TetherStatsKey;  // upstream ifindex
 
 typedef struct {
@@ -89,19 +85,9 @@
 } TetherStatsValue;
 STRUCT_SIZE(TetherStatsValue, 6 * 8);  // 48
 
-#define TETHER_LIMIT_MAP_PATH BPF_PATH_TETHER "map_offload_tether_limit_map"
-
 typedef uint32_t TetherLimitKey;    // upstream ifindex
 typedef uint64_t TetherLimitValue;  // in bytes
 
-#define TETHER_DOWNSTREAM6_TC_PROG_RAWIP_NAME "prog_offload_schedcls_tether_downstream6_rawip"
-#define TETHER_DOWNSTREAM6_TC_PROG_ETHER_NAME "prog_offload_schedcls_tether_downstream6_ether"
-
-#define TETHER_DOWNSTREAM6_TC_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM6_TC_PROG_RAWIP_NAME
-#define TETHER_DOWNSTREAM6_TC_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM6_TC_PROG_ETHER_NAME
-
-#define TETHER_DOWNSTREAM6_MAP_PATH BPF_PATH_TETHER "map_offload_tether_downstream6_map"
-
 // For now tethering offload only needs to support downstreams that use 6-byte MAC addresses,
 // because all downstream types that are currently supported (WiFi, USB, Bluetooth and
 // Ethernet) have 6-byte MAC addresses.
@@ -121,8 +107,6 @@
 } Tether6Value;
 STRUCT_SIZE(Tether6Value, 4 + 14 + 2);  // 20
 
-#define TETHER_DOWNSTREAM64_MAP_PATH BPF_PATH_TETHER "map_offload_tether_downstream64_map"
-
 typedef struct {
     uint32_t iif;              // The input interface index
     uint8_t dstMac[ETH_ALEN];  // destination ethernet mac address (zeroed iff rawip ingress)
@@ -146,14 +130,6 @@
 } TetherDownstream64Value;
 STRUCT_SIZE(TetherDownstream64Value, 4 + 14 + 2 + 4 + 4 + 2 + 2 + 8);  // 40
 
-#define TETHER_UPSTREAM6_TC_PROG_RAWIP_NAME "prog_offload_schedcls_tether_upstream6_rawip"
-#define TETHER_UPSTREAM6_TC_PROG_ETHER_NAME "prog_offload_schedcls_tether_upstream6_ether"
-
-#define TETHER_UPSTREAM6_TC_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_UPSTREAM6_TC_PROG_RAWIP_NAME
-#define TETHER_UPSTREAM6_TC_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_UPSTREAM6_TC_PROG_ETHER_NAME
-
-#define TETHER_UPSTREAM6_MAP_PATH BPF_PATH_TETHER "map_offload_tether_upstream6_map"
-
 typedef struct {
     uint32_t iif;              // The input interface index
     uint8_t dstMac[ETH_ALEN];  // destination ethernet mac address (zeroed iff rawip ingress)
@@ -162,23 +138,6 @@
 } TetherUpstream6Key;
 STRUCT_SIZE(TetherUpstream6Key, 12);
 
-#define TETHER_DOWNSTREAM4_TC_PROG_RAWIP_NAME "prog_offload_schedcls_tether_downstream4_rawip"
-#define TETHER_DOWNSTREAM4_TC_PROG_ETHER_NAME "prog_offload_schedcls_tether_downstream4_ether"
-
-#define TETHER_DOWNSTREAM4_TC_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM4_TC_PROG_RAWIP_NAME
-#define TETHER_DOWNSTREAM4_TC_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM4_TC_PROG_ETHER_NAME
-
-#define TETHER_DOWNSTREAM4_MAP_PATH BPF_PATH_TETHER "map_offload_tether_downstream4_map"
-
-
-#define TETHER_UPSTREAM4_TC_PROG_RAWIP_NAME "prog_offload_schedcls_tether_upstream4_rawip"
-#define TETHER_UPSTREAM4_TC_PROG_ETHER_NAME "prog_offload_schedcls_tether_upstream4_ether"
-
-#define TETHER_UPSTREAM4_TC_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_UPSTREAM4_TC_PROG_RAWIP_NAME
-#define TETHER_UPSTREAM4_TC_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_UPSTREAM4_TC_PROG_ETHER_NAME
-
-#define TETHER_UPSTREAM4_MAP_PATH BPF_PATH_TETHER "map_offload_tether_upstream4_map"
-
 typedef struct {
     uint32_t iif;              // The input interface index
     uint8_t dstMac[ETH_ALEN];  // destination ethernet mac address (zeroed iff rawip ingress)
@@ -202,16 +161,4 @@
 } Tether4Value;
 STRUCT_SIZE(Tether4Value, 4 + 14 + 2 + 16 + 16 + 2 + 2 + 8);  // 64
 
-#define TETHER_DOWNSTREAM_XDP_PROG_RAWIP_NAME "prog_offload_xdp_tether_downstream_rawip"
-#define TETHER_DOWNSTREAM_XDP_PROG_ETHER_NAME "prog_offload_xdp_tether_downstream_ether"
-
-#define TETHER_DOWNSTREAM_XDP_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM_XDP_PROG_RAWIP_NAME
-#define TETHER_DOWNSTREAM_XDP_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_DOWNSTREAM_XDP_PROG_ETHER_NAME
-
-#define TETHER_UPSTREAM_XDP_PROG_RAWIP_NAME "prog_offload_xdp_tether_upstream_rawip"
-#define TETHER_UPSTREAM_XDP_PROG_ETHER_NAME "prog_offload_xdp_tether_upstream_ether"
-
-#define TETHER_UPSTREAM_XDP_PROG_RAWIP_PATH BPF_PATH_TETHER TETHER_UPSTREAM_XDP_PROG_RAWIP_NAME
-#define TETHER_UPSTREAM_XDP_PROG_ETHER_PATH BPF_PATH_TETHER TETHER_UPSTREAM_XDP_PROG_ETHER_NAME
-
 #undef STRUCT_SIZE
diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java
index 2b76dd9..886d194 100644
--- a/framework-t/src/android/net/EthernetManager.java
+++ b/framework-t/src/android/net/EthernetManager.java
@@ -32,13 +32,13 @@
 import android.os.Build;
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
+import android.util.ArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.modules.utils.BackgroundThread;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Executor;
@@ -56,37 +56,12 @@
 
     private final IEthernetManager mService;
     @GuardedBy("mListenerLock")
-    private final ArrayList<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
-            new ArrayList<>();
+    private final ArrayMap<InterfaceStateListener, IEthernetServiceListener>
+            mIfaceServiceListeners = new ArrayMap<>();
     @GuardedBy("mListenerLock")
-    private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
-            new ArrayList<>();
+    private final ArrayMap<IntConsumer, IEthernetServiceListener> mStateServiceListeners =
+            new ArrayMap<>();
     final Object mListenerLock = new Object();
-    private final IEthernetServiceListener.Stub mServiceListener =
-            new IEthernetServiceListener.Stub() {
-                @Override
-                public void onEthernetStateChanged(int state) {
-                    synchronized (mListenerLock) {
-                        for (ListenerInfo<IntConsumer> li : mEthernetStateListeners) {
-                            li.executor.execute(() -> {
-                                li.listener.accept(state);
-                            });
-                        }
-                    }
-                }
-
-                @Override
-                public void onInterfaceStateChanged(String iface, int state, int role,
-                        IpConfiguration configuration) {
-                    synchronized (mListenerLock) {
-                        for (ListenerInfo<InterfaceStateListener> li : mIfaceListeners) {
-                            li.executor.execute(() ->
-                                    li.listener.onInterfaceStateChanged(iface, state, role,
-                                            configuration));
-                        }
-                    }
-                }
-            };
 
     /**
      * Indicates that Ethernet is disabled.
@@ -104,18 +79,6 @@
     @SystemApi(client = MODULE_LIBRARIES)
     public static final int ETHERNET_STATE_ENABLED  = 1;
 
-    private static class ListenerInfo<T> {
-        @NonNull
-        public final Executor executor;
-        @NonNull
-        public final T listener;
-
-        private ListenerInfo(@NonNull Executor executor, @NonNull T listener) {
-            this.executor = executor;
-            this.listener = listener;
-        }
-    }
-
     /**
      * The interface is absent.
      * @hide
@@ -323,18 +286,28 @@
         if (listener == null || executor == null) {
             throw new NullPointerException("listener and executor must not be null");
         }
+
+        final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() {
+            @Override
+            public void onEthernetStateChanged(int state) {}
+
+            @Override
+            public void onInterfaceStateChanged(String iface, int state, int role,
+                    IpConfiguration configuration) {
+                executor.execute(() ->
+                        listener.onInterfaceStateChanged(iface, state, role, configuration));
+            }
+        };
         synchronized (mListenerLock) {
-            maybeAddServiceListener();
-            mIfaceListeners.add(new ListenerInfo<InterfaceStateListener>(executor, listener));
+            addServiceListener(serviceListener);
+            mIfaceServiceListeners.put(listener, serviceListener);
         }
     }
 
     @GuardedBy("mListenerLock")
-    private void maybeAddServiceListener() {
-        if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
-
+    private void addServiceListener(@NonNull final IEthernetServiceListener listener) {
         try {
-            mService.addListener(mServiceListener);
+            mService.addListener(listener);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -364,17 +337,16 @@
     public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
         Objects.requireNonNull(listener);
         synchronized (mListenerLock) {
-            mIfaceListeners.removeIf(l -> l.listener == listener);
-            maybeRemoveServiceListener();
+            maybeRemoveServiceListener(mIfaceServiceListeners.remove(listener));
         }
     }
 
     @GuardedBy("mListenerLock")
-    private void maybeRemoveServiceListener() {
-        if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
+    private void maybeRemoveServiceListener(@Nullable final IEthernetServiceListener listener) {
+        if (listener == null) return;
 
         try {
-            mService.removeListener(mServiceListener);
+            mService.removeListener(listener);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -687,9 +659,19 @@
             @NonNull IntConsumer listener) {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(listener);
+        final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() {
+            @Override
+            public void onEthernetStateChanged(int state) {
+                executor.execute(() -> listener.accept(state));
+            }
+
+            @Override
+            public void onInterfaceStateChanged(String iface, int state, int role,
+                    IpConfiguration configuration) {}
+        };
         synchronized (mListenerLock) {
-            maybeAddServiceListener();
-            mEthernetStateListeners.add(new ListenerInfo<IntConsumer>(executor, listener));
+            addServiceListener(serviceListener);
+            mStateServiceListeners.put(listener, serviceListener);
         }
     }
 
@@ -705,8 +687,7 @@
     public void removeEthernetStateListener(@NonNull IntConsumer listener) {
         Objects.requireNonNull(listener);
         synchronized (mListenerLock) {
-            mEthernetStateListeners.removeIf(l -> l.listener == listener);
-            maybeRemoveServiceListener();
+            maybeRemoveServiceListener(mStateServiceListeners.remove(listener));
         }
     }
 
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index 29add1c..2c50c73 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -1076,11 +1076,12 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public final void sendNetworkInfo(NetworkInfo networkInfo) {
-        queueOrSendNetworkInfo(new NetworkInfo(networkInfo));
+        queueOrSendNetworkInfo(networkInfo);
     }
 
     private void queueOrSendNetworkInfo(NetworkInfo networkInfo) {
-        queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo));
+        final NetworkInfo ni = new NetworkInfo(networkInfo);
+        queueOrSendMessage(reg -> reg.sendNetworkInfo(ni));
     }
 
     /**
diff --git a/nearby/framework/java/android/nearby/ScanRequest.java b/nearby/framework/java/android/nearby/ScanRequest.java
index cf2dd43..c717ac7 100644
--- a/nearby/framework/java/android/nearby/ScanRequest.java
+++ b/nearby/framework/java/android/nearby/ScanRequest.java
@@ -73,7 +73,8 @@
                     .setScanMode(in.readInt())
                     .setBleEnabled(in.readBoolean())
                     .setWorkSource(in.readTypedObject(WorkSource.CREATOR));
-            for (int i = 0; i < in.readInt(); i++) {
+            final int size = in.readInt();
+            for (int i = 0; i < size; i++) {
                 builder.addScanFilter(ScanFilter.createFromParcel(in));
             }
             return builder.build();
@@ -209,8 +210,9 @@
         dest.writeInt(mScanMode);
         dest.writeBoolean(mBleEnabled);
         dest.writeTypedObject(mWorkSource, /* parcelableFlags= */0);
-        dest.writeInt(mScanFilters.size());
-        for (int i = 0; i < mScanFilters.size(); ++i) {
+        final int size = mScanFilters.size();
+        dest.writeInt(size);
+        for (int i = 0; i < size; i++) {
             mScanFilters.get(i).writeToParcel(dest, flags);
         }
     }
diff --git a/nearby/service/Android.bp b/nearby/service/Android.bp
index 0c2395c..d318a80 100644
--- a/nearby/service/Android.bp
+++ b/nearby/service/Android.bp
@@ -107,7 +107,6 @@
     // (service-connectivity is only used on 31+) and use 31 here
     min_sdk_version: "30",
 
-    installable: true,
     dex_preopt: {
         enabled: false,
         app_image: false,
diff --git a/nearby/service/java/com/android/server/nearby/provider/BroadcastProviderManager.java b/nearby/service/java/com/android/server/nearby/provider/BroadcastProviderManager.java
index 72fe29a..3fffda5 100644
--- a/nearby/service/java/com/android/server/nearby/provider/BroadcastProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/provider/BroadcastProviderManager.java
@@ -65,26 +65,26 @@
      */
     public void startBroadcast(BroadcastRequest broadcastRequest, IBroadcastListener listener) {
         synchronized (mLock) {
-            NearbyConfiguration configuration = new NearbyConfiguration();
-            if (!configuration.isPresenceBroadcastLegacyEnabled()) {
-                reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
-                return;
-            }
-            if (broadcastRequest.getType() != BroadcastRequest.BROADCAST_TYPE_NEARBY_PRESENCE) {
-                reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
-                return;
-            }
-            PresenceBroadcastRequest presenceBroadcastRequest =
-                    (PresenceBroadcastRequest) broadcastRequest;
-            if (presenceBroadcastRequest.getVersion() != BroadcastRequest.PRESENCE_VERSION_V0) {
-                reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
-                return;
-            }
-            FastAdvertisement fastAdvertisement = FastAdvertisement.createFromRequest(
-                    presenceBroadcastRequest);
-            byte[] advertisementPackets = fastAdvertisement.toBytes();
-            mBroadcastListener = listener;
             mExecutor.execute(() -> {
+                NearbyConfiguration configuration = new NearbyConfiguration();
+                if (!configuration.isPresenceBroadcastLegacyEnabled()) {
+                    reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
+                    return;
+                }
+                if (broadcastRequest.getType() != BroadcastRequest.BROADCAST_TYPE_NEARBY_PRESENCE) {
+                    reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
+                    return;
+                }
+                PresenceBroadcastRequest presenceBroadcastRequest =
+                        (PresenceBroadcastRequest) broadcastRequest;
+                if (presenceBroadcastRequest.getVersion() != BroadcastRequest.PRESENCE_VERSION_V0) {
+                    reportBroadcastStatus(listener, BroadcastCallback.STATUS_FAILURE);
+                    return;
+                }
+                FastAdvertisement fastAdvertisement = FastAdvertisement.createFromRequest(
+                        presenceBroadcastRequest);
+                byte[] advertisementPackets = fastAdvertisement.toBytes();
+                mBroadcastListener = listener;
                 mBleBroadcastProvider.start(advertisementPackets, this);
             });
         }
diff --git a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
index 3a73b9f..21f3d28 100644
--- a/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
+++ b/nearby/tests/cts/fastpair/src/android/nearby/cts/ScanRequestTest.java
@@ -45,6 +45,7 @@
 
     private static final int UID = 1001;
     private static final String APP_NAME = "android.nearby.tests";
+    private static final int RSSI = -40;
 
     @Test
     @SdkSuppress(minSdkVersion = 32, codeName = "T")
@@ -163,6 +164,14 @@
     @Test
     @SdkSuppress(minSdkVersion = 32, codeName = "T")
     public void testScanFilter() {
+        ScanRequest request = new ScanRequest.Builder().setScanType(
+                SCAN_TYPE_NEARBY_PRESENCE).addScanFilter(getPresenceScanFilter()).build();
+
+        assertThat(request.getScanFilters()).isNotEmpty();
+        assertThat(request.getScanFilters().get(0).getMaxPathLoss()).isEqualTo(RSSI);
+    }
+
+    private static PresenceScanFilter getPresenceScanFilter() {
         final byte[] secretId = new byte[]{1, 2, 3, 4};
         final byte[] authenticityKey = new byte[]{0, 1, 1, 1};
         final byte[] publicKey = new byte[]{1, 1, 2, 2};
@@ -174,19 +183,12 @@
                 .setIdentityType(IDENTITY_TYPE_PRIVATE)
                 .build();
 
-        final int rssi = -40;
         final int action = 123;
-        PresenceScanFilter filter = new PresenceScanFilter.Builder()
+        return new PresenceScanFilter.Builder()
                 .addCredential(credential)
-                .setMaxPathLoss(rssi)
+                .setMaxPathLoss(RSSI)
                 .addPresenceAction(action)
                 .build();
-
-        ScanRequest request = new ScanRequest.Builder().setScanType(
-                SCAN_TYPE_FAST_PAIR).addScanFilter(filter).build();
-
-        assertThat(request.getScanFilters()).isNotEmpty();
-        assertThat(request.getScanFilters().get(0).getMaxPathLoss()).isEqualTo(rssi);
     }
 
     private static WorkSource getWorkSource() {
diff --git a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
index a45d8bb..12de30e 100644
--- a/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
+++ b/nearby/tests/unit/src/android/nearby/ScanRequestTest.java
@@ -16,6 +16,7 @@
 
 package android.nearby;
 
+import static android.nearby.PresenceCredential.IDENTITY_TYPE_PRIVATE;
 import static android.nearby.ScanRequest.SCAN_MODE_BALANCED;
 import static android.nearby.ScanRequest.SCAN_MODE_LOW_POWER;
 import static android.nearby.ScanRequest.SCAN_TYPE_FAST_PAIR;
@@ -39,6 +40,8 @@
 @RunWith(AndroidJUnit4.class)
 public class ScanRequestTest {
 
+    private static final int RSSI = -40;
+
     private static WorkSource getWorkSource() {
         final int uid = 1001;
         final String appName = "android.nearby.tests";
@@ -137,6 +140,7 @@
                 .setScanMode(SCAN_MODE_BALANCED)
                 .setBleEnabled(true)
                 .setWorkSource(workSource)
+                .addScanFilter(getPresenceScanFilter())
                 .build();
 
         // Write the scan request to parcel, then read from it.
@@ -164,4 +168,24 @@
         parcel.setDataPosition(0);
         return ScanRequest.CREATOR.createFromParcel(parcel);
     }
+
+    private static PresenceScanFilter getPresenceScanFilter() {
+        final byte[] secretId = new byte[]{1, 2, 3, 4};
+        final byte[] authenticityKey = new byte[]{0, 1, 1, 1};
+        final byte[] publicKey = new byte[]{1, 1, 2, 2};
+        final byte[] encryptedMetadata = new byte[]{1, 2, 3, 4, 5};
+        final byte[] metadataEncryptionKeyTag = new byte[]{1, 1, 3, 4, 5};
+
+        PublicCredential credential = new PublicCredential.Builder(
+                secretId, authenticityKey, publicKey, encryptedMetadata, metadataEncryptionKeyTag)
+                .setIdentityType(IDENTITY_TYPE_PRIVATE)
+                .build();
+
+        final int action = 123;
+        return new PresenceScanFilter.Builder()
+                .addCredential(credential)
+                .setMaxPathLoss(RSSI)
+                .addPresenceAction(action)
+                .build();
+    }
 }
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index 4086e4e..ea57bac 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -738,7 +738,13 @@
         String type = service.getServiceType();
         int port = service.getPort();
         byte[] textRecord = service.getTxtRecord();
-        return mMDnsManager.registerService(regId, name, type, port, textRecord, IFACE_IDX_ANY);
+        final Network network = service.getNetwork();
+        final int registerInterface = getNetworkInterfaceIndex(network);
+        if (network != null && registerInterface == IFACE_IDX_ANY) {
+            Log.e(TAG, "Interface to register service on not found");
+            return false;
+        }
+        return mMDnsManager.registerService(regId, name, type, port, textRecord, registerInterface);
     }
 
     private boolean unregisterService(int regId) {
diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java
index fdfc893..c51a886 100644
--- a/service-t/src/com/android/server/net/NetworkStatsObservers.java
+++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java
@@ -18,6 +18,7 @@
 
 import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
 
+import android.annotation.NonNull;
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -38,6 +39,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -52,12 +54,15 @@
  */
 class NetworkStatsObservers {
     private static final String TAG = "NetworkStatsObservers";
+    private static final boolean LOG = true;
     private static final boolean LOGV = false;
 
     private static final int MSG_REGISTER = 1;
     private static final int MSG_UNREGISTER = 2;
     private static final int MSG_UPDATE_STATS = 3;
 
+    private static final int DUMP_USAGE_REQUESTS_COUNT = 200;
+
     // All access to this map must be done from the handler thread.
     // indexed by DataUsageRequest#requestId
     private final SparseArray<RequestInfo> mDataUsageRequests = new SparseArray<>();
@@ -77,13 +82,15 @@
      *
      * @return the normalized request wrapped within {@link RequestInfo}.
      */
-    public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
-            IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+    public DataUsageRequest register(@NonNull Context context,
+            @NonNull DataUsageRequest inputRequest, @NonNull IUsageCallback callback,
+            int callingPid, int callingUid, @NonNull String callingPackage,
+            @NetworkStatsAccess.Level int accessLevel) {
         DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
-        RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
-                accessLevel);
+        RequestInfo requestInfo = buildRequestInfo(request, callback, callingPid, callingUid,
+                callingPackage, accessLevel);
 
-        if (LOGV) Log.v(TAG, "Registering observer for " + request);
+        if (LOG) Log.d(TAG, "Registering observer for " + requestInfo);
         getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
         return request;
     }
@@ -172,7 +179,7 @@
         RequestInfo requestInfo;
         requestInfo = mDataUsageRequests.get(request.requestId);
         if (requestInfo == null) {
-            if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request);
+            if (LOG) Log.d(TAG, "Trying to unregister unknown request " + request);
             return;
         }
         if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) {
@@ -180,7 +187,7 @@
             return;
         }
 
-        if (LOGV) Log.v(TAG, "Unregistering " + request);
+        if (LOG) Log.d(TAG, "Unregistering " + requestInfo);
         mDataUsageRequests.remove(request.requestId);
         requestInfo.unlinkDeathRecipient();
         requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED);
@@ -214,18 +221,19 @@
     }
 
     private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback,
-            int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+            int callingPid, int callingUid, @NonNull String callingPackage,
+            @NetworkStatsAccess.Level int accessLevel) {
         if (accessLevel <= NetworkStatsAccess.Level.USER) {
-            return new UserUsageRequestInfo(this, request, callback, callingUid,
-                    accessLevel);
+            return new UserUsageRequestInfo(this, request, callback, callingPid,
+                    callingUid, callingPackage, accessLevel);
         } else {
             // Safety check in case a new access level is added and we forgot to update this
             if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
                 throw new IllegalArgumentException(
                         "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
             }
-            return new NetworkUsageRequestInfo(this, request, callback, callingUid,
-                    accessLevel);
+            return new NetworkUsageRequestInfo(this, request, callback, callingPid,
+                    callingUid, callingPackage, accessLevel);
         }
     }
 
@@ -237,18 +245,22 @@
         private final NetworkStatsObservers mStatsObserver;
         protected final DataUsageRequest mRequest;
         private final IUsageCallback mCallback;
+        protected final int mCallingPid;
         protected final int mCallingUid;
+        protected final String mCallingPackage;
         protected final @NetworkStatsAccess.Level int mAccessLevel;
         protected NetworkStatsRecorder mRecorder;
         protected NetworkStatsCollection mCollection;
 
         RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
+                IUsageCallback callback, int callingPid, int callingUid,
+                @NonNull String callingPackage, @NetworkStatsAccess.Level int accessLevel) {
             mStatsObserver = statsObserver;
             mRequest = request;
             mCallback = callback;
+            mCallingPid = callingPid;
             mCallingUid = callingUid;
+            mCallingPackage = callingPackage;
             mAccessLevel = accessLevel;
 
             try {
@@ -269,7 +281,8 @@
 
         @Override
         public String toString() {
-            return "RequestInfo from uid:" + mCallingUid
+            return "RequestInfo from pid/uid:" + mCallingPid + "/" + mCallingUid
+                    + "(" + mCallingPackage + ")"
                     + " for " + mRequest + " accessLevel:" + mAccessLevel;
         }
 
@@ -338,9 +351,10 @@
 
     private static class NetworkUsageRequestInfo extends RequestInfo {
         NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, callback, callingUid, accessLevel);
+                IUsageCallback callback, int callingPid, int callingUid,
+                @NonNull String callingPackage, @NetworkStatsAccess.Level int accessLevel) {
+            super(statsObserver, request, callback, callingPid, callingUid, callingPackage,
+                    accessLevel);
         }
 
         @Override
@@ -380,9 +394,10 @@
 
     private static class UserUsageRequestInfo extends RequestInfo {
         UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                    IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, callback, callingUid, accessLevel);
+                IUsageCallback callback, int callingPid, int callingUid,
+                @NonNull String callingPackage, @NetworkStatsAccess.Level int accessLevel) {
+            super(statsObserver, request, callback, callingPid, callingUid,
+                    callingPackage, accessLevel);
         }
 
         @Override
@@ -448,4 +463,10 @@
             mCurrentTime = currentTime;
         }
     }
+
+    public void dump(IndentingPrintWriter pw) {
+        for (int i = 0; i < Math.min(mDataUsageRequests.size(), DUMP_USAGE_REQUESTS_COUNT); i++) {
+            pw.println(mDataUsageRequests.valueAt(i));
+        }
+    }
 }
diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index 82b1fb5..217a9a6 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -1279,13 +1279,14 @@
         Objects.requireNonNull(request.template, "NetworkTemplate is null");
         Objects.requireNonNull(callback, "callback is null");
 
-        int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        final int callingUid = Binder.getCallingUid();
         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
         DataUsageRequest normalizedRequest;
         final long token = Binder.clearCallingIdentity();
         try {
             normalizedRequest = mStatsObservers.register(mContext,
-                    request, callback, callingUid, accessLevel);
+                    request, callback, callingPid, callingUid, callingPackage, accessLevel);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -2098,6 +2099,13 @@
                 }
             });
             pw.decreaseIndent();
+            pw.println();
+
+            pw.println("Stats Observers:");
+            pw.increaseIndent();
+            mStatsObservers.dump(pw);
+            pw.decreaseIndent();
+            pw.println();
 
             pw.println("Dev stats:");
             pw.increaseIndent();
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index c19bb11..67a64d5 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -610,13 +610,6 @@
     // Handle private DNS validation status updates.
     private static final int EVENT_PRIVATE_DNS_VALIDATION_UPDATE = 38;
 
-    /**
-     * used to remove a network request, either a listener or a real request and call unavailable
-     * arg1 = UID of caller
-     * obj  = NetworkRequest
-     */
-    private static final int EVENT_RELEASE_NETWORK_REQUEST_AND_CALL_UNAVAILABLE = 39;
-
      /**
       * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has
       * been tested.
@@ -2628,7 +2621,7 @@
         verifyCallingUidAndPackage(callingPackageName, mDeps.getCallingUid());
         enforceChangePermission(callingPackageName, callingAttributionTag);
         if (mProtectedNetworks.contains(networkType)) {
-            enforceConnectivityRestrictedNetworksPermission();
+            enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
         }
 
         InetAddress addr;
@@ -2982,18 +2975,35 @@
                 android.Manifest.permission.NETWORK_SETTINGS);
     }
 
-    private void enforceConnectivityRestrictedNetworksPermission() {
-        try {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
-                    "ConnectivityService");
-            return;
-        } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
-        //  TODO: Remove this fallback check after all apps have declared
-        //   CONNECTIVITY_USE_RESTRICTED_NETWORKS.
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.CONNECTIVITY_INTERNAL,
-                "ConnectivityService");
+    private boolean checkConnectivityRestrictedNetworksPermission(int callingUid,
+            boolean checkUidsAllowedList) {
+        if (PermissionUtils.checkAnyPermissionOf(mContext,
+                android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS)) {
+            return true;
+        }
+
+        // fallback to ConnectivityInternalPermission
+        // TODO: Remove this fallback check after all apps have declared
+        //  CONNECTIVITY_USE_RESTRICTED_NETWORKS.
+        if (PermissionUtils.checkAnyPermissionOf(mContext,
+                android.Manifest.permission.CONNECTIVITY_INTERNAL)) {
+            return true;
+        }
+
+        // Check whether uid is in allowed on restricted networks list.
+        if (checkUidsAllowedList
+                && mPermissionMonitor.isUidAllowedOnRestrictedNetworks(callingUid)) {
+            return true;
+        }
+        return false;
+    }
+
+    private void enforceConnectivityRestrictedNetworksPermission(boolean checkUidsAllowedList) {
+        final int callingUid = mDeps.getCallingUid();
+        if (!checkConnectivityRestrictedNetworksPermission(callingUid, checkUidsAllowedList)) {
+            throw new SecurityException("ConnectivityService: user " + callingUid
+                    + " has no permission to access restricted network.");
+        }
     }
 
     private void enforceKeepalivePermission() {
@@ -4495,7 +4505,7 @@
 
     private boolean hasCarrierPrivilegeForNetworkCaps(final int callingUid,
             @NonNull final NetworkCapabilities caps) {
-        if (SdkLevel.isAtLeastT() && mCarrierPrivilegeAuthenticator != null) {
+        if (mCarrierPrivilegeAuthenticator != null) {
             return mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
                     callingUid, caps);
         }
@@ -4525,7 +4535,6 @@
 
     private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
         ensureRunningOnConnectivityServiceThread();
-        NetworkRequest requestToBeReleased = null;
         for (final NetworkRequestInfo nri : nris) {
             mNetworkRequestInfoLogs.log("REGISTER " + nri);
             checkNrisConsistency(nri);
@@ -4540,13 +4549,6 @@
                         }
                     }
                 }
-                if (req.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
-                    if (!hasCarrierPrivilegeForNetworkCaps(nri.mUid, req.networkCapabilities)
-                            && !checkConnectivityRestrictedNetworksPermission(
-                                    nri.mPid, nri.mUid)) {
-                        requestToBeReleased = req;
-                    }
-                }
             }
 
             // If this NRI has a satisfier already, it is replacing an older request that
@@ -4558,11 +4560,6 @@
             }
         }
 
-        if (requestToBeReleased != null) {
-            releaseNetworkRequestAndCallOnUnavailable(requestToBeReleased);
-            return;
-        }
-
         if (mFlags.noRematchAllRequestsOnRegister()) {
             rematchNetworksAndRequests(nris);
         } else {
@@ -5402,11 +5399,6 @@
                             /* callOnUnavailable */ false);
                     break;
                 }
-                case EVENT_RELEASE_NETWORK_REQUEST_AND_CALL_UNAVAILABLE: {
-                    handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
-                            /* callOnUnavailable */ true);
-                    break;
-                }
                 case EVENT_SET_ACCEPT_UNVALIDATED: {
                     Network network = (Network) msg.obj;
                     handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
@@ -6631,7 +6623,7 @@
             case REQUEST:
                 networkCapabilities = new NetworkCapabilities(networkCapabilities);
                 enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
-                        callingAttributionTag);
+                        callingAttributionTag, callingUid);
                 // TODO: this is incorrect. We mark the request as metered or not depending on
                 //  the state of the app when the request is filed, but we never change the
                 //  request if the app changes network state. http://b/29964605
@@ -6721,26 +6713,19 @@
     }
 
     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
-            String callingPackageName, String callingAttributionTag) {
+            String callingPackageName, String callingAttributionTag, final int callingUid) {
         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
-            if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
-                enforceConnectivityRestrictedNetworksPermission();
+            // For T+ devices, callers with carrier privilege could request with CBS capabilities.
+            if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
+                    && hasCarrierPrivilegeForNetworkCaps(callingUid, networkCapabilities)) {
+                return;
             }
+            enforceConnectivityRestrictedNetworksPermission(true /* checkUidsAllowedList */);
         } else {
             enforceChangePermission(callingPackageName, callingAttributionTag);
         }
     }
 
-    private boolean checkConnectivityRestrictedNetworksPermission(int callerPid, int callerUid) {
-        if (checkAnyPermissionOf(callerPid, callerUid,
-                android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS)
-                || checkAnyPermissionOf(callerPid, callerUid,
-                android.Manifest.permission.CONNECTIVITY_INTERNAL)) {
-            return true;
-        }
-        return false;
-    }
-
     @Override
     public boolean requestBandwidthUpdate(Network network) {
         enforceAccessPermission();
@@ -6799,7 +6784,7 @@
         final int callingUid = mDeps.getCallingUid();
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
-                callingAttributionTag);
+                callingAttributionTag, callingUid);
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
@@ -6922,13 +6907,6 @@
                 EVENT_RELEASE_NETWORK_REQUEST, mDeps.getCallingUid(), 0, networkRequest));
     }
 
-    private void releaseNetworkRequestAndCallOnUnavailable(NetworkRequest networkRequest) {
-        ensureNetworkRequestHasType(networkRequest);
-        mHandler.sendMessage(mHandler.obtainMessage(
-                EVENT_RELEASE_NETWORK_REQUEST_AND_CALL_UNAVAILABLE, mDeps.getCallingUid(), 0,
-                networkRequest));
-    }
-
     private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {
         if (mNetworkProviderInfos.containsKey(npi.messenger)) {
             // Avoid creating duplicates. even if an app makes a direct AIDL call.
@@ -10631,7 +10609,11 @@
         if (callback == null) throw new IllegalArgumentException("callback must be non-null");
 
         if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
-            enforceConnectivityRestrictedNetworksPermission();
+            // TODO: Check allowed list here and ensure that either a) any QoS callback registered
+            //  on this network is unregistered when the app loses permission or b) no QoS
+            //  callbacks are sent for restricted networks unless the app currently has permission
+            //  to access restricted networks.
+            enforceConnectivityRestrictedNetworksPermission(false /* checkUidsAllowedList */);
         }
         mQosCallbackTracker.registerCallback(callback, filter, nai);
     }
@@ -10683,7 +10665,10 @@
         Objects.requireNonNull(profile);
 
         if (preferences.size() == 0) {
-            preferences.add((new ProfileNetworkPreference.Builder()).build());
+            final ProfileNetworkPreference pref = new ProfileNetworkPreference.Builder()
+                    .setPreference(ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT)
+                    .build();
+            preferences.add(pref);
         }
 
         PermissionUtils.enforceNetworkStackPermission(mContext);
@@ -10701,12 +10686,14 @@
 
         final List<ProfileNetworkPreferenceList.Preference> preferenceList =
                 new ArrayList<ProfileNetworkPreferenceList.Preference>();
-        boolean allowFallback = true;
+        boolean hasDefaultPreference = false;
         for (final ProfileNetworkPreference preference : preferences) {
             final NetworkCapabilities nc;
+            boolean allowFallback = true;
             switch (preference.getPreference()) {
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT:
                     nc = null;
+                    hasDefaultPreference = true;
                     if (preference.getPreferenceEnterpriseId() != 0) {
                         throw new IllegalArgumentException(
                                 "Invalid enterprise identifier in setProfileNetworkPreferences");
@@ -10716,6 +10703,14 @@
                     allowFallback = false;
                     // continue to process the enterprise preference.
                 case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE:
+                    // This code is needed even though there is a check later on,
+                    // because isRangeAlreadyInPreferenceList assumes that every preference
+                    // has a UID list.
+                    if (hasDefaultPreference) {
+                        throw new IllegalArgumentException(
+                                "Default profile preference should not be set along with other "
+                                        + "preference");
+                    }
                     if (!isEnterpriseIdentifierValid(preference.getPreferenceEnterpriseId())) {
                         throw new IllegalArgumentException(
                                 "Invalid enterprise identifier in setProfileNetworkPreferences");
@@ -10739,6 +10734,10 @@
             }
             preferenceList.add(new ProfileNetworkPreferenceList.Preference(
                     profile, nc, allowFallback));
+            if (hasDefaultPreference && preferenceList.size() > 1) {
+                throw new IllegalArgumentException(
+                        "Default profile preference should not be set along with other preference");
+            }
         }
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE,
                 new Pair<>(preferenceList, listener)));
@@ -10783,12 +10782,6 @@
         return false;
     }
 
-    private void validateNetworkCapabilitiesOfProfileNetworkPreference(
-            @Nullable final NetworkCapabilities nc) {
-        if (null == nc) return; // Null caps are always allowed. It means to remove the setting.
-        ensureRequestableCapabilities(nc);
-    }
-
     private ArraySet<NetworkRequestInfo> createNrisFromProfileNetworkPreferences(
             @NonNull final ProfileNetworkPreferenceList prefs) {
         final ArraySet<NetworkRequestInfo> result = new ArraySet<>();
@@ -10846,10 +10839,9 @@
          * Clear all the existing preferences for the user before applying new preferences.
          *
          */
-        mProfileNetworkPreferences = mProfileNetworkPreferences.clearUser(
+        mProfileNetworkPreferences = mProfileNetworkPreferences.withoutUser(
                 preferenceList.get(0).user);
         for (final ProfileNetworkPreferenceList.Preference preference : preferenceList) {
-            validateNetworkCapabilitiesOfProfileNetworkPreference(preference.capabilities);
             mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference);
         }
 
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index c02d9cf..8d99cb4 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -421,7 +421,14 @@
         if (appInfo == null) return false;
         // Check whether package's uid is in allowed on restricted networks uid list. If so, this
         // uid can have netd system permission.
-        return mUidsAllowedOnRestrictedNetworks.contains(appInfo.uid);
+        return isUidAllowedOnRestrictedNetworks(appInfo.uid);
+    }
+
+    /**
+     * Returns whether the given uid is in allowed on restricted networks list.
+     */
+    public synchronized boolean isUidAllowedOnRestrictedNetworks(final int uid) {
+        return mUidsAllowedOnRestrictedNetworks.contains(uid);
     }
 
     @VisibleForTesting
diff --git a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
index 473a115..5bafef9 100644
--- a/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
+++ b/service/src/com/android/server/connectivity/ProfileNetworkPreferenceList.java
@@ -87,7 +87,7 @@
     /**
      * Remove all preferences corresponding to a user.
      */
-    public ProfileNetworkPreferenceList clearUser(UserHandle user) {
+    public ProfileNetworkPreferenceList withoutUser(UserHandle user) {
         final ArrayList<Preference> newPrefs = new ArrayList<>();
         for (final Preference existingPref : preferences) {
             if (!existingPref.user.equals(user)) {
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index a129108..bdda82a 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -52,6 +52,7 @@
 import static android.net.ConnectivityManager.TYPE_PROXY;
 import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
+import static android.net.ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
@@ -3212,7 +3213,7 @@
     @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
     @Test
     public void testUidsAllowedOnRestrictedNetworks() throws Exception {
-        assumeTrue(TestUtils.shouldTestSApis());
+        assumeTestSApis();
 
         // TODO (b/175199465): figure out a reasonable permission check for
         //  setUidsAllowedOnRestrictedNetworks that allows tests but not system-external callers.
@@ -3225,10 +3226,10 @@
         // because it has been just installed to device. In case the uid is existed in setting
         // mistakenly, try to remove the uid and set correct uids to setting.
         originalUidsAllowedOnRestrictedNetworks.remove(uid);
-        runWithShellPermissionIdentity(() ->
-                ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
-                        mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
+        runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks(
+                mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
 
+        // File a restricted network request with permission first to hold the connection.
         final TestableNetworkCallback testNetworkCb = new TestableNetworkCallback();
         final NetworkRequest testRequest = new NetworkRequest.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
@@ -3240,6 +3241,19 @@
         runWithShellPermissionIdentity(() -> requestNetwork(testRequest, testNetworkCb),
                 CONNECTIVITY_USE_RESTRICTED_NETWORKS);
 
+        // File another restricted network request without permission.
+        final TestableNetworkCallback restrictedNetworkCb = new TestableNetworkCallback();
+        final NetworkRequest restrictedRequest = new NetworkRequest.Builder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+                .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                .setNetworkSpecifier(CompatUtil.makeTestNetworkSpecifier(
+                        TEST_RESTRICTED_NW_IFACE_NAME))
+                .build();
+        // Uid is not in allowed list and no permissions. Expect that SecurityException will throw.
+        assertThrows(SecurityException.class,
+                () -> mCm.requestNetwork(restrictedRequest, restrictedNetworkCb));
+
         final NetworkAgent agent = createRestrictedNetworkAgent(mContext);
         final Network network = agent.getNetwork();
 
@@ -3259,19 +3273,26 @@
             final Set<Integer> newUidsAllowedOnRestrictedNetworks =
                     new ArraySet<>(originalUidsAllowedOnRestrictedNetworks);
             newUidsAllowedOnRestrictedNetworks.add(uid);
-            runWithShellPermissionIdentity(() ->
-                    ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
-                            mContext, newUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
+            runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks(
+                    mContext, newUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
             // Wait a while for sending allowed uids on the restricted network to netd.
-            // TODD: Have a significant signal to know the uids has been send to netd.
+            // TODD: Have a significant signal to know the uids has been sent to netd.
             assertBindSocketToNetworkSuccess(network);
+
+            // Uid is in allowed list. Try file network request again.
+            requestNetwork(restrictedRequest, restrictedNetworkCb);
+            // Verify that the network is restricted.
+            restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+                    NETWORK_CALLBACK_TIMEOUT_MS,
+                    entry -> network.equals(entry.getNetwork())
+                            && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+                            .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
         } finally {
             agent.unregister();
 
             // Restore setting.
-            runWithShellPermissionIdentity(() ->
-                    ConnectivitySettingsManager.setUidsAllowedOnRestrictedNetworks(
-                            mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
+            runWithShellPermissionIdentity(() -> setUidsAllowedOnRestrictedNetworks(
+                    mContext, originalUidsAllowedOnRestrictedNetworks), NETWORK_SETTINGS);
         }
     }
 
@@ -3295,6 +3316,12 @@
         assertTrue(dumpOutput, dumpOutput.contains("BPF map content"));
     }
 
+    private void assumeTestSApis() {
+        // Cannot use @IgnoreUpTo(Build.VERSION_CODES.R) because this test also requires API 31
+        // shims, and @IgnoreUpTo does not check that.
+        assumeTrue(TestUtils.shouldTestSApis());
+    }
+
     private void unregisterRegisteredCallbacks() {
         for (NetworkCallback callback: mRegisteredCallbacks) {
             mCm.unregisterNetworkCallback(callback);
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index f7a2421..04434e5 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -75,7 +75,7 @@
     private val em by lazy { EthernetManagerShimImpl.newInstance(context) }
 
     private val createdIfaces = ArrayList<EthernetTestInterface>()
-    private val addedListeners = ArrayList<InterfaceStateListener>()
+    private val addedListeners = ArrayList<EthernetStateListener>()
 
     private class EthernetTestInterface(
         context: Context,
@@ -171,7 +171,7 @@
         }
     }
 
-    private fun addInterfaceStateListener(executor: Executor, listener: InterfaceStateListener) {
+    private fun addInterfaceStateListener(executor: Executor, listener: EthernetStateListener) {
         em.addInterfaceStateListener(executor, listener)
         addedListeners.add(listener)
     }
@@ -212,15 +212,25 @@
         listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
         listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
 
+        // Register a new listener, it should see state of all existing interfaces immediately.
+        val listener2 = EthernetStateListener()
+        addInterfaceStateListener(executor, listener2)
+        listener2.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
+        listener2.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
+
         // Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE.
         removeInterface(iface)
-        listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
-        listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
+        for (listener in addedListeners) {
+            listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
+            listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
+        }
 
         removeInterface(iface2)
-        listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
-        listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
-        listener.assertNoCallback()
+        for (listener in addedListeners) {
+            listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
+            listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
+            listener.assertNoCallback()
+        }
     }
 
     @Test
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 0504973..d4f3d57 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -1275,4 +1275,23 @@
         matchAllCallback.expectCallback<Lost>(wifiNetwork)
         wifiAgent.expectCallback<OnNetworkUnwanted>()
     }
+
+    @Test
+    fun testUnregisterAgentBeforeAgentFullyConnected() {
+        val specifier = UUID.randomUUID().toString()
+        val callback = TestableNetworkCallback()
+        val transports = intArrayOf(TRANSPORT_CELLULAR)
+        // Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
+        requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
+        val nc = makeTestNetworkCapabilities(specifier, transports)
+        val agent = createNetworkAgent(realContext, initialNc = nc)
+        // Connect the agent
+        agent.register()
+        // Mark agent connected then unregister agent immediately. Verify that both available and
+        // lost callback should be sent still.
+        agent.markConnected()
+        agent.unregister()
+        callback.expectCallback<Available>(agent.network!!)
+        callback.eventuallyExpect<Lost> { it.network == agent.network }
+    }
 }
diff --git a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
index de4f41b..d618915 100644
--- a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
@@ -35,7 +35,14 @@
 
 import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
 
+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 android.app.AppOpsManager;
+import android.app.Instrumentation;
 import android.app.usage.NetworkStats;
 import android.app.usage.NetworkStatsManager;
 import android.content.Context;
@@ -56,15 +63,24 @@
 import android.os.SystemClock;
 import android.platform.test.annotations.AppModeFull;
 import android.telephony.TelephonyManager;
-import android.test.InstrumentationTestCase;
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
 import com.android.compatibility.common.util.ShellIdentityUtils;
 import com.android.compatibility.common.util.SystemUtil;
 import com.android.modules.utils.build.SdkLevel;
+import com.android.testutils.ConnectivityModuleTest;
 import com.android.testutils.DevSdkIgnoreRule;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -78,7 +94,13 @@
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
-public class NetworkStatsManagerTest extends InstrumentationTestCase {
+@ConnectivityModuleTest
+@AppModeFull(reason = "instant apps cannot be granted USAGE_STATS")
+@RunWith(AndroidJUnit4.class)
+public class NetworkStatsManagerTest {
+    @Rule
+    public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(SC_V2 /* ignoreClassUpTo */);
+
     private static final String LOG_TAG = "NetworkStatsManagerTest";
     private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} {1} {2}";
     private static final String APPOPS_GET_SHELL_COMMAND = "appops get {0} {1}";
@@ -179,9 +201,11 @@
             };
 
     private String mPkg;
+    private Context mContext;
     private NetworkStatsManager mNsm;
     private ConnectivityManager mCm;
     private PackageManager mPm;
+    private Instrumentation mInstrumentation;
     private long mStartTime;
     private long mEndTime;
 
@@ -239,44 +263,40 @@
         }
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mNsm = (NetworkStatsManager) getInstrumentation().getContext()
-                .getSystemService(Context.NETWORK_STATS_SERVICE);
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+        mNsm = mContext.getSystemService(NetworkStatsManager.class);
         mNsm.setPollForce(true);
 
-        mCm = (ConnectivityManager) getInstrumentation().getContext()
-                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        mCm = mContext.getSystemService(ConnectivityManager.class);
+        mPm = mContext.getPackageManager();
+        mPkg = mContext.getPackageName();
 
-        mPm = getInstrumentation().getContext().getPackageManager();
-
-        mPkg = getInstrumentation().getContext().getPackageName();
-
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mWriteSettingsMode = getAppOpsMode(AppOpsManager.OPSTR_WRITE_SETTINGS);
         setAppOpsMode(AppOpsManager.OPSTR_WRITE_SETTINGS, "allow");
         mUsageStatsMode = getAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @After
+    public void tearDown() throws Exception {
         if (mWriteSettingsMode != null) {
             setAppOpsMode(AppOpsManager.OPSTR_WRITE_SETTINGS, mWriteSettingsMode);
         }
         if (mUsageStatsMode != null) {
             setAppOpsMode(AppOpsManager.OPSTR_GET_USAGE_STATS, mUsageStatsMode);
         }
-        super.tearDown();
     }
 
     private void setAppOpsMode(String appop, String mode) throws Exception {
         final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND, mPkg, appop, mode);
-        SystemUtil.runShellCommand(command);
+        SystemUtil.runShellCommand(mInstrumentation, command);
     }
 
     private String getAppOpsMode(String appop) throws Exception {
         final String command = MessageFormat.format(APPOPS_GET_SHELL_COMMAND, mPkg, appop);
-        String result = SystemUtil.runShellCommand(command);
+        String result = SystemUtil.runShellCommand(mInstrumentation, command);
         if (result == null) {
             Log.w(LOG_TAG, "App op " + appop + " could not be read.");
         }
@@ -284,7 +304,7 @@
     }
 
     private boolean isInForeground() throws IOException {
-        String result = SystemUtil.runShellCommand(getInstrumentation(),
+        String result = SystemUtil.runShellCommand(mInstrumentation,
                 "cmd activity get-uid-state " + Process.myUid());
         return result.contains("FOREGROUND");
     }
@@ -381,15 +401,14 @@
     private String getSubscriberId(int networkIndex) {
         int networkType = mNetworkInterfacesToTest[networkIndex].getNetworkType();
         if (ConnectivityManager.TYPE_MOBILE == networkType) {
-            TelephonyManager tm = (TelephonyManager) getInstrumentation().getContext()
-                    .getSystemService(Context.TELEPHONY_SERVICE);
+            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
             return ShellIdentityUtils.invokeMethodWithShellPermissions(tm,
                     (telephonyManager) -> telephonyManager.getSubscriberId());
         }
         return "";
     }
 
-    @AppModeFull
+    @Test
     public void testDeviceSummary() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             if (!shouldTestThisNetworkType(i, MINUTE / 2)) {
@@ -425,7 +444,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testUserSummary() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             if (!shouldTestThisNetworkType(i, MINUTE / 2)) {
@@ -461,7 +480,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testAppSummary() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Use tolerance value that large enough to make sure stats of at
@@ -537,7 +556,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testAppDetails() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
@@ -580,7 +599,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testUidDetails() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
@@ -634,7 +653,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testTagDetails() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
@@ -741,7 +760,7 @@
                 bucket.getRxBytes(), bucket.getTxBytes()));
     }
 
-    @AppModeFull
+    @Test
     public void testUidTagStateDetails() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
@@ -818,7 +837,7 @@
         }
     }
 
-    @AppModeFull
+    @Test
     public void testCallback() throws Exception {
         for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
             // Relatively large tolerance to accommodate for history bucket size.
@@ -851,9 +870,10 @@
         }
     }
 
-    @AppModeFull
-    @DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
+    @Test
     public void testDataMigrationUtils() throws Exception {
+        if (!SdkLevel.isAtLeastT()) return;
+
         final List<String> prefixes = List.of(PREFIX_UID, PREFIX_XT, PREFIX_UID_TAG);
         for (final String prefix : prefixes) {
             final long duration = TextUtils.equals(PREFIX_XT, prefix) ? TimeUnit.HOURS.toMillis(1)
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index b139a9b..7b0451f 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -82,6 +82,7 @@
 private const val TAG = "NsdManagerTest"
 private const val SERVICE_TYPE = "_nmt._tcp"
 private const val TIMEOUT_MS = 2000L
+private const val NO_CALLBACK_TIMEOUT_MS = 200L
 private const val DBG = false
 
 private val nsdShim = NsdShimImpl.newInstance()
@@ -136,6 +137,11 @@
                     nextEvent.javaClass.simpleName)
             return nextEvent
         }
+
+        inline fun assertNoCallback(timeoutMs: Long = NO_CALLBACK_TIMEOUT_MS) {
+            val cb = nextEvents.poll(timeoutMs)
+            assertNull(cb, "Expected no callback but got $cb")
+        }
     }
 
     private class NsdRegistrationRecord : RegistrationListener,
@@ -556,6 +562,55 @@
         }
     }
 
+    @Test
+    fun testNsdManager_RegisterOnNetwork() {
+        // This test requires shims supporting T+ APIs (NsdServiceInfo.network)
+        assumeTrue(ConstantsShim.VERSION > SC_V2)
+
+        val si = NsdServiceInfo()
+        si.serviceType = SERVICE_TYPE
+        si.serviceName = this.serviceName
+        si.network = testNetwork1.network
+        si.port = 12345 // Test won't try to connect so port does not matter
+
+        // Register service on testNetwork1
+        val registrationRecord = NsdRegistrationRecord()
+        registerService(registrationRecord, si)
+        val discoveryRecord = NsdDiscoveryRecord()
+        val discoveryRecord2 = NsdDiscoveryRecord()
+        val discoveryRecord3 = NsdDiscoveryRecord()
+
+        tryTest {
+            // Discover service on testNetwork1.
+            nsdShim.discoverServices(nsdManager, SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
+                testNetwork1.network, Executor { it.run() }, discoveryRecord)
+            // Expect that service is found on testNetwork1
+            val foundInfo = discoveryRecord.waitForServiceDiscovered(
+                serviceName, testNetwork1.network)
+            assertEquals(testNetwork1.network, nsdShim.getNetwork(foundInfo))
+
+            // Discover service on testNetwork2.
+            nsdShim.discoverServices(nsdManager, SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
+                testNetwork2.network, Executor { it.run() }, discoveryRecord2)
+            // Expect that discovery is started then no other callbacks.
+            discoveryRecord2.expectCallback<DiscoveryStarted>()
+            discoveryRecord2.assertNoCallback()
+
+            // Discover service on all networks (not specify any network).
+            nsdShim.discoverServices(nsdManager, SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD,
+                null as Network? /* network */, Executor { it.run() }, discoveryRecord3)
+            // Expect that service is found on testNetwork1
+            val foundInfo3 = discoveryRecord3.waitForServiceDiscovered(
+                    serviceName, testNetwork1.network)
+            assertEquals(testNetwork1.network, nsdShim.getNetwork(foundInfo3))
+        } cleanupStep {
+            nsdManager.stopServiceDiscovery(discoveryRecord2)
+            discoveryRecord2.expectCallback<DiscoveryStopped>()
+        } cleanup {
+            nsdManager.unregisterService(registrationRecord)
+        }
+    }
+
     /**
      * Register a service and return its registration record.
      */
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index f96732d..b7da17b 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -106,6 +106,9 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_2;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_3;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_4;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
 import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
 import static android.net.NetworkCapabilities.REDACT_FOR_LOCAL_MAC_ADDRESS;
 import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
@@ -470,6 +473,8 @@
     private static final int TEST_WORK_PROFILE_APP_UID_2 =
             UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID_2);
     private static final int TEST_APP_ID_3 = 105;
+    private static final int TEST_APP_ID_4 = 106;
+    private static final int TEST_APP_ID_5 = 107;
 
     private static final String CLAT_PREFIX = "v4-";
     private static final String MOBILE_IFNAME = "test_rmnet_data0";
@@ -800,6 +805,32 @@
         }
     }
 
+    // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too.
+    private static int toSdkSandboxUid(int appUid) {
+        final int firstSdkSandboxUid = 20000;
+        return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID);
+    }
+
+    // This function assumes the UID range for user 0 ([1, 99999])
+    private static UidRangeParcel[] uidRangeParcelsExcludingUids(Integer... excludedUids) {
+        int start = 1;
+        Arrays.sort(excludedUids);
+        List<UidRangeParcel> parcels = new ArrayList<UidRangeParcel>();
+        for (int excludedUid : excludedUids) {
+            if (excludedUid == start) {
+                start++;
+            } else {
+                parcels.add(new UidRangeParcel(start, excludedUid - 1));
+                start = excludedUid + 1;
+            }
+        }
+        if (start <= 99999) {
+            parcels.add(new UidRangeParcel(start, 99999));
+        }
+
+        return parcels.toArray(new UidRangeParcel[0]);
+    }
+
     private void waitForIdle() {
         HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
         waitForIdle(mCellNetworkAgent, TIMEOUT_MS);
@@ -5875,7 +5906,7 @@
     }
 
     /**
-     * Validate the callback flow CBS request without carrier privilege.
+     * Validate the service throws if request with CBS but without carrier privilege.
      */
     @Test
     public void testCBSRequestWithoutCarrierPrivilege() throws Exception {
@@ -5884,10 +5915,8 @@
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
 
         mServiceContext.setPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, PERMISSION_DENIED);
-        // Now file the test request and expect it.
-        mCm.requestNetwork(nr, networkCallback);
-        networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null);
-        mCm.unregisterNetworkCallback(networkCallback);
+        // Now file the test request and expect the service throws.
+        assertThrows(SecurityException.class, () -> mCm.requestNetwork(nr, networkCallback));
     }
 
     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
@@ -9013,10 +9042,16 @@
                 allowList);
         waitForIdle();
 
-        UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
-        UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
+        final Set<Integer> excludedUids = new ArraySet<Integer>();
+        excludedUids.add(VPN_UID);
+        if (SdkLevel.isAtLeastT()) {
+            // On T onwards, the corresponding SDK sandbox UID should also be excluded
+            excludedUids.add(toSdkSandboxUid(VPN_UID));
+        }
+        final UidRangeParcel[] uidRangeParcels = uidRangeParcelsExcludingUids(
+                excludedUids.toArray(new Integer[0]));
         InOrder inOrder = inOrder(mMockNetd);
-        expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+        expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
 
         // Connect a network when lockdown is active, expect to see it blocked.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -9040,7 +9075,7 @@
         vpnUidCallback.assertNoCallback();
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
-        expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
+        expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -9057,13 +9092,14 @@
         vpnUidDefaultCallback.assertNoCallback();
         vpnDefaultCallbackAsUid.assertNoCallback();
 
-        // The following requires that the UID of this test package is greater than VPN_UID. This
-        // is always true in practice because a plain AOSP build with no apps installed has almost
-        // 200 packages installed.
-        final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1);
-        final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1);
-        final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999);
-        expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3);
+        excludedUids.add(uid);
+        if (SdkLevel.isAtLeastT()) {
+            // On T onwards, the corresponding SDK sandbox UID should also be excluded
+            excludedUids.add(toSdkSandboxUid(uid));
+        }
+        final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs = uidRangeParcelsExcludingUids(
+                excludedUids.toArray(new Integer[0]));
+        expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -9089,12 +9125,12 @@
         // Everything should now be blocked.
         mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
         waitForIdle();
-        expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
+        expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs);
         allowList.clear();
         mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */,
                 allowList);
         waitForIdle();
-        expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+        expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels);
         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
         vpnUidCallback.assertNoCallback();
@@ -14577,6 +14613,40 @@
     }
 
     /**
+     * Make sure per-profile networking preference throws exception when default preference
+     * is set along with enterprise preference.
+     */
+    @Test
+    public void testPreferenceWithInvalidPreferenceDefaultAndEnterpriseTogether()
+            throws Exception {
+        final UserHandle testHandle = setupEnterpriseNetwork();
+        mServiceContext.setWorkProfile(testHandle, true);
+
+        final int testWorkProfileAppUid1 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+        profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+        profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+        final TestOnCompleteListener listener = new TestOnCompleteListener();
+        Assert.assertThrows(IllegalArgumentException.class,
+                () -> mCm.setProfileNetworkPreferences(
+                        testHandle, List.of(profileNetworkPreferenceBuilder1.build(),
+                                profileNetworkPreferenceBuilder2.build()),
+                        r -> r.run(), listener));
+        Assert.assertThrows(IllegalArgumentException.class,
+                () -> mCm.setProfileNetworkPreferences(
+                        testHandle, List.of(profileNetworkPreferenceBuilder2.build(),
+                                profileNetworkPreferenceBuilder1.build()),
+                        r -> r.run(), listener));
+    }
+
+    /**
      * Make sure per profile network preferences behave as expected when two slices with
      * two different apps within same user profile is configured
      * Make sure per profile network preferences overrides with latest preference when
@@ -14616,6 +14686,7 @@
 
         mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
         mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+
         appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
         appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
         appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
@@ -14717,6 +14788,218 @@
     }
 
     /**
+     * Make sure per profile network preferences behave as expected when multiple slices with
+     * multiple different apps within same user profile is configured.
+     */
+    @Test
+    public void testSetPreferenceWithMultiplePreferences()
+            throws Exception {
+        final InOrder inOrder = inOrder(mMockNetd);
+
+        final UserHandle testHandle = setupEnterpriseNetwork();
+        mServiceContext.setWorkProfile(testHandle, true);
+        registerDefaultNetworkCallbacks();
+
+        final TestNetworkCallback appCb1 = new TestNetworkCallback();
+        final TestNetworkCallback appCb2 = new TestNetworkCallback();
+        final TestNetworkCallback appCb3 = new TestNetworkCallback();
+        final TestNetworkCallback appCb4 = new TestNetworkCallback();
+        final TestNetworkCallback appCb5 = new TestNetworkCallback();
+
+        final int testWorkProfileAppUid1 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID);
+        final int testWorkProfileAppUid2 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_2);
+        final int testWorkProfileAppUid3 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_3);
+        final int testWorkProfileAppUid4 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_4);
+        final int testWorkProfileAppUid5 =
+                UserHandle.getUid(testHandle.getIdentifier(), TEST_APP_ID_5);
+
+        registerDefaultNetworkCallbackAsUid(appCb1, testWorkProfileAppUid1);
+        registerDefaultNetworkCallbackAsUid(appCb2, testWorkProfileAppUid2);
+        registerDefaultNetworkCallbackAsUid(appCb3, testWorkProfileAppUid3);
+        registerDefaultNetworkCallbackAsUid(appCb4, testWorkProfileAppUid4);
+        registerDefaultNetworkCallbackAsUid(appCb5, testWorkProfileAppUid5);
+
+        // Connect both a regular cell agent and an enterprise network first.
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+
+        final TestNetworkAgentWrapper workAgent1 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_1);
+        final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_2);
+        final TestNetworkAgentWrapper workAgent3 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_3);
+        final TestNetworkAgentWrapper workAgent4 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_4);
+        final TestNetworkAgentWrapper workAgent5 = makeEnterpriseNetworkAgent(NET_ENTERPRISE_ID_5);
+
+        workAgent1.connect(true);
+        workAgent2.connect(true);
+        workAgent3.connect(true);
+        workAgent4.connect(true);
+        workAgent5.connect(true);
+
+        mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb1.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb2.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb3.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb4.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+        appCb5.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                mCellNetworkAgent.getNetwork().netId, INetd.PERMISSION_NONE));
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                workAgent1.getNetwork().netId, INetd.PERMISSION_SYSTEM));
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                workAgent2.getNetwork().netId, INetd.PERMISSION_SYSTEM));
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                workAgent3.getNetwork().netId, INetd.PERMISSION_SYSTEM));
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                workAgent4.getNetwork().netId, INetd.PERMISSION_SYSTEM));
+        verify(mMockNetd).networkCreate(nativeNetworkConfigPhysical(
+                workAgent5.getNetwork().netId, INetd.PERMISSION_SYSTEM));
+
+        final TestOnCompleteListener listener = new TestOnCompleteListener();
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder1 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder1.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+        profileNetworkPreferenceBuilder1.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+        profileNetworkPreferenceBuilder1.setIncludedUids(new int[]{testWorkProfileAppUid1});
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder2 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder2.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+        profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_2);
+        profileNetworkPreferenceBuilder2.setIncludedUids(new int[]{testWorkProfileAppUid2});
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder3 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder3.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+        profileNetworkPreferenceBuilder3.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_3);
+        profileNetworkPreferenceBuilder3.setIncludedUids(new int[]{testWorkProfileAppUid3});
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder4 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder4.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+        profileNetworkPreferenceBuilder4.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_4);
+        profileNetworkPreferenceBuilder4.setIncludedUids(new int[]{testWorkProfileAppUid4});
+
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder5 =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder5.setPreference(
+                PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+        profileNetworkPreferenceBuilder5.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_5);
+        profileNetworkPreferenceBuilder5.setIncludedUids(new int[]{testWorkProfileAppUid5});
+
+        mCm.setProfileNetworkPreferences(testHandle,
+                List.of(profileNetworkPreferenceBuilder1.build(),
+                        profileNetworkPreferenceBuilder2.build(),
+                        profileNetworkPreferenceBuilder3.build(),
+                        profileNetworkPreferenceBuilder4.build(),
+                        profileNetworkPreferenceBuilder5.build()),
+                r -> r.run(), listener);
+
+        listener.expectOnComplete();
+
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                workAgent1.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                workAgent2.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                workAgent3.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                workAgent4.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                workAgent5.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
+                PREFERENCE_ORDER_PROFILE));
+
+        assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+        appCb1.expectAvailableCallbacksValidated(workAgent1);
+        appCb2.expectAvailableCallbacksValidated(workAgent2);
+        appCb3.expectAvailableCallbacksValidated(workAgent3);
+        appCb4.expectAvailableCallbacksValidated(workAgent4);
+        appCb5.expectAvailableCallbacksValidated(workAgent5);
+
+        workAgent1.disconnect();
+        workAgent2.disconnect();
+        workAgent3.disconnect();
+        workAgent4.disconnect();
+        workAgent5.disconnect();
+
+        appCb1.expectCallback(CallbackEntry.LOST, workAgent1);
+        appCb2.expectCallback(CallbackEntry.LOST, workAgent2);
+        appCb3.expectCallback(CallbackEntry.LOST, workAgent3);
+        appCb4.expectCallback(CallbackEntry.LOST, workAgent4);
+        appCb5.expectCallback(CallbackEntry.LOST, workAgent5);
+
+        appCb1.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb2.assertNoCallback();
+        appCb3.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb4.assertNoCallback();
+        appCb5.expectAvailableCallbacksValidated(mCellNetworkAgent);
+
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder1.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder2.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder3.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd, never()).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder4.build()),
+                PREFERENCE_ORDER_PROFILE));
+        verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
+                mCellNetworkAgent.getNetwork().netId,
+                uidRangeFor(testHandle, profileNetworkPreferenceBuilder5.build()),
+                PREFERENCE_ORDER_PROFILE));
+
+        mSystemDefaultNetworkCallback.assertNoCallback();
+        mDefaultNetworkCallback.assertNoCallback();
+
+        // Set the preferences for testHandle to default.
+        ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
+                new ProfileNetworkPreference.Builder();
+        profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+
+        mCm.setProfileNetworkPreferences(testHandle,
+                List.of(profileNetworkPreferenceBuilder.build()),
+                r -> r.run(), listener);
+        listener.expectOnComplete();
+        assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback, appCb1, appCb3,
+                appCb5);
+        appCb2.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        appCb4.expectAvailableCallbacksValidated(mCellNetworkAgent);
+        mCellNetworkAgent.disconnect();
+
+        mCm.unregisterNetworkCallback(appCb1);
+        mCm.unregisterNetworkCallback(appCb2);
+        mCm.unregisterNetworkCallback(appCb3);
+        mCm.unregisterNetworkCallback(appCb4);
+        mCm.unregisterNetworkCallback(appCb5);
+        // Other callbacks will be unregistered by tearDown()
+    }
+
+    /**
      * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
      * defaults on then off works as expected.
      */
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index 33c0868..46e7dac 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -154,7 +154,7 @@
  */
 @RunWith(DevSdkIgnoreRunner.class)
 @SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.S_V2)
 public class VpnTest {
     private static final String TAG = "VpnTest";
 
@@ -188,7 +188,7 @@
      *  - One pair of packages have consecutive UIDs.
      */
     static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"};
-    static final int[] PKG_UIDS = {66, 77, 78, 400};
+    static final int[] PKG_UIDS = {10066, 10077, 10078, 10400};
 
     // Mock packages
     static final Map<String, Integer> mPackages = new ArrayMap<>();
@@ -345,7 +345,11 @@
                 Arrays.asList(packages), null /* disallowedApplications */);
         assertEquals(rangeSet(
                 uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]),
-                uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])),
+                uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2]),
+                uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0]),
+                         Process.toSdkSandboxUid(userStart + PKG_UIDS[0])),
+                uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[1]),
+                         Process.toSdkSandboxUid(userStart + PKG_UIDS[2]))),
                 allow);
 
         // Denied list
@@ -356,7 +360,11 @@
                 uidRange(userStart, userStart + PKG_UIDS[0] - 1),
                 uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
                 /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
-                uidRange(userStart + PKG_UIDS[2] + 1, userStop)),
+                uidRange(userStart + PKG_UIDS[2] + 1,
+                         Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                         Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)),
                 disallow);
     }
 
@@ -397,18 +405,24 @@
         assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
         }));
 
         // Switch to another app.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
         }));
     }
 
@@ -423,17 +437,25 @@
                 PKGS[1], true, Collections.singletonList(PKGS[2])));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[]  {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1]) - 1),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
         }));
         // Change allowed app list to PKGS[3].
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[1], true, Collections.singletonList(PKGS[3])));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
-                new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
         }));
 
         // Change the VPN app.
@@ -441,32 +463,52 @@
                 PKGS[0], true, Collections.singletonList(PKGS[3])));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1)
+                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
+                new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1))
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1)
+                new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
+                new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1))
         }));
 
         // Remove the list of allowed packages.
         assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[3] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop)
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
-                new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop),
+                new UidRangeParcel(userStart + PKG_UIDS[0] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop),
         }));
 
         // Add the list of allowed packages.
         assertTrue(vpn.setAlwaysOnPackage(
                 PKGS[0], true, Collections.singletonList(PKGS[1])));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
-                new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[0] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop),
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
         }));
 
         // Try allowing a package with a comma, should be rejected.
@@ -479,11 +521,19 @@
                 PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
         verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[1] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop)
         }));
         verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
                 new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1),
-                new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
+                new UidRangeParcel(userStart + PKG_UIDS[2] + 1,
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1),
+                                   Process.toSdkSandboxUid(userStart + PKG_UIDS[2] - 1)),
+                new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)
         }));
     }
 
@@ -528,7 +578,10 @@
         };
         final UidRangeParcel[] exceptPkg0 = {
             new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
-            new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
+            new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1,
+                               Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] - 1)),
+            new UidRangeParcel(Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] + 1),
+                               entireUser[0].stop),
         };
 
         final InOrder order = inOrder(mConnectivityManager);
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
index 5f9d1ff..13a85e8 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -86,11 +86,19 @@
     private static NetworkTemplate sTemplateImsi1 = buildTemplateMobileAll(IMSI_1);
     private static NetworkTemplate sTemplateImsi2 = buildTemplateMobileAll(IMSI_2);
 
+    private static final int PID_SYSTEM = 1234;
+    private static final int PID_RED = 1235;
+    private static final int PID_BLUE = 1236;
+
     private static final int UID_RED = UserHandle.PER_USER_RANGE + 1;
     private static final int UID_BLUE = UserHandle.PER_USER_RANGE + 2;
     private static final int UID_GREEN = UserHandle.PER_USER_RANGE + 3;
     private static final int UID_ANOTHER_USER = 2 * UserHandle.PER_USER_RANGE + 4;
 
+    private static final String PACKAGE_SYSTEM = "android";
+    private static final String PACKAGE_RED = "RED";
+    private static final String PACKAGE_BLUE = "BLUE";
+
     private static final long WAIT_TIMEOUT_MS = 500;
     private static final long THRESHOLD_BYTES = 2 * MB_IN_BYTES;
     private static final long BASE_BYTES = 7 * MB_IN_BYTES;
@@ -131,14 +139,15 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, thresholdTooLowBytes);
 
         final DataUsageRequest requestByApp = mStatsObservers.register(mContext, inputRequest,
-                mUsageCallback, UID_RED, NetworkStatsAccess.Level.DEVICE);
+                mUsageCallback, PID_RED , UID_RED, PACKAGE_RED, NetworkStatsAccess.Level.DEVICE);
         assertTrue(requestByApp.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, requestByApp.template));
         assertEquals(thresholdTooLowBytes, requestByApp.thresholdInBytes);
 
         // Verify the threshold requested by system uid won't be overridden.
         final DataUsageRequest requestBySystem = mStatsObservers.register(mContext, inputRequest,
-                mUsageCallback, Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                mUsageCallback, PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM,
+                NetworkStatsAccess.Level.DEVICE);
         assertTrue(requestBySystem.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, requestBySystem.template));
         assertEquals(1, requestBySystem.thresholdInBytes);
@@ -151,7 +160,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, highThresholdBytes);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, request.template));
         assertEquals(highThresholdBytes, request.thresholdInBytes);
@@ -163,13 +172,13 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateWifi, THRESHOLD_BYTES);
 
         DataUsageRequest request1 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request1.requestId > 0);
         assertTrue(Objects.equals(sTemplateWifi, request1.template));
         assertEquals(THRESHOLD_BYTES, request1.thresholdInBytes);
 
         DataUsageRequest request2 = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request2.requestId > request1.requestId);
         assertTrue(Objects.equals(sTemplateWifi, request2.template));
         assertEquals(THRESHOLD_BYTES, request2.thresholdInBytes);
@@ -189,7 +198,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -209,7 +218,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                UID_RED, NetworkStatsAccess.Level.DEVICE);
+                PID_RED, UID_RED, PACKAGE_RED, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -237,7 +246,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -261,7 +270,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -291,7 +300,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                Process.SYSTEM_UID, NetworkStatsAccess.Level.DEVICE);
+                PID_SYSTEM, Process.SYSTEM_UID, PACKAGE_SYSTEM, NetworkStatsAccess.Level.DEVICE);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -322,7 +331,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                UID_RED, NetworkStatsAccess.Level.DEFAULT);
+                PID_RED, UID_RED, PACKAGE_SYSTEM , NetworkStatsAccess.Level.DEFAULT);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -355,7 +364,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                UID_BLUE, NetworkStatsAccess.Level.DEFAULT);
+                PID_BLUE, UID_BLUE, PACKAGE_BLUE, NetworkStatsAccess.Level.DEFAULT);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -387,7 +396,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                UID_BLUE, NetworkStatsAccess.Level.USER);
+                PID_BLUE, UID_BLUE, PACKAGE_BLUE, NetworkStatsAccess.Level.USER);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
@@ -420,7 +429,7 @@
                 DataUsageRequest.REQUEST_ID_UNSET, sTemplateImsi1, THRESHOLD_BYTES);
 
         DataUsageRequest request = mStatsObservers.register(mContext, inputRequest, mUsageCallback,
-                UID_RED, NetworkStatsAccess.Level.USER);
+                PID_RED, UID_RED, PACKAGE_RED, NetworkStatsAccess.Level.USER);
         assertTrue(request.requestId > 0);
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);