Merge "Add dependency on framework-connectivity" am: 80b7b65674

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Wifi/+/1608521

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ice15549db37aaffa597013e22274cca76e0146bd
diff --git a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
index 4f7b4e8..053314d 100644
--- a/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
+++ b/service/java/com/android/server/wifi/ConnectToNetworkNotificationBuilder.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wifi;
 
+import static android.app.Notification.VISIBILITY_SECRET;
+
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.content.Intent;
@@ -95,6 +97,7 @@
                 .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag))
                 .addAction(connectAction)
                 .addAction(allNetworksAction)
+                .setVisibility(VISIBILITY_SECRET)
                 .build();
     }
 
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index c0f7af7..f8c687e 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -913,32 +913,6 @@
     }
 
     /**
-     * Check if the given UID belongs to the current foreground user. This is
-     * used to prevent apps running in background users from modifying network
-     * configurations.
-     * <p>
-     * UIDs belonging to system internals (such as SystemUI) are always allowed,
-     * since they always run as {@link UserHandle#USER_SYSTEM}.
-     *
-     * @param uid uid of the app.
-     * @return true if the given UID belongs to the current foreground user,
-     *         otherwise false.
-     */
-    private boolean doesUidBelongToCurrentUser(int uid) {
-        if (uid == android.os.Process.SYSTEM_UID
-                // UIDs with the NETWORK_SETTINGS permission are always allowed since they are
-                // acting on behalf of the user.
-                || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
-            return true;
-        } else {
-            UserHandle currentUser = UserHandle.of(mCurrentUserId);
-            UserHandle callingUser = UserHandle.getUserHandleForUid(uid);
-            return currentUser.equals(callingUser)
-                    || mUserManager.isSameProfileGroup(currentUser, callingUser);
-        }
-    }
-
-    /**
      * Copy over public elements from an external WifiConfiguration object to the internal
      * configuration object if element has been set in the provided external WifiConfiguration.
      * The only exception is the hidden |IpConfiguration| parameters, these need to be copied over
@@ -1333,7 +1307,7 @@
      */
     public NetworkUpdateResult addOrUpdateNetwork(WifiConfiguration config, int uid,
                                                   @Nullable String packageName) {
-        if (!doesUidBelongToCurrentUser(uid)) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
             Log.e(TAG, "UID " + uid + " not visible to the current user");
             return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID);
         }
@@ -1439,7 +1413,7 @@
      * @return true if successful, false otherwise.
      */
     public boolean removeNetwork(int networkId, int uid, String packageName) {
-        if (!doesUidBelongToCurrentUser(uid)) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
             Log.e(TAG, "UID " + uid + " not visible to the current user");
             return false;
         }
@@ -1848,7 +1822,7 @@
         if (mVerboseLoggingEnabled) {
             Log.v(TAG, "Enabling network " + networkId + " (disableOthers " + disableOthers + ")");
         }
-        if (!doesUidBelongToCurrentUser(uid)) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
             Log.e(TAG, "UID " + uid + " not visible to the current user");
             return false;
         }
@@ -1886,7 +1860,7 @@
         if (mVerboseLoggingEnabled) {
             Log.v(TAG, "Disabling network " + networkId);
         }
-        if (!doesUidBelongToCurrentUser(uid)) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
             Log.e(TAG, "UID " + uid + " not visible to the current user");
             return false;
         }
@@ -1954,7 +1928,7 @@
         if (mVerboseLoggingEnabled) {
             Log.v(TAG, "Update network last connect UID for " + networkId);
         }
-        if (!doesUidBelongToCurrentUser(uid)) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
             Log.e(TAG, "UID " + uid + " not visible to the current user");
             return false;
         }
@@ -2926,7 +2900,8 @@
         Set<Integer> removedNetworkIds = new HashSet<>();
         // Remove any private networks of the old user before switching the userId.
         for (WifiConfiguration config : getConfiguredNetworks()) {
-            if ((!config.shared && doesUidBelongToCurrentUser(config.creatorUid))
+            if ((!config.shared && !mWifiPermissionsUtil
+                    .doesUidBelongToCurrentUser(config.creatorUid))
                     || config.ephemeral) {
                 removedNetworkIds.add(config.networkId);
                 localLog("clearInternalUserData: removed config."
@@ -3153,7 +3128,8 @@
 
             // Migrate the legacy Passpoint configurations owned by the current user to
             // {@link PasspointManager}.
-            if (config.isLegacyPasspointConfig && doesUidBelongToCurrentUser(config.creatorUid)) {
+            if (config.isLegacyPasspointConfig && !mWifiPermissionsUtil
+                    .doesUidBelongToCurrentUser(config.creatorUid)) {
                 legacyPasspointNetId.add(config.networkId);
                 // Migrate the legacy Passpoint configuration and add it to PasspointManager.
                 if (!PasspointManager.addLegacyPasspointConfig(config)) {
@@ -3173,7 +3149,8 @@
             // because all networks were previously stored in a central file. We cannot
             // write these private networks to the user specific store until the corresponding
             // user logs in.
-            if (config.shared || !doesUidBelongToCurrentUser(config.creatorUid)) {
+            if (config.shared || !mWifiPermissionsUtil
+                    .doesUidBelongToCurrentUser(config.creatorUid)) {
                 sharedConfigurations.add(config);
             } else {
                 userConfigurations.add(config);
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 993debb..48f1b3f 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -305,7 +305,7 @@
         mPasspointManager = new PasspointManager(mContext, this,
                 wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
                 mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager,
-                mMacAddressUtil);
+                mMacAddressUtil, mWifiPermissionsUtil);
         PasspointNetworkNominateHelper nominateHelper =
                 new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager,
                         mConnectivityLocalLog);
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index 464ced0..2632835 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -390,6 +390,7 @@
     private boolean mIsLastUserApprovalUiDialog = false;
 
     private boolean mUserDataLoaded = false;
+
     /**
      * Listener for app-ops changes for active suggestor apps.
      */
@@ -833,6 +834,10 @@
     public @WifiManager.NetworkSuggestionsStatusCode int add(
             List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName,
             @Nullable String featureId) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
+        }
         if (!mUserDataLoaded) {
             Log.e(TAG, "Add Network suggestion before boot complete is not allowed.");
             return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
@@ -1108,6 +1113,10 @@
      */
     public @WifiManager.NetworkSuggestionsStatusCode int remove(
             List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
+        }
         if (!mUserDataLoaded) {
             Log.e(TAG, "Remove Network suggestion before boot complete is not allowed.");
             return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL;
@@ -1166,8 +1175,12 @@
      * Get all network suggestion for target App
      * @return List of WifiNetworkSuggestions
      */
-    public @NonNull List<WifiNetworkSuggestion> get(@NonNull String packageName) {
+    public @NonNull List<WifiNetworkSuggestion> get(@NonNull String packageName, int uid) {
         List<WifiNetworkSuggestion> networkSuggestionList = new ArrayList<>();
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return networkSuggestionList;
+        }
         if (!mUserDataLoaded) {
             Log.e(TAG, "Get Network suggestion before boot complete is not allowed.");
             return networkSuggestionList;
@@ -1923,11 +1936,16 @@
      * @param binder IBinder instance to allow cleanup if the app dies.
      * @param listener ISuggestionNetworkCallback instance to add.
      * @param listenerIdentifier identifier of the listener, should be hash code of listener.
+     * @param uid uid of the app.
      * @return true if succeed otherwise false.
      */
     public boolean registerSuggestionConnectionStatusListener(@NonNull IBinder binder,
             @NonNull ISuggestionConnectionStatusListener listener,
-            int listenerIdentifier, String packageName) {
+            int listenerIdentifier, String packageName, int uid) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return false;
+        }
         ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker =
                 mSuggestionStatusListenerPerApp.get(packageName);
         if (listenersTracker == null) {
@@ -1942,9 +1960,14 @@
     /**
      * Unregister a listener on network connection failure.
      * @param listenerIdentifier identifier of the listener, should be hash code of listener.
+     * @param uid uid of the app.
      */
     public void unregisterSuggestionConnectionStatusListener(int listenerIdentifier,
-            String packageName) {
+            String packageName, int uid) {
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return;
+        }
         ExternalCallbackTracker<ISuggestionConnectionStatusListener> listenersTracker =
                 mSuggestionStatusListenerPerApp.get(packageName);
         if (listenersTracker == null || listenersTracker.remove(listenerIdentifier) == null) {
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 5019f54..3b4f397 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -3893,13 +3893,15 @@
      * @return a list of network suggestions suggested by this app
      */
     public List<WifiNetworkSuggestion> getNetworkSuggestions(String callingPackageName) {
-        mAppOps.checkPackage(Binder.getCallingUid(), callingPackageName);
+        int callingUid = Binder.getCallingUid();
+        mAppOps.checkPackage(callingUid, callingPackageName);
         enforceAccessPermission();
         if (mVerboseLoggingEnabled) {
             mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush();
         }
         return mWifiThreadRunner.call(() ->
-                mWifiNetworkSuggestionsManager.get(callingPackageName), Collections.emptyList());
+                mWifiNetworkSuggestionsManager.get(callingPackageName, callingUid),
+                Collections.emptyList());
     }
 
     /**
@@ -4227,7 +4229,7 @@
         mWifiThreadRunner.post(() ->
                 mWifiNetworkSuggestionsManager
                         .registerSuggestionConnectionStatusListener(binder, listener,
-                                listenerIdentifier, packageName));
+                                listenerIdentifier, packageName, uid));
     }
 
     /**
@@ -4237,14 +4239,15 @@
     public void unregisterSuggestionConnectionStatusListener(
             int listenerIdentifier, String packageName) {
         enforceAccessPermission();
+        int uid = Binder.getCallingUid();
         if (mVerboseLoggingEnabled) {
             mLog.info("unregisterSuggestionConnectionStatusListener uid=%")
-                    .c(Binder.getCallingUid()).flush();
+                    .c(uid).flush();
         }
         mWifiThreadRunner.post(() ->
                 mWifiNetworkSuggestionsManager
                         .unregisterSuggestionConnectionStatusListener(listenerIdentifier,
-                                packageName));
+                                packageName, uid));
     }
 
     @Override
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 9cb4254..d398759 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -57,6 +57,7 @@
 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
 import com.android.server.wifi.util.InformationElementUtil;
+import com.android.server.wifi.util.WifiPermissionsUtil;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -122,6 +123,7 @@
     private final AppOpsManager mAppOps;
     private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private final MacAddressUtil mMacAddressUtil;
+    private final WifiPermissionsUtil mWifiPermissionsUtil;
 
     /**
      * Map of package name of an app to the app ops changed listener for the app.
@@ -309,7 +311,8 @@
             WifiConfigStore wifiConfigStore,
             WifiMetrics wifiMetrics,
             WifiCarrierInfoManager wifiCarrierInfoManager,
-            MacAddressUtil macAddressUtil) {
+            MacAddressUtil macAddressUtil,
+            WifiPermissionsUtil wifiPermissionsUtil) {
         mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative,
                 new CallbackHandler(context));
         mWifiInjector = wifiInjector;
@@ -332,6 +335,7 @@
         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         sPasspointManager = this;
         mMacAddressUtil = macAddressUtil;
+        mWifiPermissionsUtil = wifiPermissionsUtil;
     }
 
     /**
@@ -412,6 +416,10 @@
             Log.e(TAG, "Set isTrusted to false on a non suggestion passpoint is not allowed");
             return false;
         }
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(uid)) {
+            Log.e(TAG, "UID " + uid + " not visible to the current user");
+            return false;
+        }
 
         mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config);
         // Create a provider and install the necessary certificates and keys.
@@ -505,6 +513,10 @@
                     + provider.getCreatorUid());
             return false;
         }
+        if (!mWifiPermissionsUtil.doesUidBelongToCurrentUser(callingUid)) {
+            Log.e(TAG, "UID " + callingUid + " not visible to the current user");
+            return false;
+        }
         provider.uninstallCertsAndKeys();
         String packageName = provider.getPackageName();
         // Remove any configs corresponding to the profile in WifiConfigManager.
diff --git a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
index 63197ea..ebe7ea4 100644
--- a/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
+++ b/service/java/com/android/server/wifi/util/WifiPermissionsUtil.java
@@ -30,6 +30,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.util.EventLog;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -589,4 +590,32 @@
         if (devicePolicyManager == null) return false;
         return devicePolicyManager.isProfileOwnerApp(packageName);
     }
+
+    /**
+     * Check if the given UID belongs to the current foreground user. This is
+     * used to prevent apps running in background users from modifying network
+     * configurations.
+     * <p>
+     * UIDs belonging to system internals (such as SystemUI) are always allowed,
+     * since they always run as {@link UserHandle#USER_SYSTEM}.
+     *
+     * @param uid uid of the app.
+     * @return true if the given UID belongs to the current foreground user,
+     *         otherwise false.
+     */
+    public boolean doesUidBelongToCurrentUser(int uid) {
+        if (uid == android.os.Process.SYSTEM_UID
+                // UIDs with the NETWORK_SETTINGS permission are always allowed since they are
+                // acting on behalf of the user.
+                || checkNetworkSettingsPermission(uid)) {
+            return true;
+        }
+        boolean isCurrentProfile = isCurrentProfile(uid);
+        if (!isCurrentProfile) {
+            // Fix for b/174749461
+            EventLog.writeEvent(0x534e4554, "174749461", -1,
+                    "Non foreground user trying to modify wifi configuration");
+        }
+        return isCurrentProfile;
+    }
 }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index e4a918c..9219076 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -222,6 +222,7 @@
                 .thenReturn(false);
         when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil);
         when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true);
         when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(TEST_RANDOMIZED_MAC);
         when(mWifiScoreCard.lookupNetwork(any())).thenReturn(mPerNetwork);
 
@@ -2913,6 +2914,8 @@
         setupStoreDataForUserRead(user2Networks, new HashMap<>());
         // Now switch the user to user 2 and ensure that user 1's private network has been removed.
         when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid))
+                .thenReturn(false);
         Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
         verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
         assertTrue((removedNetworks.size() == 1) && (removedNetworks.contains(user1NetworkId)));
@@ -3053,7 +3056,7 @@
     public void testHandleUserSwitchPushesOtherPrivateNetworksToSharedStore() throws Exception {
         int user1 = TEST_DEFAULT_USER;
         int user2 = TEST_DEFAULT_USER + 1;
-        setupUserProfiles(user2);
+        setupUserProfiles(user1);
 
         int appId = 674;
 
@@ -3091,6 +3094,8 @@
             }
         };
         setupStoreDataForUserRead(userNetworks, new HashMap<>());
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user2Network.creatorUid))
+                .thenReturn(false);
         mWifiConfigManager.handleUserUnlock(user1);
         verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
         // Capture the written data for the user 1 and ensure that it corresponds to what was
@@ -3105,6 +3110,10 @@
         // Now switch the user to user2 and ensure that user 2's private network has been moved to
         // the user store.
         when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid))
+                .thenReturn(true).thenReturn(false);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user2Network.creatorUid))
+                .thenReturn(false).thenReturn(true);
         mWifiConfigManager.handleUserSwitch(user2);
         // Set the expected network list before comparing. user1Network should be in shared data.
         // Note: In the real world, user1Network will no longer be visible now because it should
@@ -3169,6 +3178,8 @@
         // Unlock the owner of the legacy Passpoint configuration, verify it is removed from
         // the configured networks (migrated to PasspointManager).
         setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashMap<>());
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(passpointConfig.creatorUid))
+                .thenReturn(false);
         mWifiConfigManager.handleUserUnlock(user1);
         verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
         Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList =
@@ -3296,7 +3307,8 @@
 
         // Ensure that we have 2 networks in the database before the stop.
         assertEquals(2, mWifiConfigManager.getConfiguredNetworks().size());
-
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(user1Network.creatorUid))
+                .thenReturn(false);
         mWifiConfigManager.handleUserStop(user1);
 
         // Ensure that we only have 1 shared network in the database after the stop.
@@ -3498,6 +3510,7 @@
         int creatorUid = UserHandle.getUid(user2, 674);
 
         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(creatorUid)).thenReturn(false);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(creatorUid)).thenReturn(false);
 
         // Create a network for user2 try adding it. This should be rejected.
         final WifiConfiguration user2Network = WifiConfigurationTestUtil.createPskNetwork();
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index 45823c9..eb81d3a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -65,6 +65,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.test.TestLooper;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -150,6 +151,7 @@
     private @Mock Notification.Builder mNotificationBuilder;
     private @Mock Notification mNotification;
     private @Mock LruConnectionTracker mLruConnectionTracker;
+    private @Mock UserManager mUserManager;
     private TestLooper mLooper;
     private ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor =
             ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class);
@@ -216,6 +218,7 @@
         when(mActivityManager.isLowRamDevice()).thenReturn(false);
         when(mActivityManager.getPackageImportance(any())).thenReturn(
                 IMPORTANCE_FOREGROUND_SERVICE);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true);
 
         // setup resource strings for notification.
         when(mResources.getString(eq(R.string.wifi_suggestion_title), anyString()))
@@ -560,7 +563,7 @@
                         TEST_PACKAGE_1, TEST_FEATURE));
         assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED,
                 mWifiNetworkSuggestionsManager
-                        .get(TEST_PACKAGE_1).get(0).wifiConfiguration.meteredOverride);
+                        .get(TEST_PACKAGE_1, TEST_UID_1).get(0).wifiConfiguration.meteredOverride);
         // Verify we did not update config in WCM.
         verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any());
     }
@@ -607,7 +610,7 @@
                         TEST_PACKAGE_1, TEST_FEATURE));
         assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED,
                 mWifiNetworkSuggestionsManager
-                        .get(TEST_PACKAGE_1).get(0).wifiConfiguration.meteredOverride);
+                        .get(TEST_PACKAGE_1, TEST_UID_1).get(0).wifiConfiguration.meteredOverride);
         verify(mWifiMetrics, never()).incrementNetworkSuggestionApiUsageNumOfAppInType(anyInt());
         // Verify we did update config in WCM.
         ArgumentCaptor<WifiConfiguration> configCaptor =
@@ -1066,7 +1069,7 @@
     public void testOnNetworkConnectionSuccessWithOneMatch() throws Exception {
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
-                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
+                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
                 WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true);
         List<WifiNetworkSuggestion> networkSuggestionList =
@@ -1103,7 +1106,7 @@
     public void testOnNetworkConnectionSuccessWithOneMatchFromCarrierPrivilegedApp() {
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
-                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
+                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
         when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TEST_CARRIER_ID);
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
@@ -1138,6 +1141,7 @@
                 mWifiNetworkSuggestionsManager.remove(networkSuggestionList, TEST_UID_1,
                         TEST_PACKAGE_1));
         verify(mWifiConfigManager).removeSuggestionConfiguredNetwork(anyString());
+        mInorder.verify(mWifiPermissionsUtil).doesUidBelongToCurrentUser(eq(TEST_UID_1));
 
         // Verify no more broadcast were sent out.
         mInorder.verifyNoMoreInteractions();
@@ -1152,7 +1156,7 @@
     public void testOnSavedOpenNetworkConnectionSuccessWithMultipleMatch() throws Exception {
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
-                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
+                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(true);
         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
@@ -1199,7 +1203,7 @@
                 ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
-                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
+                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
         verify(mBinder).linkToDeath(drCaptor.capture(), anyInt());
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
                 WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true);
@@ -1249,7 +1253,7 @@
     public void testOnNetworkConnectionFailureWithOneMatch() throws Exception {
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
-                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
+                        NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
                 WifiConfigurationTestUtil.createOpenNetwork(), null, true, false, true, true);
         List<WifiNetworkSuggestion> networkSuggestionList =
@@ -2467,7 +2471,7 @@
     public void testGetNetworkSuggestions() {
         // test App never suggested.
         List<WifiNetworkSuggestion> storedNetworkSuggestionListPerApp =
-                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1);
+                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1);
         assertEquals(storedNetworkSuggestionListPerApp.size(), 0);
 
         // App add network suggestions then get stored suggestions.
@@ -2489,7 +2493,7 @@
                         TEST_PACKAGE_1, TEST_FEATURE));
         mWifiNetworkSuggestionsManager.setHasUserApprovedForApp(true, TEST_PACKAGE_1);
         storedNetworkSuggestionListPerApp =
-                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1);
+                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1);
         assertEquals(new HashSet<>(networkSuggestionList),
                 new HashSet<>(storedNetworkSuggestionListPerApp));
 
@@ -2498,7 +2502,7 @@
                 mWifiNetworkSuggestionsManager.remove(new ArrayList<>(), TEST_UID_1,
                         TEST_PACKAGE_1));
         storedNetworkSuggestionListPerApp =
-                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1);
+                mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1);
         assertEquals(storedNetworkSuggestionListPerApp.size(), 0);
     }
 
@@ -3222,7 +3226,7 @@
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
         assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED, status);
         verify(mNotificationManger, never()).notify(anyInt(), any());
-        assertEquals(0, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1).size());
+        assertEquals(0, mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size());
         verify(mWifiMetrics, never()).incrementNetworkSuggestionApiUsageNumOfAppInType(anyInt());
     }
 
@@ -3246,7 +3250,7 @@
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
         assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status);
         verify(mNotificationManger, never()).notify(anyInt(), any());
-        assertEquals(1,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1).size());
+        assertEquals(1,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size());
         verify(mWifiMetrics).incrementNetworkSuggestionApiUsageNumOfAppInType(
                 WifiNetworkSuggestionsManager.APP_TYPE_CARRIER_PRIVILEGED);
     }
@@ -3271,7 +3275,7 @@
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
         assertEquals(status, WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
         verify(mNotificationManger, never()).notify(anyInt(), any());
-        assertEquals(1,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1).size());
+        assertEquals(1,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size());
     }
 
     /**
@@ -3333,7 +3337,7 @@
         when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID);
         mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps();
-        assertEquals(0,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1).size());
+        assertEquals(0,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).size());
         verify(mWifiConfigManager, times(2)).saveToStore(true);
         status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
@@ -4033,7 +4037,7 @@
     public void testUnregisterSuggestionConnectionStatusListenerNeverRegistered() {
         int listenerIdentifier = 1234;
         mWifiNetworkSuggestionsManager.unregisterSuggestionConnectionStatusListener(
-                listenerIdentifier, TEST_PACKAGE_1);
+                listenerIdentifier, TEST_PACKAGE_1, TEST_UID_1);
     }
 
     /**
@@ -4084,6 +4088,43 @@
     }
 
     /**
+     * Verify when calling API from background user will fail.
+     */
+    @Test
+    public void testCallingFromBackgroundUserWillFailed() {
+        WifiConfiguration wifiConfiguration = WifiConfigurationTestUtil.createOpenNetwork();
+        WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
+                wifiConfiguration, null, false, false, true, true);
+
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1,
+                        TEST_PACKAGE_1, TEST_FEATURE));
+        // When switch the user to background
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(TEST_UID_1)).thenReturn(false);
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
+                mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1,
+                        TEST_PACKAGE_1, TEST_FEATURE));
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
+                mWifiNetworkSuggestionsManager.remove(Arrays.asList(networkSuggestion), TEST_UID_1,
+                        TEST_PACKAGE_1));
+        assertTrue(mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).isEmpty());
+        assertFalse(mWifiNetworkSuggestionsManager.registerSuggestionConnectionStatusListener(
+                mBinder, mListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
+
+        // When switch the user back to foreground
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(TEST_UID_1)).thenReturn(true);
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.add(Arrays.asList(networkSuggestion), TEST_UID_1,
+                        TEST_PACKAGE_1, TEST_FEATURE));
+        assertFalse(mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1, TEST_UID_1).isEmpty());
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.remove(Arrays.asList(networkSuggestion), TEST_UID_1,
+                        TEST_PACKAGE_1));
+        assertTrue(mWifiNetworkSuggestionsManager.registerSuggestionConnectionStatusListener(
+                mBinder, mListener, NETWORK_CALLBACK_ID, TEST_PACKAGE_1, TEST_UID_1));
+    }
+
+    /**
      * Helper function for creating a test configuration with user credential.
      *
      * @return {@link PasspointConfiguration}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 22561a1..c1ddd63 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -4592,12 +4592,12 @@
     @Test
     public void testGetNetworkSuggestions() {
         List<WifiNetworkSuggestion> testList = new ArrayList<>();
-        when(mWifiNetworkSuggestionsManager.get(anyString())).thenReturn(testList);
+        when(mWifiNetworkSuggestionsManager.get(anyString(), anyInt())).thenReturn(testList);
         mLooper.startAutoDispatch();
         assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME));
         mLooper.stopAutoDispatchAndIgnoreExceptions();
 
-        verify(mWifiNetworkSuggestionsManager).get(eq(TEST_PACKAGE_NAME));
+        verify(mWifiNetworkSuggestionsManager).get(eq(TEST_PACKAGE_NAME), anyInt());
     }
 
     /**
@@ -4612,7 +4612,7 @@
         assertTrue(mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).isEmpty());
         mLooper.stopAutoDispatchAndIgnoreExceptions();
 
-        verify(mWifiNetworkSuggestionsManager, never()).get(eq(TEST_PACKAGE_NAME));
+        verify(mWifiNetworkSuggestionsManager, never()).get(eq(TEST_PACKAGE_NAME), anyInt());
     }
 
     /**
@@ -5394,12 +5394,12 @@
         mLooper.dispatchAll();
         verify(mWifiNetworkSuggestionsManager).registerSuggestionConnectionStatusListener(
                 eq(mAppBinder), eq(mSuggestionConnectionStatusListener), eq(NETWORK_CALLBACK_ID),
-                eq(TEST_PACKAGE_NAME));
+                eq(TEST_PACKAGE_NAME), anyInt());
         mWifiServiceImpl.unregisterSuggestionConnectionStatusListener(NETWORK_CALLBACK_ID,
                 TEST_PACKAGE_NAME);
         mLooper.dispatchAll();
         verify(mWifiNetworkSuggestionsManager).unregisterSuggestionConnectionStatusListener(
-                eq(NETWORK_CALLBACK_ID), eq(TEST_PACKAGE_NAME));
+                eq(NETWORK_CALLBACK_ID), eq(TEST_PACKAGE_NAME), anyInt());
     }
 
 
diff --git a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index 9caf85f..cb45972 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -102,6 +102,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.UserActionEvent;
 import com.android.server.wifi.util.InformationElementUtil;
 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
+import com.android.server.wifi.util.WifiPermissionsUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -192,6 +193,7 @@
     @Mock SubscriptionManager mSubscriptionManager;
     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     @Mock MacAddressUtil mMacAddressUtil;
+    @Mock WifiPermissionsUtil mWifiPermissionsUtil;
 
     Handler mHandler;
     TestLooper mLooper;
@@ -220,6 +222,7 @@
         when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl);
         when(mWifiInjector.getWifiNetworkSuggestionsManager())
                 .thenReturn(mWifiNetworkSuggestionsManager);
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(true);
         mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager,
                 mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
                 mock(WifiContext.class), mWifiConfigStore, mock(Handler.class), mWifiMetrics);
@@ -227,7 +230,8 @@
         mHandler = new Handler(mLooper.getLooper());
         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil,
+                mWifiPermissionsUtil);
         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
         verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class),
@@ -524,6 +528,29 @@
     }
 
     /**
+     * Verify that adding a provider from a background user will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void addProviderWithBackgroundUser() throws Exception {
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false);
+
+        PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
+                TEST_FRIENDLY_NAME);
+        PasspointProvider provider = createMockProvider(config);
+        when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
+        when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(false))).thenReturn(provider);
+        assertFalse(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID,
+                TEST_PACKAGE, false, true));
+
+        verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
+        verify(mWifiMetrics, never()).incrementNumPasspointProviderInstallSuccess();
+    }
+
+    /**
      * Verify that adding a user saved provider with a valid configuration and user credential will
      * succeed.
      *
@@ -753,7 +780,8 @@
                 .thenReturn(true);
         PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, spyFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil,
+                mWifiPermissionsUtil);
 
         assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -1932,6 +1960,29 @@
     }
 
     /**
+     * Verify that removing a provider from a background user will fail.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void removeProviderWithBackgroundUser() throws Exception {
+        PasspointConfiguration config = createTestConfigWithUserCredential(TEST_FQDN,
+                TEST_FRIENDLY_NAME);
+        PasspointProvider provider = createMockProvider(config);
+        when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(false))).thenReturn(provider);
+        assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
+                false, true));
+        verifyInstalledConfig(config);
+        verify(mWifiMetrics).incrementNumPasspointProviderInstallation();
+        verify(mWifiMetrics).incrementNumPasspointProviderInstallSuccess();
+
+        when(mWifiPermissionsUtil.doesUidBelongToCurrentUser(anyInt())).thenReturn(false);
+        assertFalse(mManager.removeProvider(TEST_CREATOR_UID, false, null, TEST_FQDN));
+    }
+
+    /**
      * Verify that adding a suggestion provider with a valid configuration and user credential will
      * succeed.
      *