Merge "Split parcelable .aidl files to aidl-export" into sc-dev
diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java
index 3bc0f9c..b172ccc 100644
--- a/core/java/android/net/UidRange.java
+++ b/core/java/android/net/UidRange.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 
 import java.util.Collection;
 
@@ -45,6 +46,14 @@
         return new UidRange(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
     }
 
+    /** Creates a UidRange for the specified user. */
+    public static UidRange createForUser(UserHandle user) {
+        final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
+        final int start = UserHandle.getUid(user, 0 /* appId */);
+        final int end = UserHandle.getUid(nextUser, 0) - 1;
+        return new UidRange(start, end);
+    }
+
     /** Returns the smallest user Id which is contained in this UidRange */
     public int getStartUser() {
         return start / PER_USER_RANGE;
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 92d7bf0..d7c8291 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -456,7 +456,7 @@
      * @hide
      */
     @SystemApi
-    public static final int TETHERING_WIFI      = TetheringManager.TETHERING_WIFI;
+    public static final int TETHERING_WIFI      = 0;
 
     /**
      * USB tethering type.
@@ -464,7 +464,7 @@
      * @hide
      */
     @SystemApi
-    public static final int TETHERING_USB       = TetheringManager.TETHERING_USB;
+    public static final int TETHERING_USB       = 1;
 
     /**
      * Bluetooth tethering type.
@@ -472,7 +472,7 @@
      * @hide
      */
     @SystemApi
-    public static final int TETHERING_BLUETOOTH = TetheringManager.TETHERING_BLUETOOTH;
+    public static final int TETHERING_BLUETOOTH = 2;
 
     /**
      * Wifi P2p tethering type.
@@ -2799,7 +2799,7 @@
      */
     @SystemApi
     @Deprecated
-    public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR;
+    public static final int TETHER_ERROR_NO_ERROR = 0;
     /**
      * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}.
      * {@hide}
@@ -2875,8 +2875,7 @@
      */
     @SystemApi
     @Deprecated
-    public static final int TETHER_ERROR_PROVISION_FAILED =
-            TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+    public static final int TETHER_ERROR_PROVISION_FAILED = 11;
     /**
      * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}.
      * {@hide}
@@ -2890,8 +2889,7 @@
      */
     @SystemApi
     @Deprecated
-    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN =
-            TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
+    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13;
 
     /**
      * Get a more detailed error code after a Tethering or Untethering
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index 4e89414..a174a7b 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -41,7 +41,6 @@
 
     /**
      * Prefix for tap interfaces created by this class.
-     * @hide
      */
     public static final String TEST_TAP_PREFIX = "testtap";
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 558fbc2..154e183 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3584,10 +3584,10 @@
     }
 
     private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
-        handleRegisterNetworkRequest(Collections.singletonList(nri));
+        handleRegisterNetworkRequests(Collections.singleton(nri));
     }
 
-    private void handleRegisterNetworkRequest(@NonNull final List<NetworkRequestInfo> nris) {
+    private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
         ensureRunningOnConnectivityServiceThread();
         for (final NetworkRequestInfo nri : nris) {
             mNetworkRequestInfoLogs.log("REGISTER " + nri);
@@ -3718,7 +3718,10 @@
 
     private NetworkRequestInfo getNriForAppRequest(
             NetworkRequest request, int callingUid, String requestedOperation) {
-        final NetworkRequestInfo nri = mNetworkRequests.get(request);
+        // Looking up the app passed param request in mRequests isn't possible since it may return
+        // null for a request managed by a per-app default. Therefore use getNriForAppRequest() to
+        // do the lookup since that will also find per-app default managed requests.
+        final NetworkRequestInfo nri = getNriForAppRequest(request);
 
         if (nri != null) {
             if (Process.SYSTEM_UID != callingUid && Process.NETWORK_STACK_UID != callingUid
@@ -3767,8 +3770,6 @@
         if (nri == null) {
             return;
         }
-        // handleReleaseNetworkRequest() paths don't apply to multilayer requests.
-        ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequest");
         if (VDBG || (DBG && request.isRequest())) {
             log("releasing " + request + " (release request)");
         }
@@ -3780,7 +3781,6 @@
 
     private void handleRemoveNetworkRequest(@NonNull final NetworkRequestInfo nri) {
         ensureRunningOnConnectivityServiceThread();
-
         nri.unlinkDeathRecipient();
         for (final NetworkRequest req : nri.mRequests) {
             mNetworkRequests.remove(req);
@@ -3803,6 +3803,16 @@
         cancelNpiRequests(nri);
     }
 
+    private void handleRemoveNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
+        for (final NetworkRequestInfo nri : nris) {
+            if (mDefaultRequest == nri) {
+                // Make sure we never remove the default request.
+                continue;
+            }
+            handleRemoveNetworkRequest(nri);
+        }
+    }
+
     private void cancelNpiRequests(@NonNull final NetworkRequestInfo nri) {
         for (final NetworkRequest req : nri.mRequests) {
             cancelNpiRequest(req);
@@ -4973,12 +4983,12 @@
         }
     }
 
-    private void onUserAdded(int userId) {
-        mPermissionMonitor.onUserAdded(userId);
+    private void onUserAdded(UserHandle user) {
+        mPermissionMonitor.onUserAdded(user);
     }
 
-    private void onUserRemoved(int userId) {
-        mPermissionMonitor.onUserRemoved(userId);
+    private void onUserRemoved(UserHandle user) {
+        mPermissionMonitor.onUserRemoved(user);
     }
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -4986,15 +4996,18 @@
         public void onReceive(Context context, Intent intent) {
             ensureRunningOnConnectivityServiceThread();
             final String action = intent.getAction();
-            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+            final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
 
-            // UserId should be filled for below intents, check the existence.
-            if (userId == UserHandle.USER_NULL) return;
+            // User should be filled for below intents, check the existence.
+            if (user == null) {
+                Log.wtf(TAG, intent.getAction() + " broadcast without EXTRA_USER");
+                return;
+            }
 
             if (Intent.ACTION_USER_ADDED.equals(action)) {
-                onUserAdded(userId);
+                onUserAdded(user);
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                onUserRemoved(userId);
+                onUserRemoved(user);
             }  else {
                 Log.wtf(TAG, "received unexpected intent: " + action);
             }
@@ -5107,6 +5120,21 @@
         final int mUid;
         @Nullable
         final String mCallingAttributionTag;
+        // In order to preserve the mapping of NetworkRequest-to-callback when apps register
+        // callbacks using a returned NetworkRequest, the original NetworkRequest needs to be
+        // maintained for keying off of. This is only a concern when the original nri
+        // mNetworkRequests changes which happens currently for apps that register callbacks to
+        // track the default network. In those cases, the nri is updated to have mNetworkRequests
+        // that match the per-app default nri that currently tracks the calling app's uid so that
+        // callbacks are fired at the appropriate time. When the callbacks fire,
+        // mNetworkRequestForCallback will be used so as to preserve the caller's mapping. When
+        // callbacks are updated to key off of an nri vs NetworkRequest, this stops being an issue.
+        // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
+        @NonNull
+        private final NetworkRequest mNetworkRequestForCallback;
+        NetworkRequest getNetworkRequestForCallback() {
+            return mNetworkRequestForCallback;
+        }
 
         /**
          * Get the list of UIDs this nri applies to.
@@ -5122,13 +5150,15 @@
 
         NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi,
                 @Nullable String callingAttributionTag) {
-            this(Collections.singletonList(r), pi, callingAttributionTag);
+            this(Collections.singletonList(r), r, pi, callingAttributionTag);
         }
 
         NetworkRequestInfo(@NonNull final List<NetworkRequest> r,
-                @Nullable final PendingIntent pi, @Nullable String callingAttributionTag) {
+                @NonNull final NetworkRequest requestForCallback, @Nullable final PendingIntent pi,
+                @Nullable String callingAttributionTag) {
+            ensureAllNetworkRequestsHaveType(r);
             mRequests = initializeRequests(r);
-            ensureAllNetworkRequestsHaveType(mRequests);
+            mNetworkRequestForCallback = requestForCallback;
             mPendingIntent = pi;
             mMessenger = null;
             mBinder = null;
@@ -5140,15 +5170,17 @@
 
         NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final Messenger m,
                 @Nullable final IBinder binder, @Nullable String callingAttributionTag) {
-            this(Collections.singletonList(r), m, binder, callingAttributionTag);
+            this(Collections.singletonList(r), r, m, binder, callingAttributionTag);
         }
 
-        NetworkRequestInfo(@NonNull final List<NetworkRequest> r, @Nullable final Messenger m,
+        NetworkRequestInfo(@NonNull final List<NetworkRequest> r,
+                @NonNull final NetworkRequest requestForCallback, @Nullable final Messenger m,
                 @Nullable final IBinder binder, @Nullable String callingAttributionTag) {
             super();
+            ensureAllNetworkRequestsHaveType(r);
             mRequests = initializeRequests(r);
+            mNetworkRequestForCallback = requestForCallback;
             mMessenger = m;
-            ensureAllNetworkRequestsHaveType(mRequests);
             mBinder = binder;
             mPid = getCallingPid();
             mUid = mDeps.getCallingUid();
@@ -5163,12 +5195,26 @@
             }
         }
 
+        NetworkRequestInfo(@NonNull final NetworkRequestInfo nri,
+                @NonNull final List<NetworkRequest> r) {
+            super();
+            ensureAllNetworkRequestsHaveType(r);
+            mRequests = initializeRequests(r);
+            mNetworkRequestForCallback = nri.getNetworkRequestForCallback();
+            mMessenger = nri.mMessenger;
+            mBinder = nri.mBinder;
+            mPid = nri.mPid;
+            mUid = nri.mUid;
+            mPendingIntent = nri.mPendingIntent;
+            mCallingAttributionTag = nri.mCallingAttributionTag;
+        }
+
         NetworkRequestInfo(@NonNull final NetworkRequest r) {
             this(Collections.singletonList(r));
         }
 
         NetworkRequestInfo(@NonNull final List<NetworkRequest> r) {
-            this(r, null /* pi */, null /* callingAttributionTag */);
+            this(r, r.get(0), null /* pi */, null /* callingAttributionTag */);
         }
 
         // True if this NRI is being satisfied. It also accounts for if the nri has its satisifer
@@ -5327,7 +5373,8 @@
                 // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
                 // is unused and will be replaced by ones appropriate for the caller.
                 // This allows callers to keep track of the default network for their app.
-                networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
+                networkCapabilities = copyDefaultNetworkCapabilitiesForUid(
+                        defaultNc, callingUid, callingPackageName);
                 enforceAccessPermission();
                 break;
             case TRACK_SYSTEM_DEFAULT:
@@ -5366,10 +5413,10 @@
         }
         ensureValid(networkCapabilities);
 
-        NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
+        final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
                 nextNetworkRequestId(), reqType);
-        NetworkRequestInfo nri =
-                new NetworkRequestInfo(networkRequest, messenger, binder, callingAttributionTag);
+        final NetworkRequestInfo nri = getNriToRegister(
+                networkRequest, messenger, binder, callingAttributionTag);
         if (DBG) log("requestNetwork for " + nri);
 
         // For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were
@@ -5391,6 +5438,30 @@
         return networkRequest;
     }
 
+    /**
+     * Return the nri to be used when registering a network request. Specifically, this is used with
+     * requests registered to track the default request. If there is currently a per-app default
+     * tracking the app requestor, then we need to create a version of this nri that mirrors that of
+     * the tracking per-app default so that callbacks are sent to the app requestor appropriately.
+     * @param nr the network request for the nri.
+     * @param msgr the messenger for the nri.
+     * @param binder the binder for the nri.
+     * @param callingAttributionTag the calling attribution tag for the nri.
+     * @return the nri to register.
+     */
+    private NetworkRequestInfo getNriToRegister(@NonNull final NetworkRequest nr,
+            @Nullable final Messenger msgr, @Nullable final IBinder binder,
+            @Nullable String callingAttributionTag) {
+        final List<NetworkRequest> requests;
+        if (NetworkRequest.Type.TRACK_DEFAULT == nr.type) {
+            requests = copyDefaultNetworkRequestsForUid(
+                    nr.getRequestorUid(), nr.getRequestorPackageName());
+        } else {
+            requests = Collections.singletonList(nr);
+        }
+        return new NetworkRequestInfo(requests, nr, msgr, binder, callingAttributionTag);
+    }
+
     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities,
             String callingPackageName, String callingAttributionTag) {
         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
@@ -5684,6 +5755,102 @@
     }
 
     /**
+     * Return the default network request currently tracking the given uid.
+     * @param uid the uid to check.
+     * @return the NetworkRequestInfo tracking the given uid.
+     */
+    @NonNull
+    private NetworkRequestInfo getDefaultRequestTrackingUid(@NonNull final int uid) {
+        for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
+            if (nri == mDefaultRequest) {
+                continue;
+            }
+            // Checking the first request is sufficient as only multilayer requests will have more
+            // than one request and for multilayer, all requests will track the same uids.
+            if (nri.mRequests.get(0).networkCapabilities.appliesToUid(uid)) {
+                return nri;
+            }
+        }
+        return mDefaultRequest;
+    }
+
+    /**
+     * Get a copy of the network requests of the default request that is currently tracking the
+     * given uid.
+     * @param requestorUid the uid to check the default for.
+     * @param requestorPackageName the requestor's package name.
+     * @return a copy of the default's NetworkRequest that is tracking the given uid.
+     */
+    @NonNull
+    private List<NetworkRequest> copyDefaultNetworkRequestsForUid(
+            @NonNull final int requestorUid, @NonNull final String requestorPackageName) {
+        return copyNetworkRequestsForUid(
+                getDefaultRequestTrackingUid(requestorUid).mRequests,
+                requestorUid, requestorPackageName);
+    }
+
+    /**
+     * Copy the given nri's NetworkRequest collection.
+     * @param requestsToCopy the NetworkRequest collection to be copied.
+     * @param requestorUid the uid to set on the copied collection.
+     * @param requestorPackageName the package name to set on the copied collection.
+     * @return the copied NetworkRequest collection.
+     */
+    @NonNull
+    private List<NetworkRequest> copyNetworkRequestsForUid(
+            @NonNull final List<NetworkRequest> requestsToCopy, @NonNull final int requestorUid,
+            @NonNull final String requestorPackageName) {
+        final List<NetworkRequest> requests = new ArrayList<>();
+        for (final NetworkRequest nr : requestsToCopy) {
+            requests.add(new NetworkRequest(copyDefaultNetworkCapabilitiesForUid(
+                            nr.networkCapabilities, requestorUid, requestorPackageName),
+                    nr.legacyType, nextNetworkRequestId(), nr.type));
+        }
+        return requests;
+    }
+
+    @NonNull
+    private NetworkCapabilities copyDefaultNetworkCapabilitiesForUid(
+            @NonNull final NetworkCapabilities netCapToCopy, @NonNull final int requestorUid,
+            @NonNull final String requestorPackageName) {
+        final NetworkCapabilities netCap = new NetworkCapabilities(netCapToCopy);
+        netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
+        netCap.setSingleUid(requestorUid);
+        netCap.setUids(new ArraySet<>());
+        restrictRequestUidsForCallerAndSetRequestorInfo(
+                netCap, requestorUid, requestorPackageName);
+        return netCap;
+    }
+
+    /**
+     * Get the nri that is currently being tracked for callbacks by per-app defaults.
+     * @param nr the network request to check for equality against.
+     * @return the nri if one exists, null otherwise.
+     */
+    @Nullable
+    private NetworkRequestInfo getNriForAppRequest(@NonNull final NetworkRequest nr) {
+        for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+            if (nri.getNetworkRequestForCallback().equals(nr)) {
+                return nri;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Check if an nri is currently being managed by per-app default networking.
+     * @param nri the nri to check.
+     * @return true if this nri is currently being managed by per-app default networking.
+     */
+    private boolean isPerAppTrackedNri(@NonNull final NetworkRequestInfo nri) {
+        // nri.mRequests.get(0) is only different from the original request filed in
+        // nri.getNetworkRequestForCallback() if nri.mRequests was changed by per-app default
+        // functionality therefore if these two don't match, it means this particular nri is
+        // currently being managed by a per-app default.
+        return nri.getNetworkRequestForCallback() != nri.mRequests.get(0);
+    }
+
+    /**
      * Determine if an nri is a managed default request that disallows default networking.
      * @param nri the request to evaluate
      * @return true if device-default networking is disallowed
@@ -6761,13 +6928,9 @@
             return;
         }
         Bundle bundle = new Bundle();
-        // In the case of multi-layer NRIs, the first request is not necessarily the one that
-        // is satisfied. This is vexing, but the ConnectivityManager code that receives this
-        // callback is only using the request as a token to identify the callback, so it doesn't
-        // matter too much at this point as long as the callback can be found.
         // TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
         // TODO: check if defensive copies of data is needed.
-        final NetworkRequest nrForCallback = new NetworkRequest(nri.mRequests.get(0));
+        final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback();
         putParcelable(bundle, nrForCallback);
         Message msg = Message.obtain();
         if (notificationType != ConnectivityManager.CALLBACK_UNAVAIL) {
@@ -8707,7 +8870,7 @@
         if (DBG) {
             log("set OEM network preferences :" + preference.toString());
         }
-        final List<NetworkRequestInfo> nris =
+        final ArraySet<NetworkRequestInfo> nris =
                 new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
         updateDefaultNetworksForOemNetworkPreference(nris);
         mOemNetworkPreferences = preference;
@@ -8719,27 +8882,88 @@
     }
 
     private void updateDefaultNetworksForOemNetworkPreference(
-            @NonNull final List<NetworkRequestInfo> nris) {
-        ensureRunningOnConnectivityServiceThread();
-        clearNonDefaultNetworkAgents();
-        addDefaultNetworkRequests(nris);
+            @NonNull final Set<NetworkRequestInfo> nris) {
+        handleRemoveNetworkRequests(mDefaultNetworkRequests);
+        addPerAppDefaultNetworkRequests(nris);
     }
 
-    private void clearNonDefaultNetworkAgents() {
-        // Copy mDefaultNetworkRequests to iterate and remove elements from it in
-        // handleRemoveNetworkRequest() without getting a ConcurrentModificationException.
-        final NetworkRequestInfo[] nris =
-                mDefaultNetworkRequests.toArray(new NetworkRequestInfo[0]);
+    private void addPerAppDefaultNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
+        ensureRunningOnConnectivityServiceThread();
+        mDefaultNetworkRequests.addAll(nris);
+        final ArraySet<NetworkRequestInfo> perAppCallbackRequestsToUpdate =
+                getPerAppCallbackRequestsToUpdate();
+        handleRemoveNetworkRequests(perAppCallbackRequestsToUpdate);
+        final ArraySet<NetworkRequestInfo> nrisToRegister = new ArraySet<>(nris);
+        nrisToRegister.addAll(
+                createPerAppCallbackRequestsToRegister(perAppCallbackRequestsToUpdate));
+        handleRegisterNetworkRequests(nrisToRegister);
+    }
+
+    /**
+     * All current requests that are tracking the default network need to be assessed as to whether
+     * or not the current set of per-application default requests will be changing their default
+     * network. If so, those requests will need to be updated so that they will send callbacks for
+     * default network changes at the appropriate time. Additionally, those requests tracking the
+     * default that were previously updated by this flow will need to be reassessed.
+     * @return the nris which will need to be updated.
+     */
+    private ArraySet<NetworkRequestInfo> getPerAppCallbackRequestsToUpdate() {
+        final ArraySet<NetworkRequestInfo> defaultCallbackRequests = new ArraySet<>();
+        // Get the distinct nris to check since for multilayer requests, it is possible to have the
+        // same nri in the map's values for each of its NetworkRequest objects.
+        final ArraySet<NetworkRequestInfo> nris = new ArraySet<>(mNetworkRequests.values());
         for (final NetworkRequestInfo nri : nris) {
-            if (mDefaultRequest != nri) {
-                handleRemoveNetworkRequest(nri);
+            // Include this nri if it is currently being tracked.
+            if (isPerAppTrackedNri(nri)) {
+                defaultCallbackRequests.add(nri);
+                continue;
+            }
+            // We only track callbacks for requests tracking the default.
+            if (NetworkRequest.Type.TRACK_DEFAULT != nri.mRequests.get(0).type) {
+                continue;
+            }
+            // Include this nri if it will be tracked by the new per-app default requests.
+            final boolean isNriGoingToBeTracked =
+                    getDefaultRequestTrackingUid(nri.mUid) != mDefaultRequest;
+            if (isNriGoingToBeTracked) {
+                defaultCallbackRequests.add(nri);
             }
         }
+        return defaultCallbackRequests;
     }
 
-    private void addDefaultNetworkRequests(@NonNull final List<NetworkRequestInfo> nris) {
-        mDefaultNetworkRequests.addAll(nris);
-        handleRegisterNetworkRequest(nris);
+    /**
+     * Create nris for those network requests that are currently tracking the default network that
+     * are being controlled by a per-application default.
+     * @param perAppCallbackRequestsForUpdate the baseline network requests to be used as the
+     * foundation when creating the nri. Important items include the calling uid's original
+     * NetworkRequest to be used when mapping callbacks as well as the caller's uid and name. These
+     * requests are assumed to have already been validated as needing to be updated.
+     * @return the Set of nris to use when registering network requests.
+     */
+    private ArraySet<NetworkRequestInfo> createPerAppCallbackRequestsToRegister(
+            @NonNull final ArraySet<NetworkRequestInfo> perAppCallbackRequestsForUpdate) {
+        final ArraySet<NetworkRequestInfo> callbackRequestsToRegister = new ArraySet<>();
+        for (final NetworkRequestInfo callbackRequest : perAppCallbackRequestsForUpdate) {
+            final NetworkRequestInfo trackingNri =
+                    getDefaultRequestTrackingUid(callbackRequest.mUid);
+
+            // If this nri is not being tracked, the change it back to an untracked nri.
+            if (trackingNri == mDefaultRequest) {
+                callbackRequestsToRegister.add(new NetworkRequestInfo(
+                        callbackRequest,
+                        Collections.singletonList(callbackRequest.getNetworkRequestForCallback())));
+                continue;
+            }
+
+            final String requestorPackageName =
+                    callbackRequest.mRequests.get(0).getRequestorPackageName();
+            callbackRequestsToRegister.add(new NetworkRequestInfo(
+                    callbackRequest,
+                    copyNetworkRequestsForUid(
+                            trackingNri.mRequests, callbackRequest.mUid, requestorPackageName)));
+        }
+        return callbackRequestsToRegister;
     }
 
     /**
@@ -8747,9 +8971,9 @@
      */
     @VisibleForTesting
     final class OemNetworkRequestFactory {
-        List<NetworkRequestInfo> createNrisFromOemNetworkPreferences(
+        ArraySet<NetworkRequestInfo> createNrisFromOemNetworkPreferences(
                 @NonNull final OemNetworkPreferences preference) {
-            final List<NetworkRequestInfo> nris = new ArrayList<>();
+            final ArraySet<NetworkRequestInfo> nris = new ArraySet<>();
             final SparseArray<Set<Integer>> uids =
                     createUidsFromOemNetworkPreferences(preference);
             for (int i = 0; i < uids.size(); i++) {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 8d21f6f..8bf1886 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -83,9 +83,8 @@
     private final INetd mNetd;
     private final Dependencies mDeps;
 
-    // Values are User IDs.
     @GuardedBy("this")
-    private final Set<Integer> mUsers = new HashSet<>();
+    private final Set<UserHandle> mUsers = new HashSet<>();
 
     // Keys are app uids. Values are true for SYSTEM permission and false for NETWORK permission.
     @GuardedBy("this")
@@ -173,10 +172,7 @@
             netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
         }
 
-        final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */);
-        for (UserHandle user : users) {
-            mUsers.add(user.getIdentifier());
-        }
+        mUsers.addAll(mUserManager.getUserHandles(true /* excludeDying */));
 
         final SparseArray<ArraySet<String>> systemPermission =
                 SystemConfig.getInstance().getSystemPermissions();
@@ -259,16 +255,15 @@
         return array;
     }
 
-    private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) {
+    private void update(Set<UserHandle> users, Map<Integer, Boolean> apps, boolean add) {
         List<Integer> network = new ArrayList<>();
         List<Integer> system = new ArrayList<>();
         for (Entry<Integer, Boolean> app : apps.entrySet()) {
             List<Integer> list = app.getValue() ? system : network;
-            for (int user : users) {
-                final UserHandle handle = UserHandle.of(user);
-                if (handle == null) continue;
+            for (UserHandle user : users) {
+                if (user == null) continue;
 
-                list.add(UserHandle.getUid(handle, app.getKey()));
+                list.add(UserHandle.getUid(user, app.getKey()));
             }
         }
         try {
@@ -291,14 +286,10 @@
      *
      * @hide
      */
-    public synchronized void onUserAdded(int user) {
-        if (user < 0) {
-            loge("Invalid user in onUserAdded: " + user);
-            return;
-        }
+    public synchronized void onUserAdded(@NonNull UserHandle user) {
         mUsers.add(user);
 
-        Set<Integer> users = new HashSet<>();
+        Set<UserHandle> users = new HashSet<>();
         users.add(user);
         update(users, mApps, true);
     }
@@ -310,14 +301,10 @@
      *
      * @hide
      */
-    public synchronized void onUserRemoved(int user) {
-        if (user < 0) {
-            loge("Invalid user in onUserRemoved: " + user);
-            return;
-        }
+    public synchronized void onUserRemoved(@NonNull UserHandle user) {
         mUsers.remove(user);
 
-        Set<Integer> users = new HashSet<>();
+        Set<UserHandle> users = new HashSet<>();
         users.add(user);
         update(users, mApps, false);
     }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2a693eb..1358410 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -66,6 +66,8 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
@@ -169,6 +171,7 @@
 import android.net.INetworkMonitorCallbacks;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkStatsService;
+import android.net.IOnSetOemNetworkPreferenceListener;
 import android.net.IQosCallback;
 import android.net.InetAddresses;
 import android.net.InterfaceConfigurationParcel;
@@ -192,6 +195,7 @@
 import android.net.NetworkStackClient;
 import android.net.NetworkState;
 import android.net.NetworkTestResultParcelable;
+import android.net.OemNetworkPreferences;
 import android.net.ProxyInfo;
 import android.net.QosCallbackException;
 import android.net.QosFilter;
@@ -300,6 +304,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -359,6 +364,7 @@
     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
     private static final String VPN_IFNAME = "tun10042";
     private static final String TEST_PACKAGE_NAME = "com.android.test.package";
+    private static final int TEST_PACKAGE_UID = 123;
     private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
 
     private static final String INTERFACE_NAME = "interface";
@@ -418,6 +424,7 @@
     @Mock EthernetManager mEthernetManager;
     @Mock NetworkPolicyManager mNetworkPolicyManager;
     @Mock KeyStore mKeyStore;
+    @Mock IOnSetOemNetworkPreferenceListener mOnSetOemNetworkPreferenceListener;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
             ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -9422,4 +9429,264 @@
         }
         fail("TOO_MANY_REQUESTS never thrown");
     }
+
+    private void mockGetApplicationInfo(@NonNull final String packageName, @NonNull final int uid)
+            throws PackageManager.NameNotFoundException {
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = uid;
+        when(mPackageManager.getApplicationInfo(eq(packageName), anyInt()))
+                .thenReturn(applicationInfo);
+    }
+
+    private void mockHasSystemFeature(@NonNull final String featureName,
+            @NonNull final boolean hasFeature) {
+        when(mPackageManager.hasSystemFeature(eq(featureName)))
+                .thenReturn(hasFeature);
+    }
+
+    private UidRange getNriFirstUidRange(
+            @NonNull final ConnectivityService.NetworkRequestInfo nri) {
+        return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
+    }
+
+    private OemNetworkPreferences createDefaultOemNetworkPreferences(
+            @OemNetworkPreferences.OemNetworkPreference final int preference)
+            throws PackageManager.NameNotFoundException {
+        // Arrange PackageManager mocks
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+
+        // Build OemNetworkPreferences object
+        return new OemNetworkPreferences.Builder()
+                .addNetworkPreference(TEST_PACKAGE_NAME, preference)
+                .build();
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryPreferenceUninitializedThrowsError()
+            throws PackageManager.NameNotFoundException {
+        @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_UNINITIALIZED;
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        assertThrows(IllegalArgumentException.class,
+                () -> mService.new OemNetworkRequestFactory()
+                        .createNrisFromOemNetworkPreferences(
+                                createDefaultOemNetworkPreferences(prefToTest)));
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryPreferenceOemPaid()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 1;
+        final int expectedNumOfRequests = 3;
+
+        @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory()
+                        .createNrisFromOemNetworkPreferences(
+                                createDefaultOemNetworkPreferences(prefToTest));
+
+        final List<NetworkRequest> mRequests = nris.iterator().next().mRequests;
+        assertEquals(expectedNumOfNris, nris.size());
+        assertEquals(expectedNumOfRequests, mRequests.size());
+        assertTrue(mRequests.get(0).isListen());
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
+        assertTrue(mRequests.get(1).isRequest());
+        assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
+        assertTrue(mRequests.get(2).isRequest());
+        assertTrue(mService.getDefaultRequest().networkCapabilities.equalsNetCapabilities(
+                mRequests.get(2).networkCapabilities));
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryPreferenceOemPaidNoFallback()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 1;
+        final int expectedNumOfRequests = 2;
+
+        @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory()
+                        .createNrisFromOemNetworkPreferences(
+                                createDefaultOemNetworkPreferences(prefToTest));
+
+        final List<NetworkRequest> mRequests = nris.iterator().next().mRequests;
+        assertEquals(expectedNumOfNris, nris.size());
+        assertEquals(expectedNumOfRequests, mRequests.size());
+        assertTrue(mRequests.get(0).isListen());
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_NOT_METERED));
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_VALIDATED));
+        assertTrue(mRequests.get(1).isRequest());
+        assertTrue(mRequests.get(1).hasCapability(NET_CAPABILITY_OEM_PAID));
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryPreferenceOemPaidOnly()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 1;
+        final int expectedNumOfRequests = 1;
+
+        @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY;
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory()
+                        .createNrisFromOemNetworkPreferences(
+                                createDefaultOemNetworkPreferences(prefToTest));
+
+        final List<NetworkRequest> mRequests = nris.iterator().next().mRequests;
+        assertEquals(expectedNumOfNris, nris.size());
+        assertEquals(expectedNumOfRequests, mRequests.size());
+        assertTrue(mRequests.get(0).isRequest());
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryPreferenceOemPrivateOnly()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 1;
+        final int expectedNumOfRequests = 1;
+
+        @OemNetworkPreferences.OemNetworkPreference final int prefToTest =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory()
+                        .createNrisFromOemNetworkPreferences(
+                                createDefaultOemNetworkPreferences(prefToTest));
+
+        final List<NetworkRequest> mRequests = nris.iterator().next().mRequests;
+        assertEquals(expectedNumOfNris, nris.size());
+        assertEquals(expectedNumOfRequests, mRequests.size());
+        assertTrue(mRequests.get(0).isRequest());
+        assertTrue(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PRIVATE));
+        assertFalse(mRequests.get(0).hasCapability(NET_CAPABILITY_OEM_PAID));
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryCreatesCorrectNumOfNris()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 2;
+
+        // Arrange PackageManager mocks
+        final String testPackageName2 = "com.google.apps.dialer";
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+        mockGetApplicationInfo(testPackageName2, TEST_PACKAGE_UID);
+
+        // Build OemNetworkPreferences object
+        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+        final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
+                .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
+                .addNetworkPreference(testPackageName2, testOemPref2)
+                .build();
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
+
+        assertNotNull(nris);
+        assertEquals(expectedNumOfNris, nris.size());
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryCorrectlySetsUids()
+            throws PackageManager.NameNotFoundException {
+        // Arrange PackageManager mocks
+        final String testPackageName2 = "com.google.apps.dialer";
+        final int testPackageNameUid2 = 456;
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+        mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
+
+        // Build OemNetworkPreferences object
+        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final int testOemPref2 = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK;
+        final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
+                .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
+                .addNetworkPreference(testPackageName2, testOemPref2)
+                .build();
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final List<ConnectivityService.NetworkRequestInfo> nris =
+                new ArrayList<>(
+                        mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(
+                                pref));
+
+        // Sort by uid to access nris by index
+        nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start));
+        assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start);
+        assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop);
+        assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start);
+        assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop);
+    }
+
+    @Test
+    public void testOemNetworkRequestFactoryAddsPackagesToCorrectPreference()
+            throws PackageManager.NameNotFoundException {
+        // Expectations
+        final int expectedNumOfNris = 1;
+        final int expectedNumOfAppUids = 2;
+
+        // Arrange PackageManager mocks
+        final String testPackageName2 = "com.google.apps.dialer";
+        final int testPackageNameUid2 = 456;
+        mockGetApplicationInfo(TEST_PACKAGE_NAME, TEST_PACKAGE_UID);
+        mockGetApplicationInfo(testPackageName2, testPackageNameUid2);
+
+        // Build OemNetworkPreferences object
+        final int testOemPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+        final OemNetworkPreferences pref = new OemNetworkPreferences.Builder()
+                .addNetworkPreference(TEST_PACKAGE_NAME, testOemPref)
+                .addNetworkPreference(testPackageName2, testOemPref)
+                .build();
+
+        // Act on OemNetworkRequestFactory.createNrisFromOemNetworkPreferences()
+        final ArraySet<ConnectivityService.NetworkRequestInfo> nris =
+                mService.new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(pref);
+
+        assertEquals(expectedNumOfNris, nris.size());
+        assertEquals(expectedNumOfAppUids,
+                nris.iterator().next().mRequests.get(0).networkCapabilities.getUids().size());
+    }
+
+    @Test
+    public void testSetOemNetworkPreferenceNullListenerAndPrefParamThrowsNpe() {
+        mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, true);
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
+        // Act on ConnectivityService.setOemNetworkPreference()
+        assertThrows(NullPointerException.class,
+                () -> mService.setOemNetworkPreference(
+                        null,
+                        null));
+    }
+
+    @Test
+    public void testSetOemNetworkPreferenceFailsForNonAutomotive()
+            throws PackageManager.NameNotFoundException, RemoteException {
+        mockHasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, false);
+        @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+                OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
+        // Act on ConnectivityService.setOemNetworkPreference()
+        assertThrows(UnsupportedOperationException.class,
+                () -> mService.setOemNetworkPreference(
+                        createDefaultOemNetworkPreferences(networkPref),
+                        mOnSetOemNetworkPreferenceListener));
+    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 3556c72..8f5ae97 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -89,8 +89,8 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PermissionMonitorTest {
-    private static final int MOCK_USER1 = 0;
-    private static final int MOCK_USER2 = 1;
+    private static final UserHandle MOCK_USER1 = UserHandle.of(0);
+    private static final UserHandle MOCK_USER2 = UserHandle.of(1);
     private static final int MOCK_UID1 = 10001;
     private static final int MOCK_UID2 = 10086;
     private static final int SYSTEM_UID1 = 1000;
@@ -123,10 +123,7 @@
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
         when(mUserManager.getUserHandles(eq(true))).thenReturn(
-                Arrays.asList(new UserHandle[] {
-                        new UserHandle(MOCK_USER1),
-                        new UserHandle(MOCK_USER2),
-                }));
+                Arrays.asList(new UserHandle[] { MOCK_USER1, MOCK_USER2 }));
 
         mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
 
@@ -184,7 +181,8 @@
         return packageInfo;
     }
 
-    private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) {
+    private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid,
+            UserHandle user) {
         final PackageInfo pkgInfo;
         if (hasSystemPermission) {
             pkgInfo = systemPackageInfoWithPermissions(
@@ -192,7 +190,7 @@
         } else {
             pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, "");
         }
-        pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
+        pkgInfo.applicationInfo.uid = UserHandle.getUid(user, UserHandle.getAppId(uid));
         return pkgInfo;
     }
 
@@ -382,8 +380,8 @@
             }).when(mockNetd).networkClearPermissionForUser(any(int[].class));
         }
 
-        public void expectPermission(Boolean permission, int[] users, int[] apps) {
-            for (final int user : users) {
+        public void expectPermission(Boolean permission, UserHandle[] users, int[] apps) {
+            for (final UserHandle user : users) {
                 for (final int app : apps) {
                     final int uid = UserHandle.getUid(user, app);
                     if (!mApps.containsKey(uid)) {
@@ -396,8 +394,8 @@
             }
         }
 
-        public void expectNoPermission(int[] users, int[] apps) {
-            for (final int user : users) {
+        public void expectNoPermission(UserHandle[] users, int[] apps) {
+            for (final UserHandle user : users) {
                 for (final int app : apps) {
                     final int uid = UserHandle.getUid(user, app);
                     if (mApps.containsKey(uid)) {
@@ -425,46 +423,48 @@
 
         // Add SYSTEM_PACKAGE2, expect only have network permission.
         mPermissionMonitor.onUserAdded(MOCK_USER1);
-        addPackageForUsers(new int[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID);
-        mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1}, new int[]{SYSTEM_UID});
+        addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE2, SYSTEM_UID);
+        mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID});
 
         // Add SYSTEM_PACKAGE1, expect permission escalate.
-        addPackageForUsers(new int[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID);
-        mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1}, new int[]{SYSTEM_UID});
+        addPackageForUsers(new UserHandle[]{MOCK_USER1}, SYSTEM_PACKAGE1, SYSTEM_UID);
+        mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1}, new int[]{SYSTEM_UID});
 
         mPermissionMonitor.onUserAdded(MOCK_USER2);
-        mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1, MOCK_USER2},
+        mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{SYSTEM_UID});
 
-        addPackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
-        mNetdMonitor.expectPermission(SYSTEM, new int[]{MOCK_USER1, MOCK_USER2},
+        addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
+        mNetdMonitor.expectPermission(SYSTEM, new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{SYSTEM_UID});
-        mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1, MOCK_USER2},
+        mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{MOCK_UID1});
 
         // Remove MOCK_UID1, expect no permission left for all user.
         mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
-        removePackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
-        mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2}, new int[]{MOCK_UID1});
+        removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_UID1);
+        mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
+                new int[]{MOCK_UID1});
 
         // Remove SYSTEM_PACKAGE1, expect permission downgrade.
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{SYSTEM_PACKAGE2});
-        removePackageForUsers(new int[]{MOCK_USER1, MOCK_USER2}, SYSTEM_PACKAGE1, SYSTEM_UID);
-        mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER1, MOCK_USER2},
+        removePackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2},
+                SYSTEM_PACKAGE1, SYSTEM_UID);
+        mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{SYSTEM_UID});
 
         mPermissionMonitor.onUserRemoved(MOCK_USER1);
-        mNetdMonitor.expectPermission(NETWORK, new int[]{MOCK_USER2}, new int[]{SYSTEM_UID});
+        mNetdMonitor.expectPermission(NETWORK, new UserHandle[]{MOCK_USER2}, new int[]{SYSTEM_UID});
 
         // Remove all packages, expect no permission left.
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(new String[]{});
-        removePackageForUsers(new int[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
-        mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2},
+        removePackageForUsers(new UserHandle[]{MOCK_USER2}, SYSTEM_PACKAGE2, SYSTEM_UID);
+        mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{SYSTEM_UID, MOCK_UID1});
 
         // Remove last user, expect no redundant clearPermission is invoked.
         mPermissionMonitor.onUserRemoved(MOCK_USER2);
-        mNetdMonitor.expectNoPermission(new int[]{MOCK_USER1, MOCK_USER2},
+        mNetdMonitor.expectNoPermission(new UserHandle[]{MOCK_USER1, MOCK_USER2},
                 new int[]{SYSTEM_UID, MOCK_UID1});
     }
 
@@ -548,14 +548,14 @@
     // Normal package add/remove operations will trigger multiple intent for uids corresponding to
     // each user. To simulate generic package operations, the onPackageAdded/Removed will need to be
     // called multiple times with the uid corresponding to each user.
-    private void addPackageForUsers(int[] users, String packageName, int uid) {
-        for (final int user : users) {
+    private void addPackageForUsers(UserHandle[] users, String packageName, int uid) {
+        for (final UserHandle user : users) {
             mPermissionMonitor.onPackageAdded(packageName, UserHandle.getUid(user, uid));
         }
     }
 
-    private void removePackageForUsers(int[] users, String packageName, int uid) {
-        for (final int user : users) {
+    private void removePackageForUsers(UserHandle[] users, String packageName, int uid) {
+        for (final UserHandle user : users) {
             mPermissionMonitor.onPackageRemoved(packageName, UserHandle.getUid(user, uid));
         }
     }