Merge "Current network bonus score adjustment" into rvc-dev
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
index 5f8d44d..a6c3226 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -22,14 +22,17 @@
 
 import static com.android.wifitrackerlib.Utils.getAppLabel;
 import static com.android.wifitrackerlib.Utils.getAppLabelForSavedNetwork;
+import static com.android.wifitrackerlib.Utils.getAppLabelForWifiConfiguration;
 import static com.android.wifitrackerlib.Utils.getAutoConnectDescription;
 import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel;
+import static com.android.wifitrackerlib.Utils.getCarrierNameForSubId;
 import static com.android.wifitrackerlib.Utils.getCurrentNetworkCapabilitiesInformation;
 import static com.android.wifitrackerlib.Utils.getDisconnectedStateDescription;
 import static com.android.wifitrackerlib.Utils.getMeteredDescription;
 import static com.android.wifitrackerlib.Utils.getNetworkDetailedState;
 import static com.android.wifitrackerlib.Utils.getSecurityTypeFromWifiConfiguration;
 import static com.android.wifitrackerlib.Utils.getSpeedDescription;
+import static com.android.wifitrackerlib.Utils.getSubIdForConfig;
 import static com.android.wifitrackerlib.Utils.getVerboseLoggingDescription;
 
 import android.content.Context;
@@ -194,8 +197,17 @@
             if (TextUtils.isEmpty(disconnectDescription)) {
                 if (concise) {
                     sj.add(mContext.getString(R.string.wifi_disconnected));
-                } else if (!mForSavedNetworksPage && isSaved()) {
-                    sj.add(mContext.getString(R.string.wifi_remembered));
+                } else if (!mForSavedNetworksPage) {
+                    // Summary for unconnected suggested network
+                    if (mWifiConfig != null && mWifiConfig.fromWifiNetworkSuggestion) {
+                        String carrierName = getCarrierNameForSubId(mContext,
+                                getSubIdForConfig(mContext, mWifiConfig));
+                        sj.add(mContext.getString(R.string.available_via_app, carrierName != null
+                                ? carrierName
+                                : getAppLabelForWifiConfiguration(mContext, mWifiConfig)));
+                    } else if (isSaved()) {
+                        sj.add(mContext.getString(R.string.wifi_remembered));
+                    }
                 }
             } else {
                 sj.add(disconnectDescription);
@@ -242,8 +254,12 @@
             final String suggestionOrSpecifierPackageName = mWifiInfo != null
                     ? mWifiInfo.getRequestingPackageName() : null;
             if (!TextUtils.isEmpty(suggestionOrSpecifierPackageName)) {
-                return mContext.getString(R.string.connected_via_app,
-                        getAppLabel(mContext, suggestionOrSpecifierPackageName));
+                String carrierName = mWifiConfig != null
+                        ? getCarrierNameForSubId(mContext, getSubIdForConfig(mContext, mWifiConfig))
+                        : null;
+                return mContext.getString(R.string.connected_via_app, carrierName != null
+                        ? carrierName
+                        : getAppLabel(mContext, suggestionOrSpecifierPackageName));
             }
 
             String networkCapabilitiesinformation =
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index 47fc9ed..382fe02 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
@@ -307,8 +307,12 @@
 
     static CharSequence getAppLabelForSavedNetwork(@NonNull Context context,
             @NonNull WifiEntry wifiEntry) {
-        final WifiConfiguration config = wifiEntry.getWifiConfiguration();
-        if (context == null || wifiEntry == null || config == null) {
+        return getAppLabelForWifiConfiguration(context, wifiEntry.getWifiConfiguration());
+    }
+
+    static CharSequence getAppLabelForWifiConfiguration(@NonNull Context context,
+            @NonNull WifiConfiguration config) {
+        if (context == null || config == null) {
             return "";
         }
 
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 96a2bf9..4ca7716 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -115,6 +115,8 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 import com.android.server.wifi.MboOceController.BtmFrameData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData;
 import com.android.server.wifi.hotspot2.AnqpEvent;
 import com.android.server.wifi.hotspot2.IconEvent;
 import com.android.server.wifi.hotspot2.NetworkDetail;
@@ -130,9 +132,6 @@
 import com.android.server.wifi.util.NativeUtil;
 import com.android.server.wifi.util.RssiUtil;
 import com.android.server.wifi.util.ScanResultUtil;
-import com.android.server.wifi.util.TelephonyUtil;
-import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData;
-import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 import com.android.wifi.resources.R;
@@ -722,7 +721,7 @@
 
     private final BatteryStatsManager mBatteryStatsManager;
 
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
 
     // Used for debug and stats gathering
@@ -751,7 +750,8 @@
                             BatteryStatsManager batteryStatsManager,
                             SupplicantStateTracker supplicantStateTracker,
                             MboOceController mboOceController,
-                            TelephonyUtil telephonyUtil, EapFailureNotifier eapFailureNotifier,
+                            WifiCarrierInfoManager wifiCarrierInfoManager,
+                            EapFailureNotifier eapFailureNotifier,
                             SimRequiredNotifier simRequiredNotifier) {
         super(TAG, looper);
         mWifiInjector = wifiInjector;
@@ -771,7 +771,7 @@
         mWifiTrafficPoller = wifiTrafficPoller;
         mLinkProbeManager = linkProbeManager;
         mMboOceController = mboOceController;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mNetworkAgentState = DetailedState.DISCONNECTED;
 
         mBatteryStatsManager = batteryStatsManager;
@@ -3930,7 +3930,7 @@
                             && mTargetWifiConfiguration.enterpriseConfig
                                     .isAuthenticationSimBased()) {
                         // Pair<identity, encrypted identity>
-                        Pair<String, String> identityPair = mTelephonyUtil
+                        Pair<String, String> identityPair = mWifiCarrierInfoManager
                                 .getSimIdentity(mTargetWifiConfiguration);
                         Log.i(TAG, "SUP_REQUEST_IDENTITY: identityPair=["
                                 + ((identityPair.first.length() >= 7)
@@ -4164,15 +4164,15 @@
                         // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA'
                         if (config.enterpriseConfig != null
                                 && config.enterpriseConfig.isAuthenticationSimBased()) {
-                            mLastSubId = mTelephonyUtil.getBestMatchSubscriptionId(config);
+                            mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config);
                             mLastSimBasedConnectionCarrierName =
-                                mTelephonyUtil.getCarrierNameforSubId(mLastSubId);
+                                mWifiCarrierInfoManager.getCarrierNameforSubId(mLastSubId);
                             String anonymousIdentity =
                                     mWifiNative.getEapAnonymousIdentity(mInterfaceName);
                             if (!TextUtils.isEmpty(anonymousIdentity)
-                                    && !TelephonyUtil
+                                    && !WifiCarrierInfoManager
                                     .isAnonymousAtRealmIdentity(anonymousIdentity)) {
-                                String decoratedPseudonym = mTelephonyUtil
+                                String decoratedPseudonym = mWifiCarrierInfoManager
                                         .decoratePseudonymWith3GppRealm(config,
                                                 anonymousIdentity);
                                 if (decoratedPseudonym != null) {
@@ -4488,7 +4488,7 @@
                 case WifiEnterpriseConfig.Eap.AKA:
                 case WifiEnterpriseConfig.Eap.AKA_PRIME:
                     if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) {
-                        mTelephonyUtil.resetCarrierKeysForImsiEncryption(targetedNetwork);
+                        mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork);
                     }
                     break;
 
@@ -4933,7 +4933,7 @@
                                 && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)
                                 || (config.enterpriseConfig != null
                                         && config.enterpriseConfig.isAuthenticationSimBased()
-                                        && !mTelephonyUtil.isSimPresent(mLastSubId))) {
+                                        && !mWifiCarrierInfoManager.isSimPresent(mLastSubId))) {
                             mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
                                     StaEvent.DISCONNECT_RESET_SIM_NETWORKS);
                             // remove local PMKSA cache in framework
@@ -5741,15 +5741,15 @@
          * 3. 3GPP TS 11.11  2G_authentication [RAND]
          *                            [SRES][Cipher Key Kc]
          */
-        String response = mTelephonyUtil
+        String response = mWifiCarrierInfoManager
                 .getGsmSimAuthResponse(requestData.data, mTargetWifiConfiguration);
         if (response == null) {
             // In case of failure, issue may be due to sim type, retry as No.2 case
-            response = mTelephonyUtil
+            response = mWifiCarrierInfoManager
                     .getGsmSimpleSimAuthResponse(requestData.data, mTargetWifiConfiguration);
             if (response == null) {
                 // In case of failure, issue may be due to sim type, retry as No.3 case
-                response = mTelephonyUtil.getGsmSimpleSimNoLengthAuthResponse(
+                response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
                                 requestData.data, mTargetWifiConfiguration);
             }
         }
@@ -5772,7 +5772,7 @@
             return;
         }
 
-        SimAuthResponseData response = mTelephonyUtil
+        SimAuthResponseData response = mWifiCarrierInfoManager
                 .get3GAuthResponse(requestData, mTargetWifiConfiguration);
         if (response != null) {
             mWifiNative.simAuthResponse(
@@ -6338,10 +6338,10 @@
 
         if (config.enterpriseConfig != null
                 && config.enterpriseConfig.isAuthenticationSimBased()
-                && mTelephonyUtil.isImsiEncryptionInfoAvailable(
-                mTelephonyUtil.getBestMatchSubscriptionId(config))
+                && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(
+                mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))
                 && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) {
-            String anonAtRealm = mTelephonyUtil
+            String anonAtRealm = mWifiCarrierInfoManager
                     .getAnonymousIdentityWith3GppRealm(config);
             // Use anonymous@<realm> when pseudonym is not available
             config.enterpriseConfig.setAnonymousIdentity(anonAtRealm);
diff --git a/service/java/com/android/server/wifi/EapFailureNotifier.java b/service/java/com/android/server/wifi/EapFailureNotifier.java
index 3cc80b9..fe4cfbd 100644
--- a/service/java/com/android/server/wifi/EapFailureNotifier.java
+++ b/service/java/com/android/server/wifi/EapFailureNotifier.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.server.wifi.util.TelephonyUtil;
 
 /**
  * This class may be used to launch notifications when EAP failure occurs.
@@ -45,17 +44,17 @@
     private final WifiContext mContext;
     private final NotificationManager mNotificationManager;
     private final FrameworkFacade mFrameworkFacade;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     // Unique ID associated with the notification.
     public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_EAP_FAILURE;
     private String mCurrentShownSsid;
 
     public EapFailureNotifier(WifiContext context, FrameworkFacade frameworkFacade,
-            TelephonyUtil telephonyUtil) {
+            WifiCarrierInfoManager wifiCarrierInfoManager) {
         mContext = context;
         mFrameworkFacade = frameworkFacade;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mNotificationManager =
                 mContext.getSystemService(NotificationManager.class);
     }
@@ -74,7 +73,7 @@
             }
         }
         Resources res = getResourcesForSubId(mContext,
-                mTelephonyUtil.getBestMatchSubscriptionId(config));
+                mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
         if (res == null) return;
         int resourceId = res.getIdentifier(ERROR_MESSAGE_OVERLAY_PREFIX + errorCode,
                 "string", mContext.getWifiOverlayApkPkgName());
diff --git a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java b/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
index acfba80..98664d0 100644
--- a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
+++ b/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
@@ -172,8 +172,7 @@
 
     @Override
     public int getStoreFileId() {
-        // Suggestion Store.
-        return WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS;
+        // User general store.
+        return WifiConfigStore.STORE_FILE_USER_GENERAL;
     }
-
 }
diff --git a/service/java/com/android/server/wifi/NetworkListStoreData.java b/service/java/com/android/server/wifi/NetworkListStoreData.java
index 33c511b..95c3ba3 100644
--- a/service/java/com/android/server/wifi/NetworkListStoreData.java
+++ b/service/java/com/android/server/wifi/NetworkListStoreData.java
@@ -288,6 +288,14 @@
         if (configuration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) {
             fixSaeNetworkSecurityBits(configuration);
         }
+        // b/153435438: Added to deal with badly formed WifiConfiguration from apps.
+        if (configuration.preSharedKey != null && !configuration.needsPreSharedKey()) {
+            Log.e(TAG, "preSharedKey set with an invalid KeyMgmt, resetting KeyMgmt to WPA_PSK");
+            configuration.allowedKeyManagement.clear();
+            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+            // Recreate configKey to pass the check below.
+            configKeyParsed = configuration.getKey();
+        }
 
         String configKeyCalculated = configuration.getKey();
         if (!configKeyParsed.equals(configKeyCalculated)) {
diff --git a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
index c4fd6a9..fbc1f5f 100644
--- a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
+++ b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
@@ -24,7 +24,6 @@
 
 import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion;
 import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -54,16 +53,16 @@
     private final WifiConfigManager mWifiConfigManager;
     private final PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
     private final LocalLog mLocalLog;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     NetworkSuggestionNominator(WifiNetworkSuggestionsManager networkSuggestionsManager,
             WifiConfigManager wifiConfigManager, PasspointNetworkNominateHelper nominateHelper,
-            LocalLog localLog, TelephonyUtil telephonyUtil) {
+            LocalLog localLog, WifiCarrierInfoManager wifiCarrierInfoManager) {
         mWifiNetworkSuggestionsManager = networkSuggestionsManager;
         mWifiConfigManager = wifiConfigManager;
         mPasspointNetworkNominateHelper = nominateHelper;
         mLocalLog = localLog;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
     }
 
     @Override
@@ -111,7 +110,7 @@
             }
 
             if (WifiConfiguration.isMetered(config, null)
-                    && mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config)) {
+                    && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) {
                 continue;
             }
             if (!isSimBasedNetworkAvailableToAutoConnect(config)) {
@@ -152,7 +151,7 @@
                     continue;
                 }
                 if (WifiConfiguration.isMetered(config, null)
-                        && mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config)) {
+                        && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) {
                     continue;
                 }
                 if (!ewns.isAutojoinEnabled
@@ -214,13 +213,13 @@
                 || !config.enterpriseConfig.isAuthenticationSimBased()) {
             return true;
         }
-        int subId = mTelephonyUtil.getBestMatchSubscriptionId(config);
-        if (!mTelephonyUtil.isSimPresent(subId)) {
+        int subId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config);
+        if (!mWifiCarrierInfoManager.isSimPresent(subId)) {
             mLocalLog.log("SIM is not present for subId: " + subId);
             return false;
         }
-        if (mTelephonyUtil.requiresImsiEncryption(subId)) {
-            return mTelephonyUtil.isImsiEncryptionInfoAvailable(subId);
+        if (mWifiCarrierInfoManager.requiresImsiEncryption(subId)) {
+            return mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId);
         }
         return true;
     }
diff --git a/service/java/com/android/server/wifi/SavedNetworkNominator.java b/service/java/com/android/server/wifi/SavedNetworkNominator.java
index dd4d45f..2d91881 100644
--- a/service/java/com/android/server/wifi/SavedNetworkNominator.java
+++ b/service/java/com/android/server/wifi/SavedNetworkNominator.java
@@ -19,11 +19,12 @@
 import android.annotation.NonNull;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
+import android.telephony.TelephonyManager;
 import android.util.LocalLog;
 import android.util.Pair;
 
 import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper;
-import com.android.server.wifi.util.TelephonyUtil;
+import com.android.server.wifi.util.WifiPermissionsUtil;
 
 import java.util.List;
 
@@ -35,16 +36,19 @@
     private static final String NAME = "SavedNetworkNominator";
     private final WifiConfigManager mWifiConfigManager;
     private final LocalLog mLocalLog;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private final PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
+    private final WifiPermissionsUtil mWifiPermissionsUtil;
 
     SavedNetworkNominator(WifiConfigManager configManager,
-            PasspointNetworkNominateHelper nominateHelper,
-            LocalLog localLog, TelephonyUtil telephonyUtil) {
+            PasspointNetworkNominateHelper nominateHelper, LocalLog localLog,
+            WifiCarrierInfoManager wifiCarrierInfoManager,
+            WifiPermissionsUtil wifiPermissionsUtil) {
         mWifiConfigManager = configManager;
         mPasspointNetworkNominateHelper = nominateHelper;
         mLocalLog = localLog;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
+        mWifiPermissionsUtil = wifiPermissionsUtil;
     }
 
     private void localLog(String log) {
@@ -128,7 +132,8 @@
 
             if (!status.isNetworkEnabled()) {
                 continue;
-            } else if (network.BSSID != null &&  !network.BSSID.equals("any")
+            }
+            if (network.BSSID != null &&  !network.BSSID.equals("any")
                     && !network.BSSID.equals(scanResult.BSSID)) {
                 // App has specified the only BSSID to connect for this
                 // configuration. So only the matching ScanResult can be a candidate.
@@ -136,20 +141,9 @@
                         + " has specified BSSID " + network.BSSID + ". Skip "
                         + scanResult.BSSID);
                 continue;
-            } else if (network.enterpriseConfig != null
-                    && network.enterpriseConfig.isAuthenticationSimBased()) {
-                int subId = mTelephonyUtil.getBestMatchSubscriptionId(network);
-                if (!mTelephonyUtil.isSimPresent(subId)) {
-                    // Don't select if security type is EAP SIM/AKA/AKA' when SIM is not present.
-                    localLog("No SIM card is good for Network "
-                            + WifiNetworkSelector.toNetworkString(network));
-                    continue;
-                }
-                // Ignore metered network with non-data Sim, ignore.
-                if (WifiConfiguration.isMetered(network, null)
-                        && mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(network)) {
-                    continue;
-                }
+            }
+            if (isNetworkSimBasedCredential(network) && !isSimBasedNetworkAbleToAutoJoin(network)) {
+                continue;
             }
 
             // If the network is marked to use external scores, or is an open network with
@@ -171,12 +165,60 @@
                 mPasspointNetworkNominateHelper.getPasspointNetworkCandidates(scanDetails, false);
         for (Pair<ScanDetail, WifiConfiguration> candidate : candidates) {
             WifiConfiguration config = candidate.second;
-            // Ignore metered network with non-data Sim, ignore.
-            if (WifiConfiguration.isMetered(config, null)
-                    && mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config)) {
+            if (isNetworkSimBasedCredential(config) && !isSimBasedNetworkAbleToAutoJoin(config)) {
                 continue;
             }
             onConnectableListener.onConnectable(candidate.first, config);
         }
     }
+
+    private boolean isSimBasedNetworkAbleToAutoJoin(WifiConfiguration network) {
+        int carrierId = network.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID
+                ? mWifiCarrierInfoManager.getDefaultDataSimCarrierId() : network.carrierId;
+        int subId = mWifiCarrierInfoManager.getMatchingSubId(carrierId);
+        // Ignore security type is EAP SIM/AKA/AKA' when SIM is not present.
+        if (!mWifiCarrierInfoManager.isSimPresent(subId)) {
+            localLog("No SIM card is good for Network "
+                    + WifiNetworkSelector.toNetworkString(network));
+            return false;
+        }
+        // Ignore IMSI info not available or protection exemption pending network.
+        if (mWifiCarrierInfoManager.requiresImsiEncryption(subId)) {
+            if (!mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(subId)) {
+                localLog("Imsi protection required but not available for Network "
+                        + WifiNetworkSelector.toNetworkString(network));
+                return false;
+            }
+        } else if (isImsiProtectionApprovalNeeded(network.creatorUid, carrierId)) {
+            localLog("Imsi protection exemption needed for Network "
+                    + WifiNetworkSelector.toNetworkString(network));
+            return false;
+        }
+        // Ignore metered network with non-data Sim.
+        if (WifiConfiguration.isMetered(network, null)
+                && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(network)) {
+            localLog("No default SIM is used for metered Network: "
+                    + WifiNetworkSelector.toNetworkString(network));
+            return false;
+        }
+        return true;
+    }
+
+    private boolean isNetworkSimBasedCredential(WifiConfiguration network) {
+        return network != null && network.enterpriseConfig != null
+                && network.enterpriseConfig.isAuthenticationSimBased();
+    }
+
+    private boolean isImsiProtectionApprovalNeeded(int creatorUid, int carrierId) {
+        // User saved network got exemption.
+        if (mWifiPermissionsUtil.checkNetworkSettingsPermission(creatorUid)
+                || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(creatorUid)) {
+            return false;
+        }
+        if (mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(carrierId)) {
+            return false;
+        }
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(carrierId);
+        return true;
+    }
 }
diff --git a/service/java/com/android/server/wifi/SelfRecovery.java b/service/java/com/android/server/wifi/SelfRecovery.java
index e789dd3..b7eb723 100644
--- a/service/java/com/android/server/wifi/SelfRecovery.java
+++ b/service/java/com/android/server/wifi/SelfRecovery.java
@@ -17,12 +17,16 @@
 package com.android.server.wifi;
 
 import android.annotation.IntDef;
+import android.content.Context;
 import android.util.Log;
 
+import com.android.wifi.resources.R;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.concurrent.TimeUnit;
 
 /**
  * This class is used to recover the wifi stack from a fatal failure. The recovery mechanism
@@ -50,19 +54,19 @@
             REASON_STA_IFACE_DOWN})
     public @interface RecoveryReason {}
 
-    public static final long MAX_RESTARTS_IN_TIME_WINDOW = 2; // 2 restarts per hour
-    public static final long MAX_RESTARTS_TIME_WINDOW_MILLIS = 60 * 60 * 1000; // 1 hour
     protected static final String[] REASON_STRINGS = {
             "Last Resort Watchdog",  // REASON_LAST_RESORT_WATCHDOG
             "WifiNative Failure",    // REASON_WIFINATIVE_FAILURE
             "Sta Interface Down"     // REASON_STA_IFACE_DOWN
     };
 
+    private final Context mContext;
     private final ActiveModeWarden mActiveModeWarden;
     private final Clock mClock;
     // Time since boot (in millis) that restart occurred
     private final LinkedList<Long> mPastRestartTimes;
-    public SelfRecovery(ActiveModeWarden activeModeWarden, Clock clock) {
+    public SelfRecovery(Context context, ActiveModeWarden activeModeWarden, Clock clock) {
+        mContext = context;
         mActiveModeWarden = activeModeWarden;
         mClock = clock;
         mPastRestartTimes = new LinkedList<>();
@@ -94,11 +98,17 @@
 
         Log.e(TAG, "Triggering recovery for reason: " + REASON_STRINGS[reason]);
         if (reason == REASON_WIFINATIVE_FAILURE) {
+            int maxRecoveriesPerHour = mContext.getResources().getInteger(
+                    R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour);
+            if (maxRecoveriesPerHour == 0) {
+                Log.e(TAG, "Recovery disabled. Disabling wifi");
+                mActiveModeWarden.recoveryDisableWifi();
+                return;
+            }
             trimPastRestartTimes();
-            // Ensure there haven't been too many restarts within MAX_RESTARTS_TIME_WINDOW
-            if (mPastRestartTimes.size() >= MAX_RESTARTS_IN_TIME_WINDOW) {
-                Log.e(TAG, "Already restarted wifi (" + MAX_RESTARTS_IN_TIME_WINDOW + ") times in"
-                        + " last (" + MAX_RESTARTS_TIME_WINDOW_MILLIS + "ms ). Disabling wifi");
+            if (mPastRestartTimes.size() >= maxRecoveriesPerHour) {
+                Log.e(TAG, "Already restarted wifi " + maxRecoveriesPerHour + " times in"
+                        + " last 1 hour. Disabling wifi");
                 mActiveModeWarden.recoveryDisableWifi();
                 return;
             }
@@ -115,7 +125,7 @@
         long now = mClock.getElapsedSinceBootMillis();
         while (iter.hasNext()) {
             Long restartTimeMillis = iter.next();
-            if (now - restartTimeMillis > MAX_RESTARTS_TIME_WINDOW_MILLIS) {
+            if (now - restartTimeMillis > TimeUnit.HOURS.toMillis(1)) {
                 iter.remove();
             } else {
                 break;
diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
similarity index 73%
rename from service/java/com/android/server/wifi/util/TelephonyUtil.java
rename to service/java/com/android/server/wifi/WifiCarrierInfoManager.java
index b7b2d9e..a0dcfe9 100644
--- a/service/java/com/android/server/wifi/util/TelephonyUtil.java
+++ b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java
@@ -14,14 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.server.wifi.util;
+package com.android.server.wifi;
 
 import android.annotation.NonNull;
+import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiEnterpriseConfig;
@@ -39,19 +45,21 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseBooleanArray;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.wifi.FrameworkFacade;
-import com.android.server.wifi.IMSIParameter;
-import com.android.server.wifi.WifiNative;
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.wifi.resources.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Nullable;
 import javax.crypto.BadPaddingException;
@@ -60,12 +68,12 @@
 import javax.crypto.NoSuchPaddingException;
 
 /**
- * Utilities for the Wifi Service to interact with telephony.
+ * This class provide APIs to get carrier info from telephony service.
  * TODO(b/132188983): Refactor into TelephonyFacade which owns all instances of
  *  TelephonyManager/SubscriptionManager in Wifi
  */
-public class TelephonyUtil {
-    public static final String TAG = "TelephonyUtil";
+public class WifiCarrierInfoManager {
+    public static final String TAG = "WifiCarrierInfoManager";
     public static final String DEFAULT_EAP_PREFIX = "\0";
 
     public static final int CARRIER_INVALID_TYPE = -1;
@@ -73,6 +81,24 @@
     public static final int CARRIER_MVNO_TYPE = 1; // Mobile Virtual Network Operator
     public static final String ANONYMOUS_IDENTITY = "anonymous";
     public static final String THREE_GPP_NAI_REALM_FORMAT = "wlan.mnc%s.mcc%s.3gppnetwork.org";
+    /** Intent when user tapped action button to allow the app. */
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION =
+            "com.android.server.wifi.action.CarrierNetwork.USER_ALLOWED_CARRIER";
+    /** Intent when user tapped action button to disallow the app. */
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION =
+            "com.android.server.wifi.action.CarrierNetwork.USER_DISALLOWED_CARRIER";
+    /** Intent when user dismissed the notification. */
+    @VisibleForTesting
+    public static final String NOTIFICATION_USER_DISMISSED_INTENT_ACTION =
+            "com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED";
+    @VisibleForTesting
+    public static final String EXTRA_CARRIER_NAME =
+            "com.android.server.wifi.extra.CarrierNetwork.CARRIER_NAME";
+    @VisibleForTesting
+    public static final String EXTRA_CARRIER_ID =
+            "com.android.server.wifi.extra.CarrierNetwork.CARRIER_ID";
 
     // IMSI encryption method: RSA-OAEP with SHA-256 hash function
     private static final String IMSI_CIPHER_TRANSFORMATION =
@@ -97,27 +123,158 @@
 
     private static final Uri CONTENT_URI = Uri.parse("content://carrier_information/carrier");
 
+    private final WifiContext mContext;
+    private final Handler mHandler;
+    private final WifiInjector mWifiInjector;
+    private final Resources mResources;
     private final TelephonyManager mTelephonyManager;
     private final SubscriptionManager mSubscriptionManager;
+    private final NotificationManager mNotificationManager;
+
+    /**
+     * Intent filter for processing notification actions.
+     */
+    private final IntentFilter mIntentFilter;
+    private final FrameworkFacade mFrameworkFacade;
 
     private boolean mVerboseLogEnabled = false;
     private SparseBooleanArray mImsiEncryptionRequired = new SparseBooleanArray();
     private SparseBooleanArray mImsiEncryptionInfoAvailable = new SparseBooleanArray();
     private SparseBooleanArray mEapMethodPrefixEnable = new SparseBooleanArray();
+    private final Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap = new HashMap<>();
+    private final List<OnUserApproveCarrierListener>
+            mOnUserApproveCarrierListeners =
+            new ArrayList<>();
+
+    private boolean mUserApprovalUiActive = false;
+    private boolean mHasNewDataToSerialize = false;
+    private boolean mUserDataLoaded = false;
 
     /**
-     * Gets the instance of TelephonyUtil.
+     * Interface for other modules to listen to the user approve IMSI protection exemption.
+     */
+    public interface OnUserApproveCarrierListener {
+
+        /**
+         * Invoke when user approve the IMSI protection exemption.
+         */
+        void onUserAllowed(int carrierId);
+    }
+
+    /**
+     * Module to interact with the wifi config store.
+     */
+    private class ImsiProtectionExemptionDataSource implements
+            ImsiPrivacyProtectionExemptionStoreData.DataSource {
+        @Override
+        public Map<Integer, Boolean> toSerialize() {
+            // Clear the flag after writing to disk.
+            // TODO(b/115504887): Don't reset the flag on write failure.
+            mHasNewDataToSerialize = false;
+            return mImsiPrivacyProtectionExemptionMap;
+        }
+
+        @Override
+        public void fromDeserialized(Map<Integer, Boolean> imsiProtectionExemptionMap) {
+            mUserDataLoaded = true;
+            mImsiPrivacyProtectionExemptionMap.putAll(imsiProtectionExemptionMap);
+        }
+
+        @Override
+        public void reset() {
+            mUserDataLoaded = false;
+            mImsiPrivacyProtectionExemptionMap.clear();
+        }
+
+        @Override
+        public boolean hasNewDataToSerialize() {
+            return mHasNewDataToSerialize;
+        }
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver =
+            new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    String carrierName = intent.getStringExtra(EXTRA_CARRIER_NAME);
+                    int carrierId = intent.getIntExtra(EXTRA_CARRIER_ID, -1);
+                    if (carrierName == null || carrierId == -1) {
+                        Log.e(TAG, "No carrier name or carrier id found in intent");
+                        return;
+                    }
+
+                    switch (intent.getAction()) {
+                        case NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION:
+                            Log.i(TAG, "User clicked to allow carrier");
+                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
+                            // Collapse the notification bar
+                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                            break;
+                        case NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION:
+                            handleUserDisallowCarrierExemptionAction(carrierName, carrierId);
+                            break;
+                        case NOTIFICATION_USER_DISMISSED_INTENT_ACTION:
+                            handleUserDismissAction();
+                            return; // no need to cancel a dismissed notification, return.
+                        default:
+                            Log.e(TAG, "Unknown action " + intent.getAction());
+                            return;
+                    }
+                    // Clear notification once the user interacts with it.
+                    mNotificationManager.cancel(SystemMessageProto
+                            .SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+                }
+            };
+    private void handleUserDismissAction() {
+        Log.i(TAG, "User dismissed the notification");
+        mUserApprovalUiActive = false;
+    }
+
+    private void handleUserAllowCarrierExemptionAction(String carrierName, int carrierId) {
+        Log.i(TAG, "User clicked to allow carrier:" + carrierName);
+        setHasUserApprovedImsiPrivacyExemptionForCarrier(true, carrierId);
+        mUserApprovalUiActive = false;
+    }
+
+    private void handleUserDisallowCarrierExemptionAction(String carrierName, int carrierId) {
+        Log.i(TAG, "User clicked to disallow carrier:" + carrierName);
+        setHasUserApprovedImsiPrivacyExemptionForCarrier(false, carrierId);
+        mUserApprovalUiActive = false;
+    }
+
+    /**
+     * Gets the instance of WifiCarrierInfoManager.
      * @param telephonyManager Instance of {@link TelephonyManager}
      * @param subscriptionManager Instance of {@link SubscriptionManager}
-     * @return The instance of TelephonyUtil
+     * @param WifiInjector Instance of {@link WifiInjector}
+     * @return The instance of WifiCarrierInfoManager
      */
-    public TelephonyUtil(@NonNull TelephonyManager telephonyManager,
+    public WifiCarrierInfoManager(@NonNull TelephonyManager telephonyManager,
             @NonNull SubscriptionManager subscriptionManager,
+            @NonNull WifiInjector wifiInjector,
             @NonNull FrameworkFacade frameworkFacade,
-            @NonNull Context context,
+            @NonNull WifiContext context,
+            @NonNull WifiConfigStore configStore,
             @NonNull Handler handler) {
         mTelephonyManager = telephonyManager;
+        mContext = context;
+        mResources = mContext.getResources();
+        mWifiInjector = wifiInjector;
+        mHandler = handler;
         mSubscriptionManager = subscriptionManager;
+        mFrameworkFacade = frameworkFacade;
+
+        mNotificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        // Register broadcast receiver for UI interactions.
+        mIntentFilter = new IntentFilter();
+        mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION);
+        mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION);
+        mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION);
+
+        mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler);
+        configStore.registerStoreData(wifiInjector.makeImsiProtectionExemptionStoreData(
+                new ImsiProtectionExemptionDataSource()));
 
         updateImsiEncryptionInfo(context);
 
@@ -552,7 +709,7 @@
      */
     public static boolean isAnonymousAtRealmIdentity(String identity) {
         if (TextUtils.isEmpty(identity)) return false;
-        final String anonymousId = TelephonyUtil.ANONYMOUS_IDENTITY + "@";
+        final String anonymousId = WifiCarrierInfoManager.ANONYMOUS_IDENTITY + "@";
         return identity.startsWith(anonymousId)
                 || identity.substring(1).startsWith(anonymousId);
     }
@@ -1184,4 +1341,179 @@
         int subId = getMatchingSubId(config.carrierId);
         return subId != SubscriptionManager.getDefaultDataSubscriptionId();
     }
+
+    /**
+     * Get the carrier Id of the default data sim.
+     */
+    public int getDefaultDataSimCarrierId() {
+        int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+        TelephonyManager specifiedTm = mTelephonyManager.createForSubscriptionId(subId);
+        return specifiedTm.getSimCarrierId();
+    }
+
+    /**
+     * Add a listener to monitor user approval IMSI protection exemption.
+     */
+    public void addImsiExemptionUserApprovalListener(
+            OnUserApproveCarrierListener listener) {
+        mOnUserApproveCarrierListeners.add(listener);
+    }
+
+    /**
+     * Clear the Imsi Privacy Exemption user approval info the target carrier.
+     */
+    public void clearImsiPrivacyExemptionForCarrier(int carrierId) {
+        mImsiPrivacyProtectionExemptionMap.remove(carrierId);
+        saveToStore();
+    }
+
+    /**
+     * Check if carrier have user approved exemption for IMSI protection
+     */
+    public boolean hasUserApprovedImsiPrivacyExemptionForCarrier(int carrierId) {
+        return  mImsiPrivacyProtectionExemptionMap.getOrDefault(carrierId, false);
+    }
+
+    /**
+     * Enable or disable exemption on IMSI protection.
+     */
+    public void setHasUserApprovedImsiPrivacyExemptionForCarrier(boolean approved, int carrierId) {
+        if (mVerboseLogEnabled) {
+            Log.v(TAG, "Setting Imsi privacy exemption for carrier " + carrierId
+                    + (approved ? " approved" : " not approved"));
+        }
+        mImsiPrivacyProtectionExemptionMap.put(carrierId, approved);
+        // If user approved the exemption restore to initial auto join configure.
+        if (approved) {
+            for (OnUserApproveCarrierListener listener : mOnUserApproveCarrierListeners) {
+                listener.onUserAllowed(carrierId);
+            }
+        }
+        saveToStore();
+    }
+
+    private void sendImsiPrivacyNotification(int carrierId) {
+        String carrierName = getCarrierNameforSubId(getMatchingSubId(carrierId));
+        Notification.Action userAllowAppNotificationAction =
+                new Notification.Action.Builder(null,
+                        mResources.getText(R.string
+                                .wifi_suggestion_action_allow_imsi_privacy_exemption_carrier),
+                        getPrivateBroadcast(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
+                                Pair.create(EXTRA_CARRIER_NAME, carrierName),
+                                Pair.create(EXTRA_CARRIER_ID, carrierId)))
+                        .build();
+        Notification.Action userDisallowAppNotificationAction =
+                new Notification.Action.Builder(null,
+                        mResources.getText(R.string
+                                .wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier),
+                        getPrivateBroadcast(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION,
+                                Pair.create(EXTRA_CARRIER_NAME, carrierName),
+                                Pair.create(EXTRA_CARRIER_ID, carrierId)))
+                        .build();
+
+        Notification notification = mFrameworkFacade.makeNotificationBuilder(
+                mContext, WifiService.NOTIFICATION_NETWORK_STATUS)
+                .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
+                        com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range))
+                .setTicker(mResources.getString(
+                        R.string.wifi_suggestion_imsi_privacy_title, carrierName))
+                .setContentTitle(mResources.getString(
+                        R.string.wifi_suggestion_imsi_privacy_title, carrierName))
+                .setStyle(new Notification.BigTextStyle()
+                        .bigText(mResources.getString(
+                                R.string.wifi_suggestion_imsi_privacy_content)))
+                .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
+                        Pair.create(EXTRA_CARRIER_NAME, carrierName),
+                        Pair.create(EXTRA_CARRIER_ID, carrierId)))
+                .setShowWhen(false)
+                .setLocalOnly(true)
+                .setColor(mResources.getColor(android.R.color.system_notification_accent_color,
+                        mContext.getTheme()))
+                .addAction(userDisallowAppNotificationAction)
+                .addAction(userAllowAppNotificationAction)
+                .build();
+
+        // Post the notification.
+        mNotificationManager.notify(
+                SystemMessageProto.SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE, notification);
+        mUserApprovalUiActive = true;
+    }
+
+    private void sendImsiPrivacyConfirmationDialog(@NonNull String carrierName, int carrierId) {
+        AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext)
+                .setTitle(mResources.getString(
+                        R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title))
+                .setMessage(mResources.getString(
+                        R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content,
+                        carrierName))
+                .setPositiveButton(mResources.getText(
+                        R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation),
+                        (d, which) -> mHandler.post(
+                                () -> handleUserAllowCarrierExemptionAction(
+                                        carrierName, carrierId)))
+                .setNegativeButton(mResources.getText(
+                        R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation),
+                        (d, which) -> mHandler.post(
+                                () -> handleUserDisallowCarrierExemptionAction(
+                                        carrierName, carrierId)))
+                .setOnDismissListener(
+                        (d) -> mHandler.post(this::handleUserDismissAction))
+                .setOnCancelListener(
+                        (d) -> mHandler.post(this::handleUserDismissAction))
+                .create();
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        dialog.getWindow().addSystemFlags(
+                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
+        dialog.show();
+        mUserApprovalUiActive = true;
+    }
+
+    /**
+     * Send notification for exemption of IMSI protection if user never made choice before.
+     */
+    public void sendImsiProtectionExemptionNotificationIfRequired(int carrierId) {
+        int subId = getMatchingSubId(carrierId);
+        // If user data isn't loaded, don't send notification.
+        if (!mUserDataLoaded) {
+            return;
+        }
+        if (requiresImsiEncryption(subId)) {
+            return;
+        }
+        if (mImsiPrivacyProtectionExemptionMap.containsKey(carrierId)) {
+            return;
+        }
+        if (mUserApprovalUiActive) {
+            return;
+        }
+        Log.i(TAG, "Sending IMSI protection notification for " + carrierId);
+        sendImsiPrivacyNotification(carrierId);
+    }
+
+    private PendingIntent getPrivateBroadcast(@NonNull String action,
+            @NonNull Pair<String, String> extra1, @NonNull Pair<String, Integer> extra2) {
+        Intent intent = new Intent(action)
+                .setPackage(mWifiInjector.getWifiStackPackageName())
+                .putExtra(extra1.first, extra1.second)
+                .putExtra(extra2.first, extra2.second);
+        return mFrameworkFacade.getBroadcast(mContext, 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    private void saveToStore() {
+        // Set the flag to let WifiConfigStore that we have new data to write.
+        mHasNewDataToSerialize = true;
+        if (!mWifiInjector.getWifiConfigManager().saveToStore(true)) {
+            Log.w(TAG, "Failed to save to store");
+        }
+    }
+
+    /**
+     * Helper method for user factory reset network setting.
+     */
+    public void clear() {
+        mImsiPrivacyProtectionExemptionMap.clear();
+        saveToStore();
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index 418c160..90c7f42 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -54,7 +54,6 @@
 import com.android.server.wifi.hotspot2.PasspointManager;
 import com.android.server.wifi.util.LruConnectionTracker;
 import com.android.server.wifi.util.MissingCounterTimerLockList;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 import com.android.wifi.resources.R;
@@ -104,8 +103,7 @@
     public static final String PASSWORD_MASK = "*";
 
     /**
-     * Interface for other modules to listen to the network updated
-     * events.
+     * Interface for other modules to listen to the network updated events.
      * Note: Credentials are masked to avoid accidentally sending credentials outside the stack.
      * Use WifiConfigManager#getConfiguredNetworkWithPassword() to retrieve credentials.
      */
@@ -200,6 +198,9 @@
 
     @VisibleForTesting
     public static final int SCAN_RESULT_MISSING_COUNT_THRESHOLD = 1;
+    @VisibleForTesting
+    protected static final String ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG =
+            "enhanced_mac_randomization_force_enabled";
 
     /**
      * General sorting algorithm of all networks for scanning purposes:
@@ -241,7 +242,7 @@
     private final WifiPermissionsWrapper mWifiPermissionsWrapper;
     private final WifiInjector mWifiInjector;
     private final MacAddressUtil mMacAddressUtil;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private final WifiScoreCard mWifiScoreCard;
     // Keep order of network connection.
     private final LruConnectionTracker mLruConnectionTracker;
@@ -332,7 +333,7 @@
      */
     WifiConfigManager(
             Context context, Clock clock, UserManager userManager,
-            TelephonyUtil telephonyUtil, WifiKeyStore wifiKeyStore,
+            WifiCarrierInfoManager wifiCarrierInfoManager, WifiKeyStore wifiKeyStore,
             WifiConfigStore wifiConfigStore,
             WifiPermissionsUtil wifiPermissionsUtil,
             WifiPermissionsWrapper wifiPermissionsWrapper,
@@ -347,7 +348,7 @@
         mClock = clock;
         mUserManager = userManager;
         mBackupManagerProxy = new BackupManagerProxy();
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mWifiKeyStore = wifiKeyStore;
         mWifiConfigStore = wifiConfigStore;
         mWifiPermissionsUtil = wifiPermissionsUtil;
@@ -425,6 +426,10 @@
                 || config.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_PERSISTENT) {
             return false;
         }
+        if (mFrameworkFacade.getIntegerSetting(mContext,
+                ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG, 0) == 1) {
+            return true;
+        }
         if (config.getIpConfiguration().getIpAssignment() == IpConfiguration.IpAssignment.STATIC) {
             return false;
         }
@@ -2703,6 +2708,7 @@
             network = configuration.SSID;
         }
         mUserTemporarilyDisabledList.remove(network);
+        mWifiInjector.getBssidBlocklistMonitor().clearBssidBlocklistForSsid(configuration.SSID);
         Log.d(TAG, "Enable disabled network: " + network + " num="
                 + mUserTemporarilyDisabledList.size());
     }
@@ -2726,7 +2732,7 @@
             }
             if (config.enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.PEAP) {
                 Pair<String, String> currentIdentity =
-                        mTelephonyUtil.getSimIdentity(config);
+                        mWifiCarrierInfoManager.getSimIdentity(config);
                 if (mVerboseLoggingEnabled) {
                     Log.d(TAG, "New identity for config " + config + ": " + currentIdentity);
                 }
@@ -2741,7 +2747,7 @@
             } else {
                 // reset identity as well: supplicant will ask us for it
                 config.enterpriseConfig.setIdentity("");
-                if (!TelephonyUtil.isAnonymousAtRealmIdentity(
+                if (!WifiCarrierInfoManager.isAnonymousAtRealmIdentity(
                         config.enterpriseConfig.getAnonymousIdentity())) {
                     config.enterpriseConfig.setAnonymousIdentity("");
                 }
@@ -3194,7 +3200,7 @@
         pw.println("WifiConfigManager - PNO scan recency sorting enabled = "
                 + mContext.getResources().getBoolean(R.bool.config_wifiPnoRecencySortingEnabled));
         mWifiConfigStore.dump(fd, pw, args);
-        mTelephonyUtil.dump(fd, pw, args);
+        mWifiCarrierInfoManager.dump(fd, pw, args);
     }
 
     /**
@@ -3223,7 +3229,7 @@
     }
 
     /**
-     * Set the network update event listener
+     * Add the network update event listener
      */
     public void addOnNetworkUpdateListener(OnNetworkUpdateListener listener) {
         mListeners.add(listener);
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 72d8db2..e5fda67 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -605,6 +605,12 @@
                 return false;
             }
         }
+        // b/153435438: Added to deal with badly formed WifiConfiguration from apps.
+        if (config.preSharedKey != null && !config.needsPreSharedKey()) {
+            Log.e(TAG, "preSharedKey set with an invalid KeyMgmt, resetting KeyMgmt to WPA_PSK");
+            config.allowedKeyManagement.clear();
+            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        }
         if (!validateIpConfiguration(config.getIpConfiguration())) {
             return false;
         }
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 467abf3..030121e 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -145,6 +145,7 @@
     private final ClientModeImpl mStateMachine;
     private final WifiInjector mWifiInjector;
     private final WifiConfigManager mConfigManager;
+    private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     private final WifiInfo mWifiInfo;
     private final WifiConnectivityHelper mConnectivityHelper;
     private final WifiNetworkSelector mNetworkSelector;
@@ -181,6 +182,11 @@
     private boolean mPnoScanStarted = false;
     private boolean mPeriodicScanTimerSet = false;
     private boolean mDelayedPartialScanTimerSet = false;
+
+    // Used for Initial Scan metrics
+    private boolean mFailedInitialPartialScan = false;
+    private int mInitialPartialScanChannelCount;
+
     // Device configs
     private boolean mWaitForFullBandScanResults = false;
 
@@ -521,10 +527,20 @@
                     Log.i(TAG, "Connection attempted with the reduced initial scans");
                     schedulePeriodicScanTimer(
                             getScheduledSingleScanIntervalMs(mCurrentSingleScanScheduleIndex));
+                    mWifiMetrics.reportInitialPartialScan(mInitialPartialScanChannelCount, true);
+                    mInitialPartialScanChannelCount = 0;
                 } else {
                     Log.i(TAG, "Connection was not attempted, issuing a full scan");
                     startConnectivityScan(SCAN_IMMEDIATELY);
+                    mFailedInitialPartialScan = true;
                 }
+            } else if (mInitialScanState == INITIAL_SCAN_STATE_COMPLETE) {
+                if (mFailedInitialPartialScan && wasConnectAttempted) {
+                    // Initial scan failed, but following full scan succeeded
+                    mWifiMetrics.reportInitialPartialScan(mInitialPartialScanChannelCount, false);
+                }
+                mFailedInitialPartialScan = false;
+                mInitialPartialScanChannelCount = 0;
             }
         }
 
@@ -699,40 +715,39 @@
             WifiConfigManager.OnNetworkUpdateListener {
         @Override
         public void onNetworkAdded(WifiConfiguration config) {
-            updateScan();
+            triggerScanOnNetworkChanges();
         }
         @Override
         public void onNetworkEnabled(WifiConfiguration config) {
-            updateScan();
+            triggerScanOnNetworkChanges();
         }
         @Override
         public void onNetworkRemoved(WifiConfiguration config) {
-            updateScan();
+            triggerScanOnNetworkChanges();
         }
         @Override
         public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) {
-            updateScan();
+            triggerScanOnNetworkChanges();
         }
         @Override
         public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) { }
 
         @Override
         public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) {
-            updateScan();
+            triggerScanOnNetworkChanges();
         }
-        private void updateScan() {
-            if (mScreenOn) {
-                // Update scanning schedule if needed
-                if (updateSingleScanningSchedule()) {
-                    localLog("Saved networks updated impacting single scan schedule");
-                    startConnectivityScan(false);
-                }
-            } else {
-                // Update the PNO scan network list when screen is off. Here we
-                // rely on startConnectivityScan() to perform all the checks and clean up.
-                localLog("Saved networks updated impacting pno scan");
-                startConnectivityScan(false);
-            }
+    }
+
+    private class OnSuggestionUpdateListener implements
+            WifiNetworkSuggestionsManager.OnSuggestionUpdateListener {
+        @Override
+        public void onSuggestionsAddedOrUpdated(List<WifiNetworkSuggestion> suggestions) {
+            triggerScanOnNetworkChanges();
+        }
+
+        @Override
+        public void onSuggestionsRemoved(List<WifiNetworkSuggestion> suggestions) {
+            triggerScanOnNetworkChanges();
         }
     }
 
@@ -741,7 +756,8 @@
      */
     WifiConnectivityManager(Context context, ScoringParams scoringParams,
             ClientModeImpl stateMachine,
-            WifiInjector injector, WifiConfigManager configManager, WifiInfo wifiInfo,
+            WifiInjector injector, WifiConfigManager configManager,
+            WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, WifiInfo wifiInfo,
             WifiNetworkSelector networkSelector, WifiConnectivityHelper connectivityHelper,
             WifiLastResortWatchdog wifiLastResortWatchdog, OpenNetworkNotifier openNetworkNotifier,
             WifiMetrics wifiMetrics, Handler handler,
@@ -750,6 +766,7 @@
         mStateMachine = stateMachine;
         mWifiInjector = injector;
         mConfigManager = configManager;
+        mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager;
         mWifiInfo = wifiInfo;
         mNetworkSelector = networkSelector;
         mConnectivityHelper = connectivityHelper;
@@ -766,6 +783,9 @@
 
         // Listen to WifiConfigManager network update events
         mConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener());
+        // Listen to WifiNetworkSuggestionsManager suggestion update events
+        mWifiNetworkSuggestionsManager.addOnSuggestionUpdateListener(
+                new OnSuggestionUpdateListener());
         mBssidBlocklistMonitor = mWifiInjector.getBssidBlocklistMonitor();
         mWifiChannelUtilization = mWifiInjector.getWifiChannelUtilizationScan();
         mNetworkSelector.setWifiChannelUtilization(mWifiChannelUtilization);
@@ -1052,6 +1072,21 @@
         }
     }
 
+    private void triggerScanOnNetworkChanges() {
+        if (mScreenOn) {
+            // Update scanning schedule if needed
+            if (updateSingleScanningSchedule()) {
+                localLog("Saved networks / suggestions updated impacting single scan schedule");
+                startConnectivityScan(false);
+            }
+        } else {
+            // Update the PNO scan network list when screen is off. Here we
+            // rely on startConnectivityScan() to perform all the checks and clean up.
+            localLog("Saved networks / suggestions updated impacting pno scan");
+            startConnectivityScan(false);
+        }
+    }
+
     // Start a single scan and set up the interval for next single scan.
     private void startPeriodicSingleScan() {
         // Reaching here with scanning schedule is null means this is a false timer alarm
@@ -1115,6 +1150,7 @@
                 // Hence, we verify state before changing to AWIATING_RESPONSE
                 if (mInitialScanState == INITIAL_SCAN_STATE_START) {
                     setInitialScanState(INITIAL_SCAN_STATE_AWAITING_RESPONSE);
+                    mWifiMetrics.incrementInitialPartialScanCount();
                 }
                 // No scheduling for another scan (until we get the results)
                 return;
@@ -1219,6 +1255,8 @@
                 isFullBandScan = true;
                 // Skip the initial scan since no channel history available
                 setInitialScanState(INITIAL_SCAN_STATE_COMPLETE);
+            } else {
+                mInitialPartialScanChannelCount = settings.channels.length;
             }
         }
         settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; // always do high accuracy scans.
@@ -1230,8 +1268,7 @@
         // retrieve the list of hidden network SSIDs from saved network to scan for
         settings.hiddenNetworks.addAll(mConfigManager.retrieveHiddenNetworkList());
         // retrieve the list of hidden network SSIDs from Network suggestion to scan for
-        settings.hiddenNetworks.addAll(
-                mWifiInjector.getWifiNetworkSuggestionsManager().retrieveHiddenNetworkList());
+        settings.hiddenNetworks.addAll(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList());
 
         SingleScanListener singleScanListener =
                 new SingleScanListener(isFullBandScan);
@@ -1356,8 +1393,7 @@
 
     private @NonNull List<WifiConfiguration> getAllScanOptimizationNetworks() {
         List<WifiConfiguration> networks = mConfigManager.getSavedNetworks(-1);
-        networks.addAll(mWifiInjector.getWifiNetworkSuggestionsManager()
-                .getAllScanOptimizationSuggestionNetworks());
+        networks.addAll(mWifiNetworkSuggestionsManager.getAllScanOptimizationSuggestionNetworks());
         // remove all auto-join disabled or network selection disabled network.
         networks.removeIf(config -> !config.allowAutojoin
                 || !config.getNetworkSelectionStatus().isNetworkEnabled());
@@ -1580,7 +1616,7 @@
         }
 
         Set<WifiNetworkSuggestion> suggestionsNetworks =
-                mWifiInjector.getWifiNetworkSuggestionsManager().getAllNetworkSuggestions();
+                mWifiNetworkSuggestionsManager.getAllNetworkSuggestions();
         // If total size not equal to 1, then no need to proceed
         if (passpointNetworks.size() + savedNetworks.size() + suggestionsNetworks.size() != 1) {
             return false;
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 5940089..23bb75a 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -56,7 +56,6 @@
 import com.android.server.wifi.util.LruConnectionTracker;
 import com.android.server.wifi.util.NetdWrapper;
 import com.android.server.wifi.util.SettingsMigrationDataHolder;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 
@@ -155,7 +154,7 @@
     private BssidBlocklistMonitor mBssidBlocklistMonitor;
     private final MacAddressUtil mMacAddressUtil;
     private final MboOceController mMboOceController;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private WifiChannelUtilization mWifiChannelUtilizationScan;
     private WifiChannelUtilization mWifiChannelUtilizationConnected;
     private final KeyStore mKeyStore;
@@ -260,8 +259,9 @@
                 WifiConfigStore.createSharedFiles(mFrameworkFacade.isNiapModeOn(mContext)));
         SubscriptionManager subscriptionManager =
                 mContext.getSystemService(SubscriptionManager.class);
-        mTelephonyUtil = new TelephonyUtil(makeTelephonyManager(), subscriptionManager,
-                mFrameworkFacade, mContext, wifiHandler);
+        mWifiCarrierInfoManager = new WifiCarrierInfoManager(makeTelephonyManager(),
+                subscriptionManager, this, mFrameworkFacade, mContext,
+                mWifiConfigStore, wifiHandler);
         String l2KeySeed = Secure.getString(mContext.getContentResolver(), Secure.ANDROID_ID);
         mWifiScoreCard = new WifiScoreCard(mClock, l2KeySeed, mDeviceConfigFacade);
         mWifiMetrics.setWifiScoreCard(mWifiScoreCard);
@@ -269,7 +269,7 @@
                 mContext);
         // Config Manager
         mWifiConfigManager = new WifiConfigManager(mContext, mClock,
-                mUserManager, mTelephonyUtil,
+                mUserManager, mWifiCarrierInfoManager,
                 mWifiKeyStore, mWifiConfigStore, mWifiPermissionsUtil,
                 mWifiPermissionsWrapper, this,
                 new NetworkListSharedStoreData(mContext),
@@ -301,17 +301,18 @@
         mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector);
         mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, wifiHandler,
                 this, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics,
-                mTelephonyUtil, mWifiKeyStore, mLruConnectionTracker);
+                mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker);
         mPasspointManager = new PasspointManager(mContext, this,
                 wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
-                mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mTelephonyUtil);
+                mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
         PasspointNetworkNominateHelper nominateHelper =
                 new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager,
                         mConnectivityLocalLog);
         mSavedNetworkNominator = new SavedNetworkNominator(
-                mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mTelephonyUtil);
+                mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mWifiCarrierInfoManager,
+                mWifiPermissionsUtil);
         mNetworkSuggestionNominator = new NetworkSuggestionNominator(mWifiNetworkSuggestionsManager,
-                mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mTelephonyUtil);
+                mWifiConfigManager, nominateHelper, mConnectivityLocalLog, mWifiCarrierInfoManager);
         mScoredNetworkNominator = new ScoredNetworkNominator(mContext, wifiHandler,
                 mFrameworkFacade, mNetworkScoreManager, mContext.getPackageManager(),
                 mWifiConfigManager, mConnectivityLocalLog,
@@ -346,8 +347,8 @@
                 this, mBackupManagerProxy, mCountryCode, mWifiNative,
                 new WrongPasswordNotifier(mContext, mFrameworkFacade),
                 mSarManager, mWifiTrafficPoller, mLinkProbeManager, mBatteryStats,
-                supplicantStateTracker, mMboOceController, mTelephonyUtil,
-                new EapFailureNotifier(mContext, mFrameworkFacade, mTelephonyUtil),
+                supplicantStateTracker, mMboOceController, mWifiCarrierInfoManager,
+                new EapFailureNotifier(mContext, mFrameworkFacade, mWifiCarrierInfoManager),
                 new SimRequiredNotifier(mContext, mFrameworkFacade));
         mActiveModeWarden = new ActiveModeWarden(this, wifiLooper,
                 mWifiNative, new DefaultModeManager(mContext), mBatteryStats, mWifiDiagnostics,
@@ -369,7 +370,7 @@
                 this, mFrameworkFacade, mClock);
         mLockManager = new WifiLockManager(mContext, mBatteryStats,
                 mClientModeImpl, mFrameworkFacade, wifiHandler, mWifiNative, mClock, mWifiMetrics);
-        mSelfRecovery = new SelfRecovery(mActiveModeWarden, mClock);
+        mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock);
         mWifiMulticastLockManager = new WifiMulticastLockManager(
                 mClientModeImpl.getMcastLockManagerFilterController(), mBatteryStats);
         mDppManager = new DppManager(wifiHandler, mWifiNative,
@@ -410,7 +411,7 @@
         mWifiNetworkSuggestionsManager.enableVerboseLogging(verbose);
         LogcatLog.enableVerboseLogging(verbose);
         mDppManager.enableVerboseLogging(verbose);
-        mTelephonyUtil.enableVerboseLogging(verbose);
+        mWifiCarrierInfoManager.enableVerboseLogging(verbose);
     }
 
     public UserManager getUserManager() {
@@ -537,8 +538,8 @@
         return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
     }
 
-    public TelephonyUtil getTelephonyUtil() {
-        return mTelephonyUtil;
+    public WifiCarrierInfoManager getWifiCarrierInfoManager() {
+        return mWifiCarrierInfoManager;
     }
 
     public WifiStateTracker getWifiStateTracker() {
@@ -619,7 +620,7 @@
         mWifiChannelUtilizationScan = new WifiChannelUtilization(mClock);
         return new WifiConnectivityManager(mContext, getScoringParams(),
                 clientModeImpl, this,
-                mWifiConfigManager, clientModeImpl.getWifiInfo(),
+                mWifiConfigManager, mWifiNetworkSuggestionsManager, clientModeImpl.getWifiInfo(),
                 mWifiNetworkSelector, mWifiConnectivityHelper,
                 mWifiLastResortWatchdog, mOpenNetworkNotifier,
                 mWifiMetrics, new Handler(mWifiHandlerThread.getLooper()),
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 9a75a5f..409293f 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -64,6 +64,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.ExperimentValues;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.HealthMonitorMetrics;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.InitPartialScanStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
@@ -463,6 +464,17 @@
     private final IntHistogram mRxThroughputMbpsHistogramAbove2G =
             new IntHistogram(THROUGHPUT_MBPS_BUCKETS);
 
+    // Init partial scan metrics
+    private int mInitPartialScanTotalCount;
+    private int mInitPartialScanSuccessCount;
+    private int mInitPartialScanFailureCount;
+    private static final int[] INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS =
+            {1, 3, 5, 10};
+    private final IntHistogram mInitPartialScanSuccessHistogram =
+            new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
+    private final IntHistogram mInitPartialScanFailureHistogram =
+            new IntHistogram(INIT_PARTIAL_SCAN_HISTOGRAM_BUCKETS);
+
     // Wi-Fi off metrics
     private final WifiOffMetrics mWifiOffMetrics = new WifiOffMetrics();
 
@@ -2190,6 +2202,8 @@
         int mboCellularDataAwareNetworks = 0;
         int oceSupportedNetworks = 0;
         int filsSupportedNetworks = 0;
+        int band6gNetworks = 0;
+        int standard11axNetworks = 0;
 
         for (ScanDetail scanDetail : scanDetails) {
             NetworkDetail networkDetail = scanDetail.getNetworkDetail();
@@ -2215,12 +2229,18 @@
                         oceSupportedNetworks++;
                     }
                 }
+                if (networkDetail.getWifiMode() == InformationElementUtil.WifiMode.MODE_11AX) {
+                    standard11axNetworks++;
+                }
             }
             if (scanResult != null && scanResult.capabilities != null) {
                 if (ScanResultUtil.isScanResultForFilsSha256Network(scanResult)
                         || ScanResultUtil.isScanResultForFilsSha384Network(scanResult)) {
                     filsSupportedNetworks++;
                 }
+                if (scanResult.is6GHz()) {
+                    band6gNetworks++;
+                }
                 if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
                     wpa3EnterpriseNetworks++;
                 } else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) {
@@ -2258,6 +2278,8 @@
             mWifiLogProto.numMboCellularDataAwareNetworkScanResults += mboCellularDataAwareNetworks;
             mWifiLogProto.numOceSupportedNetworkScanResults += oceSupportedNetworks;
             mWifiLogProto.numFilsSupportedNetworkScanResults += filsSupportedNetworks;
+            mWifiLogProto.num11AxNetworkScanResults += standard11axNetworks;
+            mWifiLogProto.num6GNetworkScanResults += band6gNetworks;
             mWifiLogProto.numScans++;
         }
     }
@@ -3113,6 +3135,10 @@
                         + mWifiLogProto.numOceSupportedNetworkScanResults);
                 pw.println("mWifiLogProto.numFilsSupportedNetworkScanResults="
                         + mWifiLogProto.numFilsSupportedNetworkScanResults);
+                pw.println("mWifiLogProto.num11AxNetworkScanResults="
+                        + mWifiLogProto.num11AxNetworkScanResults);
+                pw.println("mWifiLogProto.num6GNetworkScanResults"
+                        + mWifiLogProto.num6GNetworkScanResults);
                 pw.println("mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd="
                         + mWifiLogProto.numBssidFilteredDueToMboAssocDisallowInd);
                 pw.println("mWifiLogProto.numConnectToNetworkSupportingMbo="
@@ -3501,10 +3527,20 @@
                         + mTxThroughputMbpsHistogramAbove2G);
                 pw.println("mRxThroughputMbpsHistogramAbove2G:\n"
                         + mRxThroughputMbpsHistogramAbove2G);
+
+                dumpInitPartialScanMetrics(pw);
             }
         }
     }
 
+    private void dumpInitPartialScanMetrics(PrintWriter pw) {
+        pw.println("mInitPartialScanTotalCount:\n" + mInitPartialScanTotalCount);
+        pw.println("mInitPartialScanSuccessCount:\n" + mInitPartialScanSuccessCount);
+        pw.println("mInitPartialScanFailureCount:\n" + mInitPartialScanFailureCount);
+        pw.println("mInitPartialScanSuccessHistogram:\n" + mInitPartialScanSuccessHistogram);
+        pw.println("mInitPartialScanFailureHistogram:\n" + mInitPartialScanFailureHistogram);
+    }
+
     private void printWifiUsabilityStatsEntry(PrintWriter pw, WifiUsabilityStatsEntry entry) {
         StringBuilder line = new StringBuilder();
         line.append("timestamp_ms=" + entry.timeStampMs);
@@ -3677,6 +3713,32 @@
     }
 
     /**
+     * Increment initial partial scan count
+     */
+    public void incrementInitialPartialScanCount() {
+        synchronized (mLock) {
+            mInitPartialScanTotalCount++;
+        }
+    }
+
+    /**
+     * Report of initial partial scan
+     * @param channelCount number of channels used in this scan
+     * @param status true if scan resulted in a network connection attempt, false otherwise
+     */
+    public void reportInitialPartialScan(int channelCount, boolean status) {
+        synchronized (mLock) {
+            if (status) {
+                mInitPartialScanSuccessCount++;
+                mInitPartialScanSuccessHistogram.increment(channelCount);
+            } else {
+                mInitPartialScanFailureCount++;
+                mInitPartialScanFailureHistogram.increment(channelCount);
+            }
+        }
+    }
+
+    /**
      * Put all metrics that were being tracked separately into mWifiLogProto
      */
     private void consolidateProto() {
@@ -4088,6 +4150,16 @@
                     mRxThroughputMbpsHistogram2G.toProto();
             mWifiLogProto.throughputMbpsHistogram.rxAbove2G =
                     mRxThroughputMbpsHistogramAbove2G.toProto();
+
+            InitPartialScanStats initialPartialScanStats = new InitPartialScanStats();
+            initialPartialScanStats.numScans = mInitPartialScanTotalCount;
+            initialPartialScanStats.numSuccessScans = mInitPartialScanSuccessCount;
+            initialPartialScanStats.numFailureScans = mInitPartialScanFailureCount;
+            initialPartialScanStats.successfulScanChannelCountHistogram =
+                    mInitPartialScanSuccessHistogram.toProto();
+            initialPartialScanStats.failedScanChannelCountHistogram =
+                    mInitPartialScanFailureHistogram.toProto();
+            mWifiLogProto.initPartialScanStats = initialPartialScanStats;
         }
     }
 
@@ -4293,7 +4365,12 @@
             mWifiLogProto.isExternalWifiScorerOn = false;
             mWifiOffMetrics.clear();
             mSoftApConfigLimitationMetrics.clear();
-
+            //Initial partial scan metrics
+            mInitPartialScanTotalCount = 0;
+            mInitPartialScanSuccessCount = 0;
+            mInitPartialScanFailureCount = 0;
+            mInitPartialScanSuccessHistogram.clear();
+            mInitPartialScanFailureHistogram.clear();
         }
     }
 
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index 4e006a2..7f62085 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -29,10 +29,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Protocol;
 import com.android.server.wifi.MboOceController.BtmFrameData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
 import com.android.server.wifi.hotspot2.AnqpEvent;
 import com.android.server.wifi.hotspot2.IconEvent;
 import com.android.server.wifi.hotspot2.WnmData;
-import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index 271bbef..26e6023 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -645,11 +645,11 @@
                 return;
             }
             if (Objects.equals(mActiveSpecificNetworkRequest, networkRequest)) {
-                Log.i(TAG, "App released request, cancelling "
+                Log.i(TAG, "App released active request, cancelling "
                         + mActiveSpecificNetworkRequest);
                 teardownForActiveRequest();
             } else if (Objects.equals(mConnectedSpecificNetworkRequest, networkRequest)) {
-                Log.i(TAG, "App released request, cancelling "
+                Log.i(TAG, "App released connected request, cancelling "
                         + mConnectedSpecificNetworkRequest);
                 teardownForConnectedNetwork();
             } else {
@@ -985,6 +985,10 @@
 
     // Invoked at the termination of current active request processing.
     private void teardownForActiveRequest() {
+        if (mPendingConnectionSuccess) {
+            Log.i(TAG, "Disconnecting from network on reset");
+            disconnectAndRemoveNetworkFromWifiConfigManager(mUserSelectedNetwork);
+        }
         cleanupActiveRequest();
         // ensure there is no connected request in progress.
         if (mConnectedSpecificNetworkRequest == null) {
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index d29d384..28cf627 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -59,7 +59,6 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.server.wifi.util.ExternalCallbackTracker;
 import com.android.server.wifi.util.LruConnectionTracker;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.wifi.resources.R;
 
@@ -106,22 +105,6 @@
     public static final String EXTRA_UID =
             "com.android.server.wifi.extra.NetworkSuggestion.UID";
 
-    @VisibleForTesting
-    public static final String EXTRA_CARRIER_NAME =
-            "com.android.server.wifi.extra.NetworkSuggestion.CARRIER_NAME";
-    @VisibleForTesting
-    public static final String EXTRA_CARRIER_ID =
-            "com.android.server.wifi.extra.NetworkSuggestion.CARRIER_ID";
-
-    /** Intent when user tapped action button to allow the app. */
-    @VisibleForTesting
-    public static final String NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION =
-            "com.android.server.wifi.action.NetworkSuggestion.USER_ALLOWED_CARRIER";
-    /** Intent when user tapped action button to disallow the app. */
-    @VisibleForTesting
-    public static final String NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION =
-            "com.android.server.wifi.action.NetworkSuggestion.USER_DISALLOWED_CARRIER";
-
     /**
      * Limit number of hidden networks attach to scan
      */
@@ -140,7 +123,7 @@
     private final WifiMetrics mWifiMetrics;
     private final WifiInjector mWifiInjector;
     private final FrameworkFacade mFrameworkFacade;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private final WifiKeyStore mWifiKeyStore;
     // Keep order of network connection.
     private final LruConnectionTracker mLruConnectionTracker;
@@ -362,7 +345,10 @@
     private final HashMap<String, ExternalCallbackTracker<ISuggestionConnectionStatusListener>>
             mSuggestionStatusListenerPerApp = new HashMap<>();
 
-    private final Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap = new HashMap<>();
+    /**
+     * Store the suggestion update listeners.
+     */
+    private final List<OnSuggestionUpdateListener> mListeners = new ArrayList<>();
 
     /**
      * Intent filter for processing notification actions.
@@ -483,35 +469,6 @@
         }
     }
 
-    /**
-     * Module to interact with the wifi config store.
-     */
-    private class ImsiProtectionExemptionDataSource implements
-            ImsiPrivacyProtectionExemptionStoreData.DataSource {
-        @Override
-        public Map<Integer, Boolean> toSerialize() {
-            // Clear the flag after writing to disk.
-            // TODO(b/115504887): Don't reset the flag on write failure.
-            mHasNewDataToSerialize = false;
-            return mImsiPrivacyProtectionExemptionMap;
-        }
-
-        @Override
-        public void fromDeserialized(Map<Integer, Boolean> imsiProtectionExemptionMap) {
-            mImsiPrivacyProtectionExemptionMap.putAll(imsiProtectionExemptionMap);
-        }
-
-        @Override
-        public void reset() {
-            mImsiPrivacyProtectionExemptionMap.clear();
-        }
-
-        @Override
-        public boolean hasNewDataToSerialize() {
-            return mHasNewDataToSerialize;
-        }
-    }
-
     private void handleUserAllowAction(int uid, String packageName) {
         Log.i(TAG, "User clicked to allow app");
         // Set the user approved flag.
@@ -534,59 +491,23 @@
         mUserApprovalUiActive = false;
     }
 
-    private void handleUserAllowCarrierExemptionAction(String carrierName, int carrierId) {
-        Log.i(TAG, "User clicked to allow carrier:" + carrierName);
-        setHasUserApprovedImsiPrivacyExemptionForCarrier(true, carrierId);
-        mUserApprovalUiActive = false;
-    }
-
-    private void handleUserDisallowCarrierExemptionAction(String carrierName, int carrierId) {
-        Log.i(TAG, "User clicked to disallow carrier:" + carrierName);
-        setHasUserApprovedImsiPrivacyExemptionForCarrier(false, carrierId);
-        mUserApprovalUiActive = false;
-    }
-
     private final BroadcastReceiver mBroadcastReceiver =
             new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
                     String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
-                    String carrierName = intent.getStringExtra(EXTRA_CARRIER_NAME);
                     int uid = intent.getIntExtra(EXTRA_UID, -1);
-                    int carrierId = intent.getIntExtra(EXTRA_CARRIER_ID, -1);
-
+                    if (packageName == null || uid == -1) {
+                        Log.e(TAG, "No package name or uid found in intent");
+                        return;
+                    }
                     switch (intent.getAction()) {
                         case NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION:
-                            if (packageName == null || uid == -1) {
-                                Log.e(TAG, "No package name or uid found in intent");
-                                return;
-                            }
                             handleUserAllowAction(uid, packageName);
                             break;
                         case NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION:
-                            if (packageName == null || uid == -1) {
-                                Log.e(TAG, "No package name or uid found in intent");
-                                return;
-                            }
                             handleUserDisallowAction(uid, packageName);
                             break;
-                        case NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION:
-                            if (carrierName == null || carrierId == -1) {
-                                Log.e(TAG, "No carrier name or carrier id found in intent");
-                                return;
-                            }
-                            Log.i(TAG, "User clicked to allow carrier");
-                            sendImsiPrivacyConfirmationDialog(carrierName, carrierId);
-                            // Collapse the notification bar
-                            mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-                            break;
-                        case NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION:
-                            if (carrierName == null || carrierId == -1) {
-                                Log.e(TAG, "No carrier name or carrier id found in intent");
-                                return;
-                            }
-                            handleUserDisallowCarrierExemptionAction(carrierName, carrierId);
-                            break;
                         case NOTIFICATION_USER_DISMISSED_INTENT_ACTION:
                             handleUserDismissAction();
                             return; // no need to cancel a dismissed notification, return.
@@ -599,10 +520,33 @@
                 }
             };
 
+    /**
+     * Interface for other modules to listen to the suggestion updated events.
+     */
+    public interface OnSuggestionUpdateListener {
+        /**
+         * Invoked on suggestion being added or updated.
+         */
+        void onSuggestionsAddedOrUpdated(@NonNull List<WifiNetworkSuggestion> addedSuggestions);
+        /**
+         * Invoked on suggestion being removed.
+         */
+        void onSuggestionsRemoved(@NonNull List<WifiNetworkSuggestion> removedSuggestions);
+    }
+
+    private final class UserApproveCarrierListener implements
+            WifiCarrierInfoManager.OnUserApproveCarrierListener {
+
+        @Override
+        public void onUserAllowed(int carrierId) {
+            restoreInitialAutojoinForCarrierId(carrierId);
+        }
+    }
+
     public WifiNetworkSuggestionsManager(WifiContext context, Handler handler,
             WifiInjector wifiInjector, WifiPermissionsUtil wifiPermissionsUtil,
             WifiConfigManager wifiConfigManager, WifiConfigStore wifiConfigStore,
-            WifiMetrics wifiMetrics, TelephonyUtil telephonyUtil,
+            WifiMetrics wifiMetrics, WifiCarrierInfoManager wifiCarrierInfoManager,
             WifiKeyStore keyStore, LruConnectionTracker lruConnectionTracker) {
         mContext = context;
         mResources = context.getResources();
@@ -618,22 +562,21 @@
         mWifiPermissionsUtil = wifiPermissionsUtil;
         mWifiConfigManager = wifiConfigManager;
         mWifiMetrics = wifiMetrics;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mWifiKeyStore = keyStore;
 
         // register the data store for serializing/deserializing data.
         wifiConfigStore.registerStoreData(
                 wifiInjector.makeNetworkSuggestionStoreData(new NetworkSuggestionDataSource()));
-        wifiConfigStore.registerStoreData(wifiInjector.makeImsiProtectionExemptionStoreData(
-                new ImsiProtectionExemptionDataSource()));
+
+        mWifiCarrierInfoManager.addImsiExemptionUserApprovalListener(
+                new UserApproveCarrierListener());
 
         // Register broadcast receiver for UI interactions.
         mIntentFilter = new IntentFilter();
         mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION);
         mIntentFilter.addAction(NOTIFICATION_USER_DISMISSED_INTENT_ACTION);
-        mIntentFilter.addAction(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION);
-        mIntentFilter.addAction(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION);
 
         mContext.registerReceiver(mBroadcastReceiver, mIntentFilter, null, handler);
         mLruConnectionTracker = lruConnectionTracker;
@@ -871,7 +814,8 @@
             return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED;
         }
 
-        int carrierId = mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(packageName);
+        int carrierId = mWifiCarrierInfoManager
+                .getCarrierIdForPackageWithCarrierPrivileges(packageName);
         final String activeScorerPackage = mNetworkScoreManager.getActiveScorerPackage();
         PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName);
         if (perAppInfo == null) {
@@ -928,9 +872,10 @@
             // If network has no IMSI protection and user didn't approve exemption, make it initial
             // auto join disabled
             if (isSimBasedSuggestion(ewns)) {
-                int subId = mTelephonyUtil.getMatchingSubId(getCarrierIdFromSuggestion(ewns));
-                if (!(mTelephonyUtil.requiresImsiEncryption(subId)
-                        || hasUserApprovedImsiPrivacyExemptionForCarrier(
+                int subId = mWifiCarrierInfoManager
+                        .getMatchingSubId(getCarrierIdFromSuggestion(ewns));
+                if (!(mWifiCarrierInfoManager.requiresImsiEncryption(subId)
+                        || mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(
                         getCarrierIdFromSuggestion(ewns)))) {
                     ewns.isAutojoinEnabled = false;
                 }
@@ -964,6 +909,9 @@
             perAppInfo.extNetworkSuggestions.remove(ewns);
             perAppInfo.extNetworkSuggestions.add(ewns);
         }
+        for (OnSuggestionUpdateListener listener : mListeners) {
+            listener.onSuggestionsAddedOrUpdated(networkSuggestions);
+        }
         // Update the max size for this app.
         perAppInfo.maxSize = Math.max(perAppInfo.extNetworkSuggestions.size(), perAppInfo.maxSize);
         saveToStore();
@@ -1010,7 +958,7 @@
     private boolean validateCarrierNetworkSuggestions(
             List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) {
         if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)
-                || mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(packageName)
+                || mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(packageName)
                 != TelephonyManager.UNKNOWN_CARRIER_ID) {
             return true;
         }
@@ -1059,11 +1007,11 @@
             @NonNull String packageName,
             @NonNull PerAppInfo perAppInfo) {
         // Get internal suggestions
-        Set<ExtendedWifiNetworkSuggestion> removingSuggestions =
+        Set<ExtendedWifiNetworkSuggestion> removingExtSuggestions =
                 new HashSet<>(perAppInfo.extNetworkSuggestions);
         if (!extNetworkSuggestions.isEmpty()) {
             // Keep the internal suggestions need to remove.
-            removingSuggestions.retainAll(extNetworkSuggestions);
+            removingExtSuggestions.retainAll(extNetworkSuggestions);
             perAppInfo.extNetworkSuggestions.removeAll(extNetworkSuggestions);
         } else {
             // empty list is used to clear everything for the app. Store a copy for use below.
@@ -1078,7 +1026,8 @@
             stopTrackingAppOpsChange(packageName);
         }
         // Clear the cache.
-        for (ExtendedWifiNetworkSuggestion ewns : removingSuggestions) {
+        List<WifiNetworkSuggestion> removingSuggestions = new ArrayList<>();
+        for (ExtendedWifiNetworkSuggestion ewns : removingExtSuggestions) {
             if (ewns.wns.passpointConfiguration != null) {
                 // Clear the Passpoint config.
                 mWifiInjector.getPasspointManager().removeProvider(
@@ -1092,9 +1041,13 @@
                 }
                 removeFromScanResultMatchInfoMapAndRemoveRelatedScoreCard(ewns);
             }
+            removingSuggestions.add(ewns.wns);
+        }
+        for (OnSuggestionUpdateListener listener : mListeners) {
+            listener.onSuggestionsRemoved(removingSuggestions);
         }
         // Disconnect suggested network if connected
-        removeFromConfigManagerIfServingNetworkSuggestionRemoved(removingSuggestions);
+        removeFromConfigManagerIfServingNetworkSuggestionRemoved(removingExtSuggestions);
     }
 
     /**
@@ -1179,7 +1132,6 @@
             iter.remove();
         }
         mSuggestionStatusListenerPerApp.clear();
-        mImsiPrivacyProtectionExemptionMap.clear();
         saveToStore();
         Log.i(TAG, "Cleared all internal state");
     }
@@ -1210,46 +1162,25 @@
     }
 
     /**
-     * Clear the Imsi Privacy Exemption user approval info the target carrier.
-     */
-    public void clearImsiPrivacyExemptionForCarrier(int carrierId) {
-        mImsiPrivacyProtectionExemptionMap.remove(carrierId);
-        saveToStore();
-    }
-
-    /**
-     * Check if carrier have user approved exemption for IMSI protection
-     */
-    public boolean hasUserApprovedImsiPrivacyExemptionForCarrier(int carrierId) {
-        return  mImsiPrivacyProtectionExemptionMap.getOrDefault(carrierId, false);
-    }
-
-    /**
-     * Enable or disable exemption on IMSI protection.
-     */
-    public void setHasUserApprovedImsiPrivacyExemptionForCarrier(boolean approved, int carrierId) {
-        if (mVerboseLoggingEnabled) {
-            Log.v(TAG, "Setting Imsi privacy exemption for carrier " + carrierId
-                    + (approved ? " approved" : " not approved"));
-        }
-        mImsiPrivacyProtectionExemptionMap.put(carrierId, approved);
-        // If user approved the exemption restore to initial auto join configure.
-        if (approved) {
-            restoreInitialAutojoinForCarrierId(carrierId);
-        }
-        saveToStore();
-    }
-
-    /**
      * When user approve the IMSI protection exemption for carrier, restore the initial auto join
      * configure. If user already change it to enabled, keep that choice.
      */
     private void restoreInitialAutojoinForCarrierId(int carrierId) {
         for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) {
             for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) {
-                if (isSimBasedSuggestion(ewns)
-                        && getCarrierIdFromSuggestion(ewns) == carrierId) {
-                    ewns.isAutojoinEnabled |= ewns.wns.isInitialAutoJoinEnabled;
+                if (!(isSimBasedSuggestion(ewns)
+                        && getCarrierIdFromSuggestion(ewns) == carrierId)) {
+                    continue;
+                }
+                if (mVerboseLoggingEnabled) {
+                    Log.v(TAG, "Restore auto-join for suggestion: " + ewns);
+                }
+                ewns.isAutojoinEnabled |= ewns.wns.isInitialAutoJoinEnabled;
+                // Restore passpoint provider auto join.
+                if (ewns.wns.passpointConfiguration != null) {
+                    mWifiInjector.getPasspointManager()
+                            .enableAutojoin(ewns.wns.passpointConfiguration.getUniqueId(),
+                                    null, ewns.isAutojoinEnabled);
                 }
             }
         }
@@ -1402,83 +1333,6 @@
         mUserApprovalUiActive = true;
     }
 
-    private void sendImsiPrivacyNotification(@NonNull String carrierName, int carrierId) {
-        Notification.Action userAllowAppNotificationAction =
-                new Notification.Action.Builder(null,
-                        mResources.getText(R.string
-                                .wifi_suggestion_action_allow_imsi_privacy_exemption_carrier),
-                        getPrivateBroadcast(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                                Pair.create(EXTRA_CARRIER_NAME, carrierName),
-                                Pair.create(EXTRA_CARRIER_ID, carrierId)))
-                        .build();
-        Notification.Action userDisallowAppNotificationAction =
-                new Notification.Action.Builder(null,
-                        mResources.getText(R.string
-                                .wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier),
-                        getPrivateBroadcast(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION,
-                                Pair.create(EXTRA_CARRIER_NAME, carrierName),
-                                Pair.create(EXTRA_CARRIER_ID, carrierId)))
-                        .build();
-
-        Notification notification = mFrameworkFacade.makeNotificationBuilder(
-                mContext, WifiService.NOTIFICATION_NETWORK_STATUS)
-                .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
-                        com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range))
-                .setTicker(mResources.getString(
-                        R.string.wifi_suggestion_imsi_privacy_title, carrierName))
-                .setContentTitle(mResources.getString(
-                        R.string.wifi_suggestion_imsi_privacy_title, carrierName))
-                .setStyle(new Notification.BigTextStyle()
-                        .bigText(mResources.getString(
-                                R.string.wifi_suggestion_imsi_privacy_content)))
-                .setDeleteIntent(getPrivateBroadcast(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
-                        Pair.create(EXTRA_CARRIER_NAME, carrierName),
-                        Pair.create(EXTRA_CARRIER_ID, carrierId)))
-                .setShowWhen(false)
-                .setLocalOnly(true)
-                .setColor(mResources.getColor(android.R.color.system_notification_accent_color,
-                        mContext.getTheme()))
-                .addAction(userDisallowAppNotificationAction)
-                .addAction(userAllowAppNotificationAction)
-                .build();
-
-        // Post the notification.
-        mNotificationManager.notify(
-                SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE, notification);
-        mUserApprovalUiActive = true;
-    }
-
-    private void sendImsiPrivacyConfirmationDialog(@NonNull String carrierName, int carrierId) {
-        AlertDialog dialog = mFrameworkFacade.makeAlertDialogBuilder(mContext)
-                .setTitle(mResources.getString(
-                        R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title))
-                .setMessage(mResources.getString(
-                        R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content,
-                        carrierName))
-                .setPositiveButton(mResources.getText(
-                        R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation),
-                        (d, which) -> mHandler.post(
-                                () -> handleUserAllowCarrierExemptionAction(
-                                        carrierName, carrierId)))
-                .setNegativeButton(mResources.getText(
-                        R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation),
-                        (d, which) -> mHandler.post(
-                                () -> handleUserDisallowCarrierExemptionAction(
-                                        carrierName, carrierId)))
-                .setOnDismissListener(
-                        (d) -> mHandler.post(this::handleUserDismissAction))
-                .setOnCancelListener(
-                        (d) -> mHandler.post(this::handleUserDismissAction))
-                .create();
-        dialog.setCanceledOnTouchOutside(false);
-        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        dialog.getWindow().addSystemFlags(
-                WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
-        dialog.show();
-        mUserApprovalUiActive = true;
-    }
-
-
     /**
      * Send user approval notification if the app is not approved
      * @param packageName app package name
@@ -1503,24 +1357,6 @@
         return true;
     }
 
-    /**
-     * Send notification for exemption of IMSI protection if user never made choice before.
-     */
-    private void sendImsiProtectionExemptionNotificationIfRequired(int carrierId) {
-        int subId = mTelephonyUtil.getMatchingSubId(carrierId);
-        if (mTelephonyUtil.requiresImsiEncryption(subId)) {
-            return;
-        }
-        if (mImsiPrivacyProtectionExemptionMap.containsKey(carrierId)) {
-            return;
-        }
-        if (mUserApprovalUiActive) {
-            return;
-        }
-        Log.i(TAG, "Sending IMSI protection notification for " + carrierId);
-        sendImsiPrivacyNotification(mTelephonyUtil.getCarrierNameforSubId(subId), carrierId);
-    }
-
     private @Nullable Set<ExtendedWifiNetworkSuggestion>
             getNetworkSuggestionsForScanResultMatchInfo(
             @NonNull ScanResultMatchInfo scanResultMatchInfo, @Nullable MacAddress bssid) {
@@ -1570,8 +1406,8 @@
                 continue;
             }
             if (isSimBasedSuggestion(ewns)) {
-                int carrierId = getCarrierIdFromSuggestion(ewns);
-                sendImsiProtectionExemptionNotificationIfRequired(carrierId);
+                mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(
+                        getCarrierIdFromSuggestion(ewns));
             }
             approvedExtNetworkSuggestions.add(ewns);
         }
@@ -1617,8 +1453,8 @@
                 continue;
             }
             if (isSimBasedSuggestion(ewns)) {
-                int carrierId = getCarrierIdFromSuggestion(ewns);
-                sendImsiProtectionExemptionNotificationIfRequired(carrierId);
+                mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(
+                        getCarrierIdFromSuggestion(ewns));
             }
             approvedExtNetworkSuggestions.add(ewns);
         }
@@ -1725,7 +1561,7 @@
      */
     public boolean isPasspointSuggestionSharedWithUser(WifiConfiguration config) {
         if (WifiConfiguration.isMetered(config, null)
-                && mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config)) {
+                && mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config)) {
             return false;
         }
         Set<ExtendedWifiNetworkSuggestion> extendedWifiNetworkSuggestions =
@@ -2052,7 +1888,7 @@
     public void resetCarrierPrivilegedApps() {
         Log.w(TAG, "SIM state is changed!");
         for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) {
-            int carrierId = mTelephonyUtil
+            int carrierId = mWifiCarrierInfoManager
                     .getCarrierIdForPackageWithCarrierPrivileges(appInfo.packageName);
             if (carrierId == appInfo.carrierId) {
                 continue;
@@ -2158,6 +1994,13 @@
     }
 
     /**
+     * Add the suggestion update event listener
+     */
+    public void addOnSuggestionUpdateListener(OnSuggestionUpdateListener listener) {
+        mListeners.add(listener);
+    }
+
+    /**
      * Dump of {@link WifiNetworkSuggestionsManager}.
      */
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java
index 1ec56b4..6af4e8d 100644
--- a/service/java/com/android/server/wifi/WifiShellCommand.java
+++ b/service/java/com/android/server/wifi/WifiShellCommand.java
@@ -111,6 +111,7 @@
     private final WifiServiceImpl mWifiService;
     private final Context mContext;
     private final ConnectivityManager mConnectivityManager;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     WifiShellCommand(WifiInjector wifiInjector, WifiServiceImpl wifiService, Context context) {
         mClientModeImpl = wifiInjector.getClientModeImpl();
@@ -124,6 +125,7 @@
         mWifiService = wifiService;
         mContext = context;
         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+        mWifiCarrierInfoManager = wifiInjector.getWifiCarrierInfoManager();
     }
 
     @Override
@@ -216,7 +218,7 @@
                         return -1;
                     }
                     boolean approved = getNextArgRequiredTrueOrFalse("yes", "no");
-                    mWifiNetworkSuggestionsManager
+                    mWifiCarrierInfoManager
                             .setHasUserApprovedImsiPrivacyExemptionForCarrier(approved, carrierId);
                     return 0;
                 }
@@ -231,7 +233,7 @@
                                 + "- 'carrierId' must be an Integer");
                         return -1;
                     }
-                    boolean hasUserApproved = mWifiNetworkSuggestionsManager
+                    boolean hasUserApproved = mWifiCarrierInfoManager
                             .hasUserApprovedImsiPrivacyExemptionForCarrier(carrierId);
                     pw.println(hasUserApproved ? "yes" : "no");
                     return 0;
@@ -247,7 +249,7 @@
                                 + "- 'carrierId' must be an Integer");
                         return -1;
                     }
-                    mWifiNetworkSuggestionsManager.clearImsiPrivacyExemptionForCarrier(carrierId);
+                    mWifiCarrierInfoManager.clearImsiPrivacyExemptionForCarrier(carrierId);
                     return 0;
                 }
                 case "network-requests-remove-user-approved-access-points": {
@@ -405,11 +407,12 @@
                             countDownLatch.countDown();
                         }
                     };
+                    WifiConfiguration config = buildWifiConfiguration(pw);
                     mWifiService.connect(
-                            buildWifiConfiguration(pw), -1, new Binder(), actionListener,
-                            actionListener.hashCode());
+                            config, -1, new Binder(), actionListener, actionListener.hashCode());
                     // wait for status.
                     countDownLatch.await(500, TimeUnit.MILLISECONDS);
+                    setAutoJoin(pw, config.SSID, config.allowAutojoin);
                     break;
                 }
                 case "add-network": {
@@ -427,11 +430,12 @@
                             countDownLatch.countDown();
                         }
                     };
+                    WifiConfiguration config = buildWifiConfiguration(pw);
                     mWifiService.save(
-                            buildWifiConfiguration(pw), new Binder(), actionListener,
-                            actionListener.hashCode());
+                            config, new Binder(), actionListener, actionListener.hashCode());
                     // wait for status.
                     countDownLatch.await(500, TimeUnit.MILLISECONDS);
+                    setAutoJoin(pw, config.SSID, config.allowAutojoin);
                     break;
                 }
                 case "forget-network": {
@@ -470,9 +474,13 @@
                             pw.println("Wifi is connected to " + info.getSSID());
                             pw.println("WifiInfo: " + info);
                             Network network = mWifiService.getCurrentNetwork();
-                            NetworkCapabilities capabilities =
-                                    mConnectivityManager.getNetworkCapabilities(network);
-                            pw.println("NetworkCapabilities: " + capabilities);
+                            try {
+                                NetworkCapabilities capabilities =
+                                        mConnectivityManager.getNetworkCapabilities(network);
+                                pw.println("NetworkCapabilities: " + capabilities);
+                            } catch (SecurityException e) {
+                                // ignore on unrooted shell.
+                            }
                         } else {
                             pw.println("Wifi is not connected");
                         }
@@ -483,10 +491,12 @@
                     mWifiService.enableVerboseLogging(enabled ? 1 : 0);
                     break;
                 }
-                case "add-suggestion":
+                case "add-suggestion": {
+                    WifiNetworkSuggestion suggestion = buildSuggestion(pw);
                     mWifiService.addNetworkSuggestions(
-                            Arrays.asList(buildSuggestion(pw)), SHELL_PACKAGE_NAME, null);
+                            Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null);
                     break;
+                }
                 case "remove-suggestion": {
                     String ssid = getNextArgRequired();
                     List<WifiNetworkSuggestion> suggestions =
@@ -646,6 +656,8 @@
         while (option != null) {
             if (option.equals("-m")) {
                 configuration.meteredOverride = METERED_OVERRIDE_METERED;
+            } else if (option.equals("-d")) {
+                configuration.allowAutojoin = false;
             } else {
                 pw.println("Ignoring unknown option " + option);
             }
@@ -679,6 +691,8 @@
                 suggestionBuilder.setIsMetered(true);
             } else if (option.equals("-s")) {
                 suggestionBuilder.setCredentialSharedWithUser(true);
+            } else if (option.equals("-d")) {
+                suggestionBuilder.setIsInitialAutojoinEnabled(false);
             } else {
                 pw.println("Ignoring unknown option " + option);
             }
@@ -724,6 +738,23 @@
                 .build();
     }
 
+    private void setAutoJoin(PrintWriter pw, String ssid, boolean allowAutojoin) {
+        // For suggestions, this will work only if the config has already been added
+        // to WifiConfigManager.
+        WifiConfiguration retrievedConfig =
+                mWifiService.getPrivilegedConfiguredNetworks(SHELL_PACKAGE_NAME, null)
+                        .getList()
+                        .stream()
+                        .filter(n -> n.SSID.equals(ssid))
+                        .findAny()
+                        .orElse(null);
+        if (retrievedConfig == null) {
+            pw.println("Cannot retrieve config, autojoin setting skipped.");
+            return;
+        }
+        mWifiService.allowAutojoin(retrievedConfig.networkId, allowAutojoin);
+    }
+
     private int sendLinkProbe(PrintWriter pw) throws InterruptedException {
         // Note: should match WifiNl80211Manager#SEND_MGMT_FRAME_TIMEOUT_MS
         final int sendMgmtFrameTimeoutMs = 1000;
@@ -789,7 +820,7 @@
         pw.println("    Start a new scan");
         pw.println("  list-networks");
         pw.println("    Lists the saved networks");
-        pw.println("  connect-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m]");
+        pw.println("  connect-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d]");
         pw.println("    Connect to a network with provided params and add to saved networks list");
         pw.println("    <ssid> - SSID of the network");
         pw.println("    open|owe|wpa2|wpa3 - Security type of the network.");
@@ -800,7 +831,8 @@
         pw.println("           - 'wpa2' - WPA-2 PSK networks (Most prevalent)");
         pw.println("           - 'wpa3' - WPA-3 PSK networks");
         pw.println("    -m - Mark the network metered.");
-        pw.println("  add-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m]");
+        pw.println("    -d - Mark the network autojoin disabled.");
+        pw.println("  add-network <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-m] [-d]");
         pw.println("    Add/update saved network with provided params");
         pw.println("    <ssid> - SSID of the network");
         pw.println("    open|owe|wpa2|wpa3 - Security type of the network.");
@@ -811,6 +843,7 @@
         pw.println("           - 'wpa2' - WPA-2 PSK networks (Most prevalent)");
         pw.println("           - 'wpa3' - WPA-3 PSK networks");
         pw.println("    -m - Mark the network metered.");
+        pw.println("    -d - Mark the network autojoin disabled.");
         pw.println("  forget-network <networkId>");
         pw.println("    Remove the network mentioned by <networkId>");
         pw.println("        - Use list-networks to retrieve <networkId> for the network");
@@ -818,7 +851,7 @@
         pw.println("    Current wifi status");
         pw.println("  set-verbose-logging enabled|disabled ");
         pw.println("    Set the verbose logging enabled or disabled");
-        pw.println("  add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-m] [-s]");
+        pw.println("  add-suggestion <ssid> open|owe|wpa2|wpa3 [<passphrase>] [-u] [-m] [-s] [-d]");
         pw.println("    Add a network suggestion with provided params");
         pw.println("    Use 'network-suggestions-set-user-approved " + SHELL_PACKAGE_NAME + " yes'"
                 +  " to approve suggestions added via shell (Needs root access)");
@@ -833,6 +866,7 @@
         pw.println("    -u - Mark the suggestion untrusted.");
         pw.println("    -m - Mark the suggestion metered.");
         pw.println("    -s - Share the suggestion with user.");
+        pw.println("    -d - Mark the suggestion autojoin disabled.");
         pw.println("  remove-suggestion <ssid>");
         pw.println("    Remove a network suggestion with provided SSID of the network");
         pw.println("  remove-all-suggestions");
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java
index e7de22f..8400bb5 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java
@@ -21,9 +21,9 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiConfigStore;
 import com.android.server.wifi.WifiKeyStore;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
 import com.android.server.wifi.util.XmlUtil;
 
@@ -77,7 +77,7 @@
     private static final String XML_TAG_IS_TRUSTED = "IsTrusted";
 
     private final WifiKeyStore mKeyStore;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
     private final DataSource mDataSource;
 
     /**
@@ -99,10 +99,10 @@
         void setProviders(List<PasspointProvider> providers);
     }
 
-    PasspointConfigUserStoreData(WifiKeyStore keyStore, TelephonyUtil telephonyUtil,
-            DataSource dataSource) {
+    PasspointConfigUserStoreData(WifiKeyStore keyStore,
+            WifiCarrierInfoManager wifiCarrierInfoManager, DataSource dataSource) {
         mKeyStore = keyStore;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mDataSource = dataSource;
     }
 
@@ -348,7 +348,8 @@
         if (config == null) {
             throw new XmlPullParserException("Missing Passpoint configuration");
         }
-        PasspointProvider provider =  new PasspointProvider(config, mKeyStore, mTelephonyUtil,
+        PasspointProvider provider =  new PasspointProvider(config, mKeyStore,
+                mWifiCarrierInfoManager,
                 providerId, creatorUid, packageName, isFromSuggestion, caCertificateAliases,
                 clientPrivateKeyAndCertificateAlias, remediationCaCertificateAlias,
                 hasEverConnected, shared);
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 14f326e..a702c7e 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -52,6 +52,7 @@
 
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.NetworkUpdateResult;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiConfigManager;
 import com.android.server.wifi.WifiConfigStore;
 import com.android.server.wifi.WifiInjector;
@@ -63,7 +64,6 @@
 import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement;
 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo;
 import com.android.server.wifi.util.InformationElementUtil;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -118,7 +118,7 @@
     private final WifiMetrics mWifiMetrics;
     private final PasspointProvisioner mPasspointProvisioner;
     private final AppOpsManager mAppOps;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     /**
      * Map of package name of an app to the app ops changed listener for the app.
@@ -331,7 +331,7 @@
             PasspointObjectFactory objectFactory, WifiConfigManager wifiConfigManager,
             WifiConfigStore wifiConfigStore,
             WifiMetrics wifiMetrics,
-            TelephonyUtil telephonyUtil) {
+            WifiCarrierInfoManager wifiCarrierInfoManager) {
         mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative,
                 new CallbackHandler(context));
         mWifiInjector = wifiInjector;
@@ -344,9 +344,9 @@
         mWifiConfigManager = wifiConfigManager;
         mWifiMetrics = wifiMetrics;
         mProviderIndex = 0;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigUserStoreData(
-                mKeyStore, mTelephonyUtil, new UserDataSourceHandler()));
+                mKeyStore, mWifiCarrierInfoManager, new UserDataSourceHandler()));
         wifiConfigStore.registerStoreData(objectFactory.makePasspointConfigSharedStoreData(
                 new SharedDataSourceHandler()));
         mPasspointProvisioner = objectFactory.makePasspointProvisioner(context, wifiNative,
@@ -433,10 +433,10 @@
             return false;
         }
 
-        mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config);
+        mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config);
         // Create a provider and install the necessary certificates and keys.
         PasspointProvider newProvider = mObjectFactory.makePasspointProvider(config, mKeyStore,
-                mTelephonyUtil, mProviderIndex++, uid, packageName, isFromSuggestion);
+                mWifiCarrierInfoManager, mProviderIndex++, uid, packageName, isFromSuggestion);
         newProvider.setTrusted(isTrusted);
 
         if (!newProvider.installCertsAndKeys()) {
@@ -1171,7 +1171,7 @@
         // Note that for legacy configuration, the alias for client private key is the same as the
         // alias for the client certificate.
         PasspointProvider provider = new PasspointProvider(passpointConfig, mKeyStore,
-                mTelephonyUtil,
+                mWifiCarrierInfoManager,
                 mProviderIndex++, wifiConfig.creatorUid, null, false,
                 Arrays.asList(enterpriseConfig.getCaCertificateAlias()),
                 enterpriseConfig.getClientCertificateAlias(), null, false, false);
@@ -1226,7 +1226,7 @@
             @NonNull PasspointConfiguration passpointConfiguration,
             @NonNull List<ScanResult> scanResults) {
         PasspointProvider provider = mObjectFactory.makePasspointProvider(passpointConfiguration,
-                null, mTelephonyUtil, 0, 0, null, false);
+                null, mWifiCarrierInfoManager, 0, 0, null, false);
         List<ScanResult> filteredScanResults = new ArrayList<>();
         for (ScanResult scanResult : scanResults) {
             PasspointMatch matchInfo = provider.match(getANQPElements(scanResult),
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
index 70095f0..2ce1b1a 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointObjectFactory.java
@@ -20,10 +20,10 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 
 import com.android.server.wifi.Clock;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiKeyStore;
 import com.android.server.wifi.WifiMetrics;
 import com.android.server.wifi.WifiNative;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import java.security.KeyStore;
 import java.security.KeyStoreException;
@@ -59,23 +59,24 @@
      * @return {@link PasspointProvider}
      */
     public PasspointProvider makePasspointProvider(PasspointConfiguration config,
-            WifiKeyStore keyStore, TelephonyUtil telephonyUtil, long providerId, int creatorUid,
-            String packageName, boolean isFromSuggestion) {
-        return new PasspointProvider(config, keyStore, telephonyUtil, providerId, creatorUid,
-                packageName, isFromSuggestion);
+            WifiKeyStore keyStore, WifiCarrierInfoManager wifiCarrierInfoManager, long providerId,
+            int creatorUid, String packageName, boolean isFromSuggestion) {
+        return new PasspointProvider(config, keyStore, wifiCarrierInfoManager, providerId,
+                creatorUid, packageName, isFromSuggestion);
     }
 
     /**
      * Create a {@link PasspointConfigUserStoreData} instance.
      *
      * @param keyStore Instance of {@link WifiKeyStore}
-     * @param telephonyUtil Instance of {@link TelephonyUtil}
+     * @param wifiCarrierInfoManager Instance of {@link WifiCarrierInfoManager}
      * @param dataSource Passpoint configuration data source
      * @return {@link PasspointConfigUserStoreData}
      */
     public PasspointConfigUserStoreData makePasspointConfigUserStoreData(WifiKeyStore keyStore,
-            TelephonyUtil telephonyUtil, PasspointConfigUserStoreData.DataSource dataSource) {
-        return new PasspointConfigUserStoreData(keyStore, telephonyUtil, dataSource);
+            WifiCarrierInfoManager wifiCarrierInfoManager,
+            PasspointConfigUserStoreData.DataSource dataSource) {
+        return new PasspointConfigUserStoreData(keyStore, wifiCarrierInfoManager, dataSource);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
index 43d6f06..006b8ea 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java
@@ -34,6 +34,7 @@
 import android.util.Pair;
 
 import com.android.server.wifi.IMSIParameter;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiKeyStore;
 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
 import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
@@ -45,7 +46,6 @@
 import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth;
 import com.android.server.wifi.util.ArrayUtils;
 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
@@ -98,7 +98,7 @@
 
     private final int mEAPMethodID;
     private final AuthParam mAuthParam;
-    private final TelephonyUtil mTelephonyUtil;
+    private final WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     private int mBestGuessCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
     private boolean mHasEverConnected;
@@ -108,17 +108,16 @@
     private boolean mVerboseLoggingEnabled;
 
     public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore,
-            TelephonyUtil telephonyUtil, long providerId, int creatorUid, String packageName,
-            boolean isFromSuggestion) {
-        this(config, keyStore, telephonyUtil, providerId, creatorUid, packageName, isFromSuggestion,
-                null, null, null, false, false);
+            WifiCarrierInfoManager wifiCarrierInfoManager, long providerId, int creatorUid,
+            String packageName, boolean isFromSuggestion) {
+        this(config, keyStore, wifiCarrierInfoManager, providerId, creatorUid, packageName,
+                isFromSuggestion, null, null, null, false, false);
     }
 
     public PasspointProvider(PasspointConfiguration config, WifiKeyStore keyStore,
-            TelephonyUtil telephonyUtil, long providerId, int creatorUid, String packageName,
-            boolean isFromSuggestion, List<String> caCertificateAliases,
-            String clientPrivateKeyAndCertificateAlias,
-            String remediationCaCertificateAlias,
+            WifiCarrierInfoManager wifiCarrierInfoManager, long providerId, int creatorUid,
+            String packageName, boolean isFromSuggestion, List<String> caCertificateAliases,
+            String clientPrivateKeyAndCertificateAlias, String remediationCaCertificateAlias,
             boolean hasEverConnected, boolean isShared) {
         // Maintain a copy of the configuration to avoid it being updated by others.
         mConfig = new PasspointConfiguration(config);
@@ -132,7 +131,7 @@
         mHasEverConnected = hasEverConnected;
         mIsShared = isShared;
         mIsFromSuggestion = isFromSuggestion;
-        mTelephonyUtil = telephonyUtil;
+        mWifiCarrierInfoManager = wifiCarrierInfoManager;
         mIsTrusted = true;
 
         // Setup EAP method and authentication parameter based on the credential.
@@ -351,19 +350,19 @@
      * @return true if the carrier ID is updated, otherwise false.
      */
     public boolean tryUpdateCarrierId() {
-        return mTelephonyUtil.tryUpdateCarrierIdForPasspoint(mConfig);
+        return mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(mConfig);
     }
 
     private @Nullable String getMatchingSimImsi() {
         String matchingSIMImsi = null;
         if (mConfig.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) {
-            matchingSIMImsi = mTelephonyUtil
+            matchingSIMImsi = mWifiCarrierInfoManager
                     .getMatchingImsi(mConfig.getCarrierId());
         } else {
             // Get the IMSI and carrier ID of SIM card which match with the IMSI prefix from
             // passpoint profile
-            Pair<String, Integer> imsiCarrierIdPair = mTelephonyUtil.getMatchingImsiCarrierId(
-                    mConfig.getCredential().getSimCredential().getImsi());
+            Pair<String, Integer> imsiCarrierIdPair = mWifiCarrierInfoManager
+                    .getMatchingImsiCarrierId(mConfig.getCredential().getSimCredential().getImsi());
             if (imsiCarrierIdPair != null) {
                 matchingSIMImsi = imsiCarrierIdPair.first;
                 mBestGuessCarrierId = imsiCarrierIdPair.second;
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index 1c9ea37..04682db 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -649,6 +649,15 @@
 
   // Total number of steering requests which include MBO assoc retry delay
   optional int32 num_steering_request_including_mbo_assoc_retry_delay = 181;
+
+  // Total number of scan results from 11ax network
+  optional int32 num_11ax_network_scan_results = 182;
+
+  // Total number of scan results from 6GHz band
+  optional int32 num_6g_network_scan_results = 183;
+
+  // Initial partial scan stats
+  optional InitPartialScanStats init_partial_scan_stats = 184;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -3116,3 +3125,22 @@
   // Rx histogram above 2G
   repeated HistogramBucketInt32 rx_above_2g = 4;
 }
+
+// Initial Partial Scan stats
+message InitPartialScanStats {
+  // Total number of partial scans
+  optional int32 num_scans = 1;
+
+  // Number of instances a partial scan results in finding a network
+  optional int32 num_success_scans = 2;
+
+  // Number of instances a patial scan does not result in finding a network
+  // and a follow up full scan finds a network.
+  optional int32 num_failure_scans = 3;
+
+  // Histogram of number of channels used in a successful partial scan
+  repeated HistogramBucketInt32 successful_scan_channel_count_histogram = 4;
+
+  // Histogram of number of channels used in a failed partial scan
+  repeated HistogramBucketInt32 failed_scan_channel_count_histogram = 5;
+}
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 183e725..be59e5d 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -402,4 +402,9 @@
 
     <!-- Enable WPA2 to WPA3 auto-upgrade offload to capable Driver/Firmware -->
     <bool translatable="false" name="config_wifiSaeUpgradeOffloadEnabled">false</bool>
+
+    <!-- Number of self recoveries to be attempted per hour. Any fatal errors beyond this will
+         cause the wifi stack to turn wifi off and wait for user input.
+         Set to 0 to turn off recovery attempts and always turn off wifi on failures -->
+    <integer translatable="false" name="config_wifiMaxNativeFailureSelfRecoveryPerHour">2</integer>
 </resources>
diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml
index 10653ff..80d8051 100644
--- a/service/res/values/overlayable.xml
+++ b/service/res/values/overlayable.xml
@@ -127,6 +127,7 @@
           <item type="integer" name="config_wifiPollRssiIntervalMilliseconds" />
           <item type="bool" name="config_wifiSaeUpgradeEnabled" />
           <item type="bool" name="config_wifiSaeUpgradeOffloadEnabled" />
+          <item type="integer" name="config_wifiMaxNativeFailureSelfRecoveryPerHour" />
           <!-- Params from config.xml that can be overlayed -->
 
           <!-- Params from strings.xml that can be overlayed -->
diff --git a/tests/wifitests/Android.bp b/tests/wifitests/Android.bp
index 2f3cbad..02b4f7a 100644
--- a/tests/wifitests/Android.bp
+++ b/tests/wifitests/Android.bp
@@ -936,9 +936,9 @@
             "com.android.server.wifi.util.StringUtil",
             "com.android.server.wifi.util.StringUtil$*",
             "com.android.server.wifi.util.StringUtil.**",
-            "com.android.server.wifi.util.TelephonyUtil",
-            "com.android.server.wifi.util.TelephonyUtil$*",
-            "com.android.server.wifi.util.TelephonyUtil.**",
+            "com.android.server.wifi.WifiCarrierInfoManager",
+            "com.android.server.wifi.WifiCarrierInfoManager$*",
+            "com.android.server.wifi.WifiCarrierInfoManager.**",
             "com.android.server.wifi.util.TimedQuotaManager",
             "com.android.server.wifi.util.TimedQuotaManager$*",
             "com.android.server.wifi.util.TimedQuotaManager.**",
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index cd0b0f1..17fc1a7 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -133,7 +133,6 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
 import com.android.server.wifi.util.RssiUtilTest;
 import com.android.server.wifi.util.ScanResultUtil;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 import com.android.wifi.resources.R;
@@ -367,7 +366,7 @@
     IpClientCallbacks mIpClientCallback;
     OsuProvider mOsuProvider;
     WifiConfiguration mConnectedNetwork;
-    TelephonyUtil mTelephonyUtil;
+    WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     @Mock WifiScanner mWifiScanner;
     @Mock SupplicantStateTracker mSupplicantStateTracker;
@@ -542,9 +541,10 @@
         when(mSubscriptionManager.getActiveSubscriptionIdList())
                 .thenReturn(new int[]{DATA_SUBID});
 
-        TelephonyUtil tu = new TelephonyUtil(mTelephonyManager, mSubscriptionManager,
-                mock(FrameworkFacade.class), mock(Context.class), mock(Handler.class));
-        mTelephonyUtil = spy(tu);
+        WifiCarrierInfoManager tu = new WifiCarrierInfoManager(mTelephonyManager,
+                mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
+                mock(WifiContext.class), mock(WifiConfigStore.class), mock(Handler.class));
+        mWifiCarrierInfoManager = spy(tu);
         // static mocking
         mSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
                 .spyStatic(MacAddress.class)
@@ -605,9 +605,9 @@
     private void initializeCmi() throws Exception {
         mCmi = new ClientModeImpl(mContext, mFrameworkFacade, mLooper.getLooper(),
                 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative,
-                mWrongPasswordNotifier, mSarManager, mWifiTrafficPoller,
-                mLinkProbeManager, mBatteryStatsManager, mSupplicantStateTracker,
-                mMboOceController, mTelephonyUtil, mEapFailureNotifier, mSimRequiredNotifier);
+                mWrongPasswordNotifier, mSarManager, mWifiTrafficPoller, mLinkProbeManager,
+                mBatteryStatsManager, mSupplicantStateTracker, mMboOceController,
+                mWifiCarrierInfoManager, mEapFailureNotifier, mSimRequiredNotifier);
         mCmi.start();
         mWifiCoreThread = getCmiHandlerThread(mCmi);
 
@@ -1051,7 +1051,7 @@
         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
         mConnectedNetwork.carrierId = CARRIER_ID_1;
-        doReturn(DATA_SUBID).when(mTelephonyUtil)
+        doReturn(DATA_SUBID).when(mWifiCarrierInfoManager)
                 .getBestMatchSubscriptionId(any(WifiConfiguration.class));
         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
@@ -1078,7 +1078,7 @@
     @Test
     public void testResetSimWhenNonConnectedSimRemoved() throws Exception {
         setupEapSimConnection();
-        doReturn(true).when(mTelephonyUtil).isSimPresent(eq(DATA_SUBID));
+        doReturn(true).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID));
         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
         mLooper.dispatchAll();
@@ -1095,7 +1095,7 @@
     @Test
     public void testResetSimWhenConnectedSimRemoved() throws Exception {
         setupEapSimConnection();
-        doReturn(false).when(mTelephonyUtil).isSimPresent(eq(DATA_SUBID));
+        doReturn(false).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID));
         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
         mLooper.dispatchAll();
@@ -1135,7 +1135,7 @@
                 .mockStatic(SubscriptionManager.class)
                 .startMocking();
         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
-        doReturn(true).when(mTelephonyUtil).isImsiEncryptionInfoAvailable(anyInt());
+        doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
 
         // Initial value should be "not set"
         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
@@ -1191,7 +1191,7 @@
                 .mockStatic(SubscriptionManager.class)
                 .startMocking();
         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
-        doReturn(true).when(mTelephonyUtil).isImsiEncryptionInfoAvailable(anyInt());
+        doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
 
         triggerConnect();
 
@@ -1245,7 +1245,7 @@
                 .mockStatic(SubscriptionManager.class)
                 .startMocking();
         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
-        doReturn(true).when(mTelephonyUtil).isImsiEncryptionInfoAvailable(anyInt());
+        doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
 
         triggerConnect();
 
diff --git a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
index 08076dd..f2ec351 100644
--- a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
@@ -33,8 +33,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.server.wifi.util.TelephonyUtil;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -54,7 +52,8 @@
     @Mock NotificationManager mNotificationManager;
     @Mock FrameworkFacade mFrameworkFacade;
     @Mock Notification mNotification;
-    @Mock TelephonyUtil mTelephonyUtil;
+    @Mock
+    WifiCarrierInfoManager mWifiCarrierInfoManager;
     @Mock WifiConfiguration mWifiConfiguration;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Notification.Builder mNotificationBuilder;
@@ -79,7 +78,7 @@
             .startMocking();
         when(mContext.getSystemService(NotificationManager.class))
                 .thenReturn(mNotificationManager);
-        when(mTelephonyUtil.getBestMatchSubscriptionId(mWifiConfiguration)).thenReturn(0);
+        when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(mWifiConfiguration)).thenReturn(0);
         lenient().when(SubscriptionManager.getResourcesForSubId(eq(mContext), anyInt()))
                 .thenReturn(mResources);
         when(mContext.getResources()).thenReturn(mResources);
@@ -92,7 +91,7 @@
         when(mContext.createPackageContext(anyString(), eq(0))).thenReturn(mContext);
         when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources");
         mEapFailureNotifier =
-                new EapFailureNotifier(mContext, mFrameworkFacade, mTelephonyUtil);
+                new EapFailureNotifier(mContext, mFrameworkFacade, mWifiCarrierInfoManager);
     }
 
     @After
diff --git a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
index f9e05cb..ec2142d 100644
--- a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
@@ -79,7 +79,7 @@
      */
     @Test
     public void verifyStoreFileId() throws Exception {
-        assertEquals(WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS,
+        assertEquals(WifiConfigStore.STORE_FILE_USER_GENERAL,
                 mImsiPrivacyProtectionExemptionStoreData.getStoreFileId());
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
index 4e2eee4..d04076a 100644
--- a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
@@ -253,6 +253,69 @@
                     + "</IpConfiguration>\n"
                     + "</Network>\n";
 
+    /**
+     * Repro'es the scenario in b/153435438.
+     * Network has
+     *  - Valid preSharedKey
+     *  - KeyMgmt set to KeyMgmt.OSEN
+     *  - ConfigKey set to "SSID"NONE
+     */
+    private static final String SINGLE_INVALID_NETWORK_DATA_XML_STRING_FORMAT =
+            "<Network>\n"
+                    + "<WifiConfiguration>\n"
+                    + "<string name=\"ConfigKey\">%s</string>\n"
+                    + "<string name=\"SSID\">%s</string>\n"
+                    + "<string name=\"PreSharedKey\">%s</string>\n"
+                    + "<null name=\"WEPKeys\" />\n"
+                    + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
+                    + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
+                    + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
+                    + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">20</byte-array>\n"
+                    + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
+                    + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
+                    + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
+                    + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
+                    + "<byte-array name=\"AllowedGroupMgmtCiphers\" num=\"0\"></byte-array>\n"
+                    + "<byte-array name=\"AllowedSuiteBCiphers\" num=\"0\"></byte-array>\n"
+                    + "<boolean name=\"Shared\" value=\"%s\" />\n"
+                    + "<boolean name=\"AutoJoinEnabled\" value=\"true\" />\n"
+                    + "<boolean name=\"Trusted\" value=\"true\" />\n"
+                    + "<null name=\"BSSID\" />\n"
+                    + "<int name=\"Status\" value=\"2\" />\n"
+                    + "<null name=\"FQDN\" />\n"
+                    + "<null name=\"ProviderFriendlyName\" />\n"
+                    + "<null name=\"LinkedNetworksList\" />\n"
+                    + "<null name=\"DefaultGwMacAddress\" />\n"
+                    + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
+                    + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
+                    + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
+                    + "<int name=\"MeteredOverride\" value=\"0\" />\n"
+                    + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
+                    + "<int name=\"NumAssociation\" value=\"0\" />\n"
+                    + "<int name=\"CreatorUid\" value=\"%d\" />\n"
+                    + "<string name=\"CreatorName\">%s</string>\n"
+                    + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
+                    + "<null name=\"LastUpdateName\" />\n"
+                    + "<int name=\"LastConnectUid\" value=\"0\" />\n"
+                    + "<boolean name=\"IsLegacyPasspointConfig\" value=\"false\" />\n"
+                    + "<long-array name=\"RoamingConsortiumOIs\" num=\"0\" />\n"
+                    + "<string name=\"RandomizedMacAddress\">%s</string>\n"
+                    + "<int name=\"MacRandomizationSetting\" value=\"1\" />\n"
+                    + "<int name=\"CarrierId\" value=\"-1\" />\n"
+                    + "<boolean name=\"IsMostRecentlyConnected\" value=\"false\" />\n"
+                    + "</WifiConfiguration>\n"
+                    + "<NetworkStatus>\n"
+                    + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
+                    + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
+                    + "<null name=\"ConnectChoice\" />\n"
+                    + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
+                    + "</NetworkStatus>\n"
+                    + "<IpConfiguration>\n"
+                    + "<string name=\"IpAssignment\">UNASSIGNED</string>\n"
+                    + "<string name=\"ProxySettings\">UNASSIGNED</string>\n"
+                    + "</IpConfiguration>\n"
+                    + "</Network>\n";
+
     // We use {@link NetworkListSharedStoreData} instance because {@link NetworkListStoreData} is
     // abstract.
     private NetworkListSharedStoreData mNetworkListSharedStoreData;
@@ -714,4 +777,36 @@
         byte[] output2 = serializeData();
         assertArrayEquals(output2, output1);
     }
+
+    /**
+     * Verify that we parse out a badly formed WifiConfiguration saved on the device because
+     * our previous validation logic did not catch it.
+     *
+     * See b/153435438#comment26 for the exact problem.
+     */
+    @Test
+    public void parseNetworkWithInvalidConfigKeyAndKeyMmt() throws Exception {
+        // Valid psk network (that we should recreate after deserialization)
+        WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork();
+        pskNetwork.setRandomizedMacAddress(TEST_RANDOMIZED_MAC);
+        pskNetwork.creatorName = TEST_CREATOR_NAME;
+        String invalidConfigKey = pskNetwork.getKey();
+        invalidConfigKey.replace("WPA_PSK", "NONE");
+        // XML data has 2 things that needs to be corrected:
+        // - ConfigKey is set to "SSID"NONE instead of "SSID"WPA_PSK
+        // - KeyMgmt has KeyMgmt.OSEN bit set instead of KeyMgmt.WPA_PSK
+        byte[] xmlData = String.format(SINGLE_INVALID_NETWORK_DATA_XML_STRING_FORMAT,
+                invalidConfigKey,
+                pskNetwork.SSID.replaceAll("\"", "&quot;"),
+                pskNetwork.preSharedKey.replaceAll("\"", "&quot;"),
+                pskNetwork.shared, pskNetwork.creatorUid,
+                pskNetwork.creatorName, pskNetwork.getRandomizedMacAddress())
+                .getBytes(StandardCharsets.UTF_8);
+        List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData);
+        assertEquals(1, deserializedNetworks.size());
+
+        WifiConfiguration deserializedPskNetwork = deserializedNetworks.get(0);
+        WifiConfigurationTestUtil.assertConfigurationEqualForConfigStore(
+                pskNetwork, deserializedPskNetwork);
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
index f8084e3..94b14ec 100644
--- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
@@ -39,7 +39,6 @@
 import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion;
 import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo;
 import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -74,7 +73,8 @@
     private @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     private @Mock PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
     private @Mock Clock mClock;
-    private @Mock TelephonyUtil mTelephonyUtil;
+    private @Mock
+    WifiCarrierInfoManager mWifiCarrierInfoManager;
     private NetworkSuggestionNominator mNetworkSuggestionNominator;
 
     /** Sets up test. */
@@ -83,7 +83,7 @@
         MockitoAnnotations.initMocks(this);
         mNetworkSuggestionNominator = new NetworkSuggestionNominator(
                 mWifiNetworkSuggestionsManager, mWifiConfigManager, mPasspointNetworkNominateHelper,
-                new LocalLog(100), mTelephonyUtil);
+                new LocalLog(100), mWifiCarrierInfoManager);
     }
 
     /**
@@ -773,8 +773,9 @@
         eapSimConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
         eapSimConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
         eapSimConfig.carrierId = TEST_CARRIER_ID;
-        when(mTelephonyUtil.getBestMatchSubscriptionId(eapSimConfig)).thenReturn(TEST_SUB_ID);
-        when(mTelephonyUtil.isSimPresent(TEST_SUB_ID)).thenReturn(false);
+        when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(eapSimConfig))
+                .thenReturn(TEST_SUB_ID);
+        when(mWifiCarrierInfoManager.isSimPresent(TEST_SUB_ID)).thenReturn(false);
         // Link the scan result with suggestions.
         linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions);
         // setup config manager interactions.
@@ -818,10 +819,11 @@
         eapSimConfig.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
         eapSimConfig.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
         eapSimConfig.carrierId = TEST_CARRIER_ID;
-        when(mTelephonyUtil.getBestMatchSubscriptionId(eapSimConfig)).thenReturn(TEST_SUB_ID);
-        when(mTelephonyUtil.isSimPresent(TEST_SUB_ID)).thenReturn(true);
-        when(mTelephonyUtil.requiresImsiEncryption(TEST_SUB_ID)).thenReturn(true);
-        when(mTelephonyUtil.isImsiEncryptionInfoAvailable(TEST_SUB_ID)).thenReturn(false);
+        when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(eapSimConfig))
+                .thenReturn(TEST_SUB_ID);
+        when(mWifiCarrierInfoManager.isSimPresent(TEST_SUB_ID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUB_ID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(TEST_SUB_ID)).thenReturn(false);
         // Link the scan result with suggestions.
         linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions);
         // setup config manager interactions.
@@ -954,7 +956,7 @@
                 securities, appInteractions, meteredness, priorities, uids,
                 packageNames, autojoin, shareWithUser);
         suggestions[0].wns.wifiConfiguration.meteredHint = true;
-        when(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(any())).thenReturn(true);
+        when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(any())).thenReturn(true);
         // Link the scan result with suggestions.
         linkScanDetailsWithNetworkSuggestions(scanDetails, suggestions);
 
diff --git a/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
index 1a56fbb..839b2e5 100644
--- a/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java
@@ -29,7 +29,7 @@
 import com.android.server.wifi.WifiNetworkSelector.NetworkNominator.OnConnectableListener;
 import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
 import com.android.server.wifi.hotspot2.PasspointNetworkNominateHelper;
-import com.android.server.wifi.util.TelephonyUtil;
+import com.android.server.wifi.util.WifiPermissionsUtil;
 
 import org.junit.After;
 import org.junit.Before;
@@ -53,9 +53,14 @@
         MockitoAnnotations.initMocks(this);
         mLocalLog = new LocalLog(512);
         mSavedNetworkNominator = new SavedNetworkNominator(mWifiConfigManager,
-                mPasspointNetworkNominateHelper, mLocalLog, mTelephonyUtil);
-        when(mTelephonyUtil.isSimPresent(anyInt())).thenReturn(true);
-        when(mTelephonyUtil.getBestMatchSubscriptionId(any())).thenReturn(1);
+                mPasspointNetworkNominateHelper, mLocalLog, mWifiCarrierInfoManager,
+                mWifiPermissionsUtil);
+        when(mWifiCarrierInfoManager.isSimPresent(anyInt())).thenReturn(true);
+        when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any())).thenReturn(VALID_SUBID);
+        when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
+        when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(VALID_SUBID);
+
     }
 
     /** Cleans up test. */
@@ -66,16 +71,19 @@
 
     private ArgumentCaptor<WifiConfiguration> mWifiConfigurationArgumentCaptor =
             ArgumentCaptor.forClass(WifiConfiguration.class);
+    private static final int VALID_SUBID = 10;
     private static final int INVALID_SUBID = 1;
     private static final int TEST_CARRIER_ID = 100;
     private static final int RSSI_LEVEL = -50;
+    private static final int TEST_UID = 1001;
 
     private SavedNetworkNominator mSavedNetworkNominator;
     @Mock private WifiConfigManager mWifiConfigManager;
     @Mock private Clock mClock;
     @Mock private OnConnectableListener mOnConnectableListener;
-    @Mock private TelephonyUtil mTelephonyUtil;
+    @Mock private WifiCarrierInfoManager mWifiCarrierInfoManager;
     @Mock private PasspointNetworkNominateHelper mPasspointNetworkNominateHelper;
+    @Mock private WifiPermissionsUtil mWifiPermissionsUtil;
     private LocalLog mLocalLog;
 
     /**
@@ -122,9 +130,8 @@
         WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
         savedConfigs[0].carrierId = TEST_CARRIER_ID;
         // SIM is absent
-        when(mTelephonyUtil.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
-                .thenReturn(INVALID_SUBID);
-        when(mTelephonyUtil.isSimPresent(eq(INVALID_SUBID))).thenReturn(false);
+        when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(INVALID_SUBID);
+        when(mWifiCarrierInfoManager.isSimPresent(eq(INVALID_SUBID))).thenReturn(false);
 
         mSavedNetworkNominator.nominateNetworks(scanDetails,
                 null, null, true, false, mOnConnectableListener);
@@ -239,7 +246,7 @@
      * Verify if a network is metered and with non-data sim, will not nominate as a candidate.
      */
     @Test
-    public void ignoreNetworksIfMeteredAndFromNonDataSim() {
+    public void testIgnoreNetworksIfMeteredAndFromNonDataSim() {
         String[] ssids = {"\"test1\""};
         String[] bssids = {"6c:f3:7f:ae:8c:f3"};
         int[] freqs = {2470};
@@ -250,14 +257,54 @@
                         freqs, levels, mWifiConfigManager, mClock);
         List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
         WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
-        when(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
+        savedConfigs[0].carrierId = TEST_CARRIER_ID;
+        when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
                 .thenReturn(false);
         mSavedNetworkNominator.nominateNetworks(scanDetails,
                 null, null, true, false, mOnConnectableListener);
         verify(mOnConnectableListener).onConnectable(any(), any());
         reset(mOnConnectableListener);
-        when(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
+        when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(savedConfigs[0]))
                 .thenReturn(true);
         verify(mOnConnectableListener, never()).onConnectable(any(), any());
     }
+
+    /**
+     * Verify a saved network is from app not user, if IMSI privacy protection is not required, will
+     * send notification for user to approve exemption, and not consider as a candidate.
+     */
+    @Test
+    public void testIgnoreNetworksFromAppIfNoImsiProtection() {
+        String[] ssids = {"\"test1\""};
+        String[] bssids = {"6c:f3:7f:ae:8c:f3"};
+        int[] freqs = {2470};
+        int[] levels = {RSSI_LEVEL};
+        when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(any()))
+                .thenReturn(false);
+        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigForEapSimNetwork(ssids, bssids,
+                        freqs, levels, mWifiConfigManager, mClock);
+        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
+        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
+        savedConfigs[0].carrierId = TEST_CARRIER_ID;
+        // Doesn't require Imsi protection and user didn't approved
+        when(mWifiCarrierInfoManager.requiresImsiEncryption(VALID_SUBID)).thenReturn(false);
+        when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
+                .thenReturn(false);
+        mSavedNetworkNominator.nominateNetworks(scanDetails,
+                null, null, true, false, mOnConnectableListener);
+        verify(mOnConnectableListener, never()).onConnectable(any(), any());
+        verify(mWifiCarrierInfoManager)
+                .sendImsiProtectionExemptionNotificationIfRequired(TEST_CARRIER_ID);
+        // Simulate user approved
+        when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
+                .thenReturn(true);
+        mSavedNetworkNominator.nominateNetworks(scanDetails,
+                null, null, true, false, mOnConnectableListener);
+        verify(mOnConnectableListener).onConnectable(any(), any());
+        // If from settings app, will bypass the IMSI check.
+        when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
+                .thenReturn(false);
+        when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java b/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java
index fe8bfd5..3538598 100644
--- a/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SelfRecoveryTest.java
@@ -19,25 +19,39 @@
 import static org.mockito.Mockito.*;
 import static org.mockito.MockitoAnnotations.*;
 
+import android.content.Context;
+
 import androidx.test.filters.SmallTest;
 
+import com.android.wifi.resources.R;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Unit tests for {@link com.android.server.wifi.SelfRecovery}.
  */
 @SmallTest
 public class SelfRecoveryTest extends WifiBaseTest {
+    private static final int DEFAULT_MAX_RECOVERY_PER_HOUR = 2;
     SelfRecovery mSelfRecovery;
+    MockResources mResources;
+    @Mock Context mContext;
     @Mock ActiveModeWarden mActiveModeWarden;
     @Mock Clock mClock;
 
     @Before
     public void setUp() throws Exception {
         initMocks(this);
-        mSelfRecovery = new SelfRecovery(mActiveModeWarden, mClock);
+        mResources = new MockResources();
+        // Default value of 2 recovery per hour.
+        mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour,
+                DEFAULT_MAX_RECOVERY_PER_HOUR);
+        when(mContext.getResources()).thenReturn(mResources);
+        mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock);
     }
 
     /**
@@ -51,7 +65,7 @@
         reset(mActiveModeWarden);
 
         when(mClock.getElapsedSinceBootMillis())
-                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
+                .thenReturn(TimeUnit.HOURS.toMillis(1) + 1);
         mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
         verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
         reset(mActiveModeWarden);
@@ -80,25 +94,16 @@
     }
 
     /**
-     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_HAL_CRASH &
-     * REASON_WIFICOND_CRASH are limited to {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
-     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
+     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE
+     * are limited to {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a
+     * 1 hour time window.
      */
     @Test
     public void testTimeWindowLimiting_typicalUse() {
         when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
         // Fill up the SelfRecovery's restart time window buffer, ensure all the restart triggers
         // aren't ignored
-        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW / 2; i++) {
-            mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
-            verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
-            reset(mActiveModeWarden);
-
-            mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
-            verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
-            reset(mActiveModeWarden);
-        }
-        if ((SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW % 2) == 1) {
+        for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR; i++) {
             mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
             verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
             reset(mActiveModeWarden);
@@ -128,27 +133,46 @@
 
         // now TRAVEL FORWARDS IN TIME and ensure that more restarts can occur
         when(mClock.getElapsedSinceBootMillis())
-                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
+                .thenReturn(TimeUnit.HOURS.toMillis(1) + 1);
         mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
         verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
         reset(mActiveModeWarden);
 
         when(mClock.getElapsedSinceBootMillis())
-                .thenReturn(SelfRecovery.MAX_RESTARTS_TIME_WINDOW_MILLIS + 1);
+                .thenReturn(TimeUnit.HOURS.toMillis(1) + 1);
         mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
         verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
         reset(mActiveModeWarden);
     }
 
     /**
+     * Verifies that invocations of {@link SelfRecovery#trigger(int)} for REASON_WIFI_NATIVE
+     * does not trigger recovery if {@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour}
+     * is set to 0
+     */
+    @Test
+    public void testTimeWindowLimiting_NativeFailureOff() {
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
+        mResources.setInteger(R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour, 0);
+        mSelfRecovery.trigger(SelfRecovery.REASON_WIFINATIVE_FAILURE);
+        verify(mActiveModeWarden, never())
+                .recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE);
+        verify(mActiveModeWarden).recoveryDisableWifi();
+        reset(mActiveModeWarden);
+
+        // Verify L.R.Watchdog can still restart things (It has its own complex limiter)
+        mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
+        verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
+    }
+
+    /**
      * Verifies that invocations of {@link SelfRecovery#trigger(int)} for
      * REASON_LAST_RESORT_WATCHDOG are NOT limited to
-     * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
-     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
+     * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window.
      */
     @Test
     public void testTimeWindowLimiting_lastResortWatchdog_noEffect() {
-        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) {
+        for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) {
             // Verify L.R.Watchdog can still restart things (It has it's own complex limiter)
             mSelfRecovery.trigger(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
             verify(mActiveModeWarden).recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG);
@@ -159,12 +183,11 @@
     /**
      * Verifies that invocations of {@link SelfRecovery#trigger(int)} for
      * REASON_STA_IFACE_DOWN are NOT limited to
-     * {@link SelfRecovery#MAX_RESTARTS_IN_TIME_WINDOW} in a
-     * {@link SelfRecovery#MAX_RESTARTS_TIME_WINDOW_MILLIS} millisecond time window.
+     * {{@link R.integer.config_wifiMaxNativeFailureSelfRecoveryPerHour} in a 1 hour time window.
      */
     @Test
     public void testTimeWindowLimiting_staIfaceDown_noEffect() {
-        for (int i = 0; i < SelfRecovery.MAX_RESTARTS_IN_TIME_WINDOW * 2; i++) {
+        for (int i = 0; i < DEFAULT_MAX_RECOVERY_PER_HOUR * 2; i++) {
             mSelfRecovery.trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
             verify(mActiveModeWarden).recoveryDisableWifi();
             verify(mActiveModeWarden, never()).recoveryRestartWifi(anyInt());
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
index 30c171f..a2a1a45 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiBackupRestoreTest.java
@@ -1020,7 +1020,7 @@
     @Test
     public void testRestoreFromV1_2BackupData() {
         List<WifiConfiguration> configurations = new ArrayList<>();
-        configurations.add(createNetworkForConfigurationWithV1_1Data());
+        configurations.add(createNetworkForConfigurationWithV1_2Data());
 
         byte[] backupData = WIFI_BACKUP_DATA_V1_2.getBytes();
         List<WifiConfiguration> retrievedConfigurations =
diff --git a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
similarity index 64%
rename from tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java
rename to tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
index a07dafb..28bffa1 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,18 +14,27 @@
  * limitations under the License.
  */
 
-package com.android.server.wifi.util;
+package com.android.server.wifi;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION;
+import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION;
+import static com.android.server.wifi.WifiCarrierInfoManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION;
 
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
+import android.app.AlertDialog;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
@@ -42,20 +51,21 @@
 import android.telephony.TelephonyManager;
 import android.util.Base64;
 import android.util.Pair;
+import android.view.Window;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
-import com.android.server.wifi.FrameworkFacade;
-import com.android.server.wifi.WifiBaseTest;
-import com.android.server.wifi.WifiConfigurationTestUtil;
-import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData;
-import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
+import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData;
+import com.android.wifi.resources.R;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
@@ -65,17 +75,18 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 
 /**
- * Unit tests for {@link com.android.server.wifi.util.TelephonyUtil}.
+ * Unit tests for {@link WifiCarrierInfoManager}.
  */
 @SmallTest
-public class TelephonyUtilTest extends WifiBaseTest {
-    private TelephonyUtil mTelephonyUtil;
+public class WifiCarrierInfoManagerTest extends WifiBaseTest {
+    private WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     private static final int DATA_SUBID = 1;
     private static final int NON_DATA_SUBID = 2;
@@ -97,29 +108,34 @@
     private static final String ANONYMOUS_IDENTITY = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
     private static final String CARRIER_NAME = "Google";
 
-    @Mock
-    CarrierConfigManager mCarrierConfigManager;
-    @Mock
-    Context mContext;
-    @Mock
-    FrameworkFacade mFrameworkFacade;
-    @Mock
-    TelephonyManager mTelephonyManager;
-    @Mock
-    TelephonyManager mDataTelephonyManager;
-    @Mock
-    TelephonyManager mNonDataTelephonyManager;
-    @Mock
-    SubscriptionManager mSubscriptionManager;
-    @Mock
-    SubscriptionInfo mDataSubscriptionInfo;
-    @Mock
-    SubscriptionInfo mNonDataSubscriptionInfo;
+    @Mock CarrierConfigManager mCarrierConfigManager;
+    @Mock WifiContext mContext;
+    @Mock Resources mResources;
+    @Mock FrameworkFacade mFrameworkFacade;
+    @Mock TelephonyManager mTelephonyManager;
+    @Mock TelephonyManager mDataTelephonyManager;
+    @Mock TelephonyManager mNonDataTelephonyManager;
+    @Mock SubscriptionManager mSubscriptionManager;
+    @Mock SubscriptionInfo mDataSubscriptionInfo;
+    @Mock SubscriptionInfo mNonDataSubscriptionInfo;
+    @Mock WifiConfigStore mWifiConfigStore;
+    @Mock WifiInjector mWifiInjector;
+    @Mock WifiConfigManager mWifiConfigManager;
+    @Mock ImsiPrivacyProtectionExemptionStoreData mImsiPrivacyProtectionExemptionStoreData;
+    @Mock NotificationManager mNotificationManger;
+    @Mock Notification.Builder mNotificationBuilder;
+    @Mock Notification mNotification;
+    @Mock AlertDialog.Builder mAlertDialogBuilder;
+    @Mock AlertDialog mAlertDialog;
+    @Mock WifiCarrierInfoManager.OnUserApproveCarrierListener mListener;
 
     private List<SubscriptionInfo> mSubInfoList;
 
     MockitoSession mMockingSession = null;
     TestLooper mLooper;
+    private ImsiPrivacyProtectionExemptionStoreData.DataSource mImsiDataSource;
+    private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
+            ArgumentCaptor.forClass(BroadcastReceiver.class);
 
     @Before
     public void setUp() throws Exception {
@@ -127,8 +143,48 @@
         mLooper = new TestLooper();
         when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
                 .thenReturn(mCarrierConfigManager);
-        mTelephonyUtil = new TelephonyUtil(mTelephonyManager, mSubscriptionManager,
-                mFrameworkFacade, mContext, new Handler(mLooper.getLooper()));
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getSystemService(Context.NOTIFICATION_SERVICE))
+                .thenReturn(mNotificationManger);
+        when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources");
+        when(mFrameworkFacade.makeAlertDialogBuilder(any()))
+                .thenReturn(mAlertDialogBuilder);
+        when(mFrameworkFacade.makeNotificationBuilder(any(), anyString()))
+                .thenReturn(mNotificationBuilder);
+        when(mFrameworkFacade.getBroadcast(any(), anyInt(), any(), anyInt()))
+                .thenReturn(mock(PendingIntent.class));
+        when(mAlertDialogBuilder.setTitle(any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setMessage(any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setPositiveButton(any(), any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setNegativeButton(any(), any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setOnDismissListener(any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.setOnCancelListener(any())).thenReturn(mAlertDialogBuilder);
+        when(mAlertDialogBuilder.create()).thenReturn(mAlertDialog);
+        when(mAlertDialog.getWindow()).thenReturn(mock(Window.class));
+        when(mNotificationBuilder.setSmallIcon(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setTicker(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setContentTitle(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setStyle(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setDeleteIntent(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setShowWhen(anyBoolean())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setLocalOnly(anyBoolean())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.setColor(anyInt())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.addAction(any())).thenReturn(mNotificationBuilder);
+        when(mNotificationBuilder.build()).thenReturn(mNotification);
+        when(mWifiInjector.makeImsiProtectionExemptionStoreData(any()))
+                .thenReturn(mImsiPrivacyProtectionExemptionStoreData);
+        when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
+        mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager,
+                mSubscriptionManager, mWifiInjector, mFrameworkFacade, mContext, mWifiConfigStore,
+                new Handler(mLooper.getLooper()));
+        ArgumentCaptor<ImsiPrivacyProtectionExemptionStoreData.DataSource>
+                imsiDataSourceArgumentCaptor =
+                ArgumentCaptor.forClass(ImsiPrivacyProtectionExemptionStoreData.DataSource.class);
+        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any(), any(), any());
+        verify(mWifiInjector).makeImsiProtectionExemptionStoreData(imsiDataSourceArgumentCaptor
+                .capture());
+        mImsiDataSource = imsiDataSourceArgumentCaptor.getValue();
+        assertNotNull(mImsiDataSource);
         mSubInfoList = new ArrayList<>();
         mSubInfoList.add(mDataSubscriptionInfo);
         mSubInfoList.add(mNonDataSubscriptionInfo);
@@ -163,6 +219,32 @@
         when(mNonDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
         when(mSubscriptionManager.getActiveSubscriptionIdList())
                 .thenReturn(new int[]{DATA_SUBID, NON_DATA_SUBID});
+
+        // setup resource strings for IMSI protection notification.
+        when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_title), anyString()))
+                .thenAnswer(s -> "blah" + s.getArguments()[1]);
+        when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_content)))
+                .thenReturn("blah");
+        when(mResources.getText(
+                eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_carrier)))
+                .thenReturn("blah");
+        when(mResources.getText(
+                eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier)))
+                .thenReturn("blah");
+        when(mResources.getString(
+                eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title)))
+                .thenReturn("blah");
+        when(mResources.getString(
+                eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content),
+                anyString())).thenAnswer(s -> "blah" + s.getArguments()[1]);
+        when(mResources.getText(
+                eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation)))
+                .thenReturn("blah");
+        when(mResources.getText(
+                eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation)))
+                .thenReturn("blah");
+        mWifiCarrierInfoManager.addImsiExemptionUserApprovalListener(mListener);
+        mImsiDataSource.fromDeserialized(new HashMap<>());
     }
 
     @After
@@ -222,8 +304,8 @@
         receiver.getValue().onReceive(mContext,
                 new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
 
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
-        assertFalse(mTelephonyUtil.requiresImsiEncryption(NON_DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID));
     }
 
     /**
@@ -242,8 +324,8 @@
         receiver.getValue().onReceive(mContext,
                 new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
 
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(NON_DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID));
 
         when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
                 .thenReturn(generateTestCarrierConfig(false));
@@ -252,8 +334,8 @@
         receiver.getValue().onReceive(mContext,
                 new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
 
-        assertFalse(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
-        assertFalse(mTelephonyUtil.requiresImsiEncryption(NON_DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(NON_DATA_SUBID));
     }
 
     /**
@@ -278,16 +360,16 @@
 
         observer.onChange(false);
 
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
-        assertFalse(mTelephonyUtil.isImsiEncryptionInfoAvailable(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID));
 
         when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN))
                 .thenReturn(mock(ImsiEncryptionInfo.class));
 
         observer.onChange(false);
 
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
-        assertTrue(mTelephonyUtil.isImsiEncryptionInfoAvailable(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID));
     }
 
     /**
@@ -313,8 +395,8 @@
 
         observer.onChange(false);
 
-        assertTrue(mTelephonyUtil.isImsiEncryptionInfoAvailable(DATA_SUBID));
-        assertTrue(mTelephonyUtil.isImsiEncryptionInfoAvailable(NON_DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(NON_DATA_SUBID));
 
         when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN))
                 .thenReturn(null);
@@ -323,8 +405,8 @@
 
         observer.onChange(false);
 
-        assertFalse(mTelephonyUtil.isImsiEncryptionInfoAvailable(DATA_SUBID));
-        assertFalse(mTelephonyUtil.isImsiEncryptionInfoAvailable(NON_DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(NON_DATA_SUBID));
     }
 
     @Test
@@ -341,14 +423,14 @@
                         WifiEnterpriseConfig.Phase2.NONE);
         simConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(simConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(simConfig));
 
         WifiConfiguration peapSimConfig =
                 WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
                         WifiEnterpriseConfig.Phase2.SIM);
         peapSimConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(peapSimConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapSimConfig));
     }
 
     @Test
@@ -365,14 +447,14 @@
                         WifiEnterpriseConfig.Phase2.NONE);
         akaConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(akaConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(akaConfig));
 
         WifiConfiguration peapAkaConfig =
                 WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
                         WifiEnterpriseConfig.Phase2.AKA);
         peapAkaConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(peapAkaConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapAkaConfig));
     }
 
     @Test
@@ -389,14 +471,14 @@
                         WifiEnterpriseConfig.Phase2.NONE);
         akaPConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(akaPConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(akaPConfig));
 
         WifiConfiguration peapAkaPConfig =
                 WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.PEAP,
                         WifiEnterpriseConfig.Phase2.AKA_PRIME);
         peapAkaPConfig.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(peapAkaPConfig));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(peapAkaPConfig));
     }
 
     /**
@@ -434,7 +516,7 @@
                             WifiEnterpriseConfig.Phase2.NONE);
             config.carrierId = DATA_CARRIER_ID;
 
-            assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(config));
+            assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config));
         } finally {
             session.finishMocking();
         }
@@ -470,7 +552,7 @@
                             WifiEnterpriseConfig.Phase2.NONE);
             config.carrierId = DATA_CARRIER_ID;
 
-            assertNull(mTelephonyUtil.getSimIdentity(config));
+            assertNull(mWifiCarrierInfoManager.getSimIdentity(config));
         } finally {
             session.finishMocking();
         }
@@ -490,7 +572,7 @@
                         WifiEnterpriseConfig.Phase2.NONE);
         config.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(config));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config));
     }
 
     @Test
@@ -507,7 +589,7 @@
                         WifiEnterpriseConfig.Phase2.NONE);
         config.carrierId = DATA_CARRIER_ID;
 
-        assertEquals(expectedIdentity, mTelephonyUtil.getSimIdentity(config));
+        assertEquals(expectedIdentity, mWifiCarrierInfoManager.getSimIdentity(config));
     }
 
     @Test
@@ -517,16 +599,16 @@
         when(mDataTelephonyManager.getSimOperator()).thenReturn("32156");
 
         assertEquals(null,
-                mTelephonyUtil.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
+                mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
                         WifiEnterpriseConfig.Eap.TTLS, WifiEnterpriseConfig.Phase2.SIM)));
         assertEquals(null,
-                mTelephonyUtil.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
+                mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
                         WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.MSCHAPV2)));
         assertEquals(null,
-                mTelephonyUtil.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
+                mWifiCarrierInfoManager.getSimIdentity(WifiConfigurationTestUtil.createEapNetwork(
                         WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE)));
         assertEquals(null,
-                mTelephonyUtil.getSimIdentity(new WifiConfiguration()));
+                mWifiCarrierInfoManager.getSimIdentity(new WifiConfiguration()));
     }
 
     /**
@@ -588,7 +670,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals("", mTelephonyUtil.getGsmSimAuthResponse(invalidRequests, config));
+        assertEquals("", mWifiCarrierInfoManager.getGsmSimAuthResponse(invalidRequests, config));
     }
 
     @Test
@@ -599,7 +681,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(null, mTelephonyUtil.getGsmSimAuthResponse(failedRequests, config));
+        assertEquals(null, mWifiCarrierInfoManager.getGsmSimAuthResponse(failedRequests, config));
     }
 
     @Test
@@ -617,7 +699,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(":3b4a:1d2c:1234:1111", mTelephonyUtil.getGsmSimAuthResponse(
+        assertEquals(":3b4a:1d2c:1234:1111", mWifiCarrierInfoManager.getGsmSimAuthResponse(
                         new String[] { "1B2B", "0122" }, config));
     }
 
@@ -628,7 +710,7 @@
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
         assertEquals("",
-                mTelephonyUtil.getGsmSimpleSimAuthResponse(invalidRequests, config));
+                mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse(invalidRequests, config));
     }
 
     @Test
@@ -640,7 +722,7 @@
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
         assertEquals(null,
-                mTelephonyUtil.getGsmSimpleSimAuthResponse(failedRequests, config));
+                mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse(failedRequests, config));
     }
 
     @Test
@@ -658,7 +740,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(":3b4a:1d2c:1100:3322", mTelephonyUtil.getGsmSimpleSimAuthResponse(
+        assertEquals(":3b4a:1d2c:1100:3322", mWifiCarrierInfoManager.getGsmSimpleSimAuthResponse(
                         new String[] { "1A2B", "0123" }, config));
     }
 
@@ -668,8 +750,8 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals("", mTelephonyUtil.getGsmSimpleSimNoLengthAuthResponse(invalidRequests,
-                config));
+        assertEquals("", mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
+                invalidRequests, config));
     }
 
     @Test
@@ -680,8 +762,8 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(null, mTelephonyUtil.getGsmSimpleSimNoLengthAuthResponse(failedRequests,
-                config));
+        assertEquals(null, mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
+                failedRequests, config));
     }
 
     @Test
@@ -700,7 +782,7 @@
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
 
         assertEquals(":1a2b3c4d5e6f7a1a:1a2b3c4d:1234567812345678:12345678",
-                mTelephonyUtil.getGsmSimpleSimNoLengthAuthResponse(
+                mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
                         new String[] { "1A2B", "0123" }, config));
     }
 
@@ -743,9 +825,9 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(null, mTelephonyUtil.get3GAuthResponse(
+        assertEquals(null, mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123"}), config));
-        assertEquals(null, mTelephonyUtil.get3GAuthResponse(
+        assertEquals(null, mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"xyz2", "1234"}),
                 config));
         verifyNoMoreInteractions(mDataTelephonyManager);
@@ -757,7 +839,7 @@
                         TelephonyManager.AUTHTYPE_EAP_AKA, "AgEjAkVn")).thenReturn(null);
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
-        SimAuthResponseData response = mTelephonyUtil.get3GAuthResponse(
+        SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}),
                 config);
 
@@ -771,7 +853,7 @@
                 .thenReturn(Base64.encodeToString(new byte[] {(byte) 0xdc}, Base64.NO_WRAP));
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
-        SimAuthResponseData response = mTelephonyUtil.get3GAuthResponse(
+        SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}),
                 config);
 
@@ -786,7 +868,7 @@
                                 Base64.NO_WRAP));
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
-        SimAuthResponseData response = mTelephonyUtil.get3GAuthResponse(
+        SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}),
                 config);
 
@@ -801,7 +883,7 @@
                                 new byte[] {0x21, 0x22, 0x23}, new byte[] {0x31}));
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
-        SimAuthResponseData response = mTelephonyUtil.get3GAuthResponse(
+        SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}),
                 config);
 
@@ -817,7 +899,7 @@
                 .thenReturn(create3GSimAuthUmtsAutsResponse(new byte[] {0x22, 0x33}));
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
-        SimAuthResponseData response = mTelephonyUtil.get3GAuthResponse(
+        SimAuthResponseData response = mWifiCarrierInfoManager.get3GAuthResponse(
                 new SimAuthRequestData(0, 0, "SSID", new String[]{"0123", "4567"}),
                 config);
         assertNotNull(response);
@@ -838,7 +920,7 @@
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
 
         assertEquals(expectedIdentity,
-                mTelephonyUtil.getAnonymousIdentityWith3GppRealm(config));
+                mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config));
     }
 
     /**
@@ -850,7 +932,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertNull(mTelephonyUtil.getAnonymousIdentityWith3GppRealm(config));
+        assertNull(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config));
     }
 
     /**
@@ -864,7 +946,7 @@
         when(subInfo2.getSubscriptionId()).thenReturn(NON_DATA_SUBID);
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Arrays.asList(subInfo1, subInfo2));
-        assertTrue(mTelephonyUtil.isSimPresent(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID));
     }
 
     /**
@@ -875,13 +957,13 @@
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
 
-        assertFalse(mTelephonyUtil.isSimPresent(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID));
 
         SubscriptionInfo subInfo = mock(SubscriptionInfo.class);
         when(subInfo.getSubscriptionId()).thenReturn(NON_DATA_SUBID);
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Arrays.asList(subInfo));
-        assertFalse(mTelephonyUtil.isSimPresent(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID));
     }
 
     /**
@@ -897,7 +979,7 @@
                 .thenReturn(Arrays.asList(subInfo1, subInfo2));
         when(mTelephonyManager.getSimState(anyInt()))
                 .thenReturn(TelephonyManager.SIM_STATE_NETWORK_LOCKED);
-        assertFalse(mTelephonyUtil.isSimPresent(DATA_SUBID));
+        assertFalse(mWifiCarrierInfoManager.isSimPresent(DATA_SUBID));
     }
 
     /**
@@ -910,12 +992,12 @@
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
         when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[0]);
 
-        assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
 
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
 
-        assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
     }
 
     /**
@@ -926,7 +1008,7 @@
         WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
 
-        assertEquals(DATA_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
     }
 
     /**
@@ -937,7 +1019,7 @@
     public void getBestMatchSubscriptionIdForEnterpriseWithoutCarrierIdFieldForNonSimConfig() {
         WifiConfiguration config = new WifiConfiguration();
 
-        assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
     }
 
     /**
@@ -950,10 +1032,10 @@
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
         config.carrierId = NON_DATA_CARRIER_ID;
 
-        assertEquals(NON_DATA_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(NON_DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
 
         config.carrierId = DATA_CARRIER_ID;
-        assertEquals(DATA_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
     }
 
     /**
@@ -967,7 +1049,7 @@
         WifiConfiguration spyConfig = spy(config);
         doReturn(true).when(spyConfig).isPasspoint();
 
-        assertEquals(DATA_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(spyConfig));
+        assertEquals(DATA_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(spyConfig));
     }
 
     /**
@@ -980,7 +1062,7 @@
         WifiConfiguration spyConfig = spy(config);
         doReturn(true).when(spyConfig).isPasspoint();
 
-        assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(spyConfig));
+        assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(spyConfig));
     }
 
     /**
@@ -993,7 +1075,7 @@
                 WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE);
         config.carrierId = DEACTIVE_CARRIER_ID;
 
-        assertEquals(INVALID_SUBID, mTelephonyUtil.getBestMatchSubscriptionId(config));
+        assertEquals(INVALID_SUBID, mWifiCarrierInfoManager.getBestMatchSubscriptionId(config));
     }
 
     /**
@@ -1004,7 +1086,7 @@
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
 
-        assertNull(mTelephonyUtil.getMatchingImsi(DEACTIVE_CARRIER_ID));
+        assertNull(mWifiCarrierInfoManager.getMatchingImsi(DEACTIVE_CARRIER_ID));
     }
 
     /**
@@ -1013,7 +1095,7 @@
      */
     @Test
     public void getMatchingImsiCarrierIdWithValidCarrierIdForImsiEncryptionCheck() {
-        TelephonyUtil spyTu = spy(mTelephonyUtil);
+        WifiCarrierInfoManager spyTu = spy(mWifiCarrierInfoManager);
         doReturn(true).when(spyTu).requiresImsiEncryption(DATA_SUBID);
         doReturn(false).when(spyTu).isImsiEncryptionInfoAvailable(DATA_SUBID);
 
@@ -1027,7 +1109,7 @@
     @Test
     public void getMatchingImsiCarrierIdWithValidCarrierId() {
         assertEquals(DATA_FULL_IMSI,
-                mTelephonyUtil.getMatchingImsi(DATA_CARRIER_ID));
+                mWifiCarrierInfoManager.getMatchingImsi(DATA_CARRIER_ID));
     }
 
     /**
@@ -1037,12 +1119,12 @@
     public void getMatchingImsiCarrierIdWithEmptyActiveSubscriptionInfoList() {
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
 
-        assertNull(mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+        assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
 
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
 
-        assertNull(mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+        assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1057,7 +1139,7 @@
         when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID);
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
-        assertNull(mTelephonyUtil.getMatchingImsiCarrierId(NO_MATCH_PREFIX_IMSI));
+        assertNull(mWifiCarrierInfoManager.getMatchingImsiCarrierId(NO_MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1073,7 +1155,8 @@
         when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID);
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
-        Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
+        Pair<String, Integer> ic = mWifiCarrierInfoManager
+                .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
 
         assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic);
 
@@ -1083,7 +1166,7 @@
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
         assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID),
-                mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+                mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
 
         // non data SIM doesn't match.
         when(mNonDataTelephonyManager.getCarrierIdFromSimMccMnc()).thenReturn(NON_DATA_CARRIER_ID);
@@ -1093,7 +1176,7 @@
                 .thenReturn(NO_MATCH_OPERATOR_NUMERIC);
 
         assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID),
-                mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+                mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1110,7 +1193,8 @@
                 .thenReturn(PARENT_NON_DATA_CARRIER_ID);
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
-        Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
+        Pair<String, Integer> ic = mWifiCarrierInfoManager
+                .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
 
         assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID), ic);
 
@@ -1122,7 +1206,7 @@
                 .thenReturn(NO_MATCH_OPERATOR_NUMERIC);
 
         assertEquals(new Pair<>(DATA_FULL_IMSI, DATA_CARRIER_ID),
-                mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+                mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1139,7 +1223,8 @@
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
 
-        Pair<String, Integer> ic = mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
+        Pair<String, Integer> ic = mWifiCarrierInfoManager
+                .getMatchingImsiCarrierId(MATCH_PREFIX_IMSI);
 
         assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID), ic);
 
@@ -1150,7 +1235,7 @@
         when(mDataTelephonyManager.getSimOperator()).thenReturn(NO_MATCH_OPERATOR_NUMERIC);
 
         assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID),
-                mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+                mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1169,7 +1254,7 @@
         when(mNonDataTelephonyManager.getSimCarrierId()).thenReturn(NON_DATA_CARRIER_ID);
 
         assertEquals(new Pair<>(NON_DATA_FULL_IMSI, NON_DATA_CARRIER_ID),
-                mTelephonyUtil.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
+                mWifiCarrierInfoManager.getMatchingImsiCarrierId(MATCH_PREFIX_IMSI));
     }
 
     /**
@@ -1187,7 +1272,7 @@
         when(mNonDataTelephonyManager.getSubscriberId()).thenReturn(NO_MATCH_FULL_IMSI);
         when(mNonDataTelephonyManager.getSimOperator())
                 .thenReturn(NO_MATCH_OPERATOR_NUMERIC);
-        TelephonyUtil spyTu = spy(mTelephonyUtil);
+        WifiCarrierInfoManager spyTu = spy(mWifiCarrierInfoManager);
         doReturn(true).when(spyTu).requiresImsiEncryption(eq(DATA_SUBID));
         doReturn(false).when(spyTu).isImsiEncryptionInfoAvailable(eq(DATA_SUBID));
 
@@ -1203,12 +1288,12 @@
         when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID);
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config));
 
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config));
     }
 
     /**
@@ -1219,7 +1304,7 @@
         PasspointConfiguration config = mock(PasspointConfiguration.class);
         when(config.getCarrierId()).thenReturn(DATA_CARRIER_ID);
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(config));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(config));
     }
 
     /**
@@ -1232,7 +1317,7 @@
         doReturn(credential).when(spyConfig).getCredential();
         when(credential.getSimCredential()).thenReturn(null);
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig));
     }
 
     /**
@@ -1248,7 +1333,7 @@
         when(credential.getSimCredential()).thenReturn(simCredential);
         when(simCredential.getImsi()).thenReturn(MATCH_PREFIX_IMSI);
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig));
     }
 
     /**
@@ -1264,7 +1349,7 @@
         when(credential.getSimCredential()).thenReturn(simCredential);
         when(simCredential.getImsi()).thenReturn(DATA_FULL_IMSI);
 
-        assertTrue(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig));
+        assertTrue(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig));
         assertEquals(DATA_CARRIER_ID, spyConfig.getCarrierId());
     }
 
@@ -1280,7 +1365,7 @@
         when(credential.getSimCredential()).thenReturn(simCredential);
         when(simCredential.getImsi()).thenReturn(NO_MATCH_PREFIX_IMSI);
 
-        assertFalse(mTelephonyUtil.tryUpdateCarrierIdForPasspoint(spyConfig));
+        assertFalse(mWifiCarrierInfoManager.tryUpdateCarrierIdForPasspoint(spyConfig));
     }
 
     private void testIdentityWithSimAndEapAkaMethodPrefix(int method, String methodStr)
@@ -1296,7 +1381,7 @@
         receiver.getValue().onReceive(mContext,
                 new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
 
-        assertTrue(mTelephonyUtil.requiresImsiEncryption(DATA_SUBID));
+        assertTrue(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
 
         String mccmnc = "123456";
         String expectedIdentity = methodStr + ANONYMOUS_IDENTITY;
@@ -1306,7 +1391,7 @@
                 method, WifiEnterpriseConfig.Phase2.NONE);
 
         assertEquals(expectedIdentity,
-                mTelephonyUtil.getAnonymousIdentityWith3GppRealm(config));
+                mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(config));
     }
 
     /**
@@ -1339,11 +1424,11 @@
      */
     @Test
     public void testIsAnonymousAtRealmIdentity() throws Exception {
-        assertTrue(mTelephonyUtil.isAnonymousAtRealmIdentity(ANONYMOUS_IDENTITY));
-        assertTrue(mTelephonyUtil.isAnonymousAtRealmIdentity("0" + ANONYMOUS_IDENTITY));
-        assertTrue(mTelephonyUtil.isAnonymousAtRealmIdentity("1" + ANONYMOUS_IDENTITY));
-        assertTrue(mTelephonyUtil.isAnonymousAtRealmIdentity("6" + ANONYMOUS_IDENTITY));
-        assertFalse(mTelephonyUtil.isAnonymousAtRealmIdentity("AKA" + ANONYMOUS_IDENTITY));
+        assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity(ANONYMOUS_IDENTITY));
+        assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("0" + ANONYMOUS_IDENTITY));
+        assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("1" + ANONYMOUS_IDENTITY));
+        assertTrue(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("6" + ANONYMOUS_IDENTITY));
+        assertFalse(mWifiCarrierInfoManager.isAnonymousAtRealmIdentity("AKA" + ANONYMOUS_IDENTITY));
     }
 
     /**
@@ -1354,12 +1439,12 @@
     public void getCarrierPrivilegeWithNoActiveSubscription() {
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
         assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID,
-                mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
+                mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
 
         when(mSubscriptionManager.getActiveSubscriptionInfoList())
                 .thenReturn(Collections.emptyList());
         assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID,
-                mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
+                mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
     }
 
     /**
@@ -1375,7 +1460,7 @@
         when(mDataTelephonyManager.checkCarrierPrivilegesForPackage(TEST_PACKAGE))
                 .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
         assertEquals(TelephonyManager.UNKNOWN_CARRIER_ID,
-                mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
+                mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
     }
 
     /**
@@ -1392,7 +1477,7 @@
         when(mDataTelephonyManager.checkCarrierPrivilegesForPackage(TEST_PACKAGE))
                 .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
         assertEquals(DATA_CARRIER_ID,
-                mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
+                mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE));
     }
 
     /**
@@ -1400,17 +1485,280 @@
      */
     @Test
     public void getCarrierNameFromSubId() {
-        assertEquals(CARRIER_NAME, mTelephonyUtil.getCarrierNameforSubId(DATA_SUBID));
-        assertNull(mTelephonyUtil.getCarrierNameforSubId(NON_DATA_SUBID));
+        assertEquals(CARRIER_NAME, mWifiCarrierInfoManager.getCarrierNameforSubId(DATA_SUBID));
+        assertNull(mWifiCarrierInfoManager.getCarrierNameforSubId(NON_DATA_SUBID));
     }
 
     @Test
     public void testIsCarrierNetworkFromNonDataSim() {
         WifiConfiguration config = new WifiConfiguration();
-        assertFalse(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config));
+        assertFalse(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config));
         config.carrierId = DATA_CARRIER_ID;
-        assertFalse(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config));
+        assertFalse(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config));
         config.carrierId = NON_DATA_CARRIER_ID;
-        assertTrue(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(config));
+        assertTrue(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(config));
+    }
+
+    @Test
+    public void testCheckSetClearImsiProtectionExemption() {
+        InOrder inOrder = inOrder(mWifiConfigManager);
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        mWifiCarrierInfoManager.setHasUserApprovedImsiPrivacyExemptionForCarrier(true,
+                DATA_CARRIER_ID);
+        verify(mListener).onUserAllowed(DATA_CARRIER_ID);
+        inOrder.verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        mWifiCarrierInfoManager.clearImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID);
+        inOrder.verify(mWifiConfigManager).saveToStore(true);
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+    }
+
+    @Test
+    public void testSendImsiProtectionExemptionNotificationWithUserAllowed() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        // Simulate user clicking on allow in the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        validateUserApprovalDialog(CARRIER_NAME);
+
+        // Simulate user clicking on allow in the dialog.
+        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
+                any(), clickListenerCaptor.capture());
+        assertNotNull(clickListenerCaptor.getValue());
+        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
+        mLooper.dispatchAll();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendBroadcast(intentCaptor.capture());
+        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
+        verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        assertTrue(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        verify(mListener).onUserAllowed(DATA_CARRIER_ID);
+    }
+
+    @Test
+    public void testSendImsiProtectionExemptionNotificationWithUserDisallowed() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        // Simulate user clicking on disallow in the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION,
+                CARRIER_NAME, DATA_CARRIER_ID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        verify(mAlertDialog, never()).show();
+
+        verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID);
+    }
+
+    @Test
+    public void testSendImsiProtectionExemptionNotificationWithUserDismissal() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        //Simulate user dismissal the notification
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
+                CARRIER_NAME, DATA_SUBID);
+        reset(mNotificationManger);
+        // No Notification is active, should send notification again.
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        reset(mNotificationManger);
+
+        // As there is notification is active, should not send notification again.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISMISSED_INTENT_ACTION,
+                CARRIER_NAME, DATA_SUBID);
+        verifyNoMoreInteractions(mNotificationManger);
+        verify(mWifiConfigManager, never()).saveToStore(true);
+        assertFalse(mImsiDataSource.hasNewDataToSerialize());
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID);
+    }
+
+    @Test
+    public void testSendImsiProtectionExemptionConfirmationDialogWithUserDisallowed() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        // Simulate user clicking on allow in the notification.
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
+                CARRIER_NAME, DATA_SUBID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        validateUserApprovalDialog(CARRIER_NAME);
+
+        // Simulate user clicking on disallow in the dialog.
+        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
+                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setNegativeButton(
+                any(), clickListenerCaptor.capture());
+        assertNotNull(clickListenerCaptor.getValue());
+        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
+        mLooper.dispatchAll();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendBroadcast(intentCaptor.capture());
+        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
+        verify(mWifiConfigManager).saveToStore(true);
+        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID);
+    }
+
+    @Test
+    public void testSendImsiProtectionExemptionConfirmationDialogWithUserDismissal() {
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
+                CARRIER_NAME, DATA_SUBID);
+        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
+        validateUserApprovalDialog(CARRIER_NAME);
+
+        // Simulate user clicking on dismissal in the dialog.
+        ArgumentCaptor<DialogInterface.OnDismissListener> dismissListenerCaptor =
+                ArgumentCaptor.forClass(DialogInterface.OnDismissListener.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setOnDismissListener(
+                dismissListenerCaptor.capture());
+        assertNotNull(dismissListenerCaptor.getValue());
+        dismissListenerCaptor.getValue().onDismiss(mAlertDialog);
+        mLooper.dispatchAll();
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mContext).sendBroadcast(intentCaptor.capture());
+        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
+
+        // As no notification is active, new notification should be sent
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+
+        verify(mWifiConfigManager, never()).saveToStore(true);
+        assertFalse(mImsiDataSource.hasNewDataToSerialize());
+        assertFalse(mWifiCarrierInfoManager
+                .hasUserApprovedImsiPrivacyExemptionForCarrier(DATA_CARRIER_ID));
+        verify(mListener, never()).onUserAllowed(DATA_CARRIER_ID);
+    }
+
+    @Test
+    public void testUserDataStoreIsNotLoadedNotificationWillNotBeSent() {
+        // reset data source to unloaded state.
+        mImsiDataSource.reset();
+        // Setup carrier without IMSI privacy protection
+        when(mCarrierConfigManager.getConfigForSubId(DATA_SUBID))
+                .thenReturn(generateTestCarrierConfig(false));
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+
+        receiver.getValue().onReceive(mContext,
+                new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        assertFalse(mWifiCarrierInfoManager.requiresImsiEncryption(DATA_SUBID));
+
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        verifyNoMoreInteractions(mNotificationManger);
+
+        // Loaded user data store, notification should be sent
+        mImsiDataSource.fromDeserialized(new HashMap<>());
+        mWifiCarrierInfoManager.sendImsiProtectionExemptionNotificationIfRequired(DATA_CARRIER_ID);
+        validateImsiProtectionNotification(CARRIER_NAME);
+    }
+
+    private void validateImsiProtectionNotification(String carrierName) {
+        verify(mNotificationManger, atLeastOnce()).notify(
+                eq(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE),
+                eq(mNotification));
+        ArgumentCaptor<CharSequence> contentCaptor =
+                ArgumentCaptor.forClass(CharSequence.class);
+        verify(mNotificationBuilder, atLeastOnce()).setContentTitle(contentCaptor.capture());
+        CharSequence content = contentCaptor.getValue();
+        assertNotNull(content);
+        assertTrue(content.toString().contains(carrierName));
+    }
+
+    private void validateUserApprovalDialog(String... anyOfExpectedAppNames) {
+        verify(mAlertDialog, atLeastOnce()).show();
+        ArgumentCaptor<CharSequence> contentCaptor =
+                ArgumentCaptor.forClass(CharSequence.class);
+        verify(mAlertDialogBuilder, atLeastOnce()).setMessage(contentCaptor.capture());
+        CharSequence content = contentCaptor.getValue();
+        assertNotNull(content);
+
+        boolean foundMatch = false;
+        for (int i = 0; i < anyOfExpectedAppNames.length; i++) {
+            foundMatch = content.toString().contains(anyOfExpectedAppNames[i]);
+            if (foundMatch) break;
+        }
+        assertTrue(foundMatch);
+    }
+
+    private void sendBroadcastForUserActionOnImsi(String action, String carrierName,
+            int carrierId) {
+        Intent intent = new Intent()
+                .setAction(action)
+                .putExtra(WifiCarrierInfoManager.EXTRA_CARRIER_NAME, carrierName)
+                .putExtra(WifiCarrierInfoManager.EXTRA_CARRIER_ID, carrierId);
+        assertNotNull(mBroadcastReceiverCaptor.getValue());
+        mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index da4b1e2..8e199ec 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -44,6 +44,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Pair;
 
 import androidx.test.filters.SmallTest;
@@ -51,7 +52,6 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.server.wifi.WifiScoreCard.PerNetwork;
 import com.android.server.wifi.util.LruConnectionTracker;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.server.wifi.util.WifiPermissionsWrapper;
 import com.android.wifi.resources.R;
@@ -151,7 +151,7 @@
     private boolean mStoreReadTriggered = false;
     private TestLooper mLooper = new TestLooper();
     private MockitoSession mSession;
-    private TelephonyUtil mTelephonyUtil;
+    private WifiCarrierInfoManager mWifiCarrierInfoManager;
 
 
     /**
@@ -225,8 +225,9 @@
         when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(TEST_RANDOMIZED_MAC);
         when(mWifiScoreCard.lookupNetwork(any())).thenReturn(mPerNetwork);
 
-        mTelephonyUtil = new TelephonyUtil(mTelephonyManager, mSubscriptionManager,
-                mock(FrameworkFacade.class), mock(Context.class), mock(Handler.class));
+        mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager,
+                mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
+                mock(WifiContext.class), mock(WifiConfigStore.class), mock(Handler.class));
         mLruConnectionTracker = new LruConnectionTracker(100, mContext);
         createWifiConfigManager();
         mWifiConfigManager.addOnNetworkUpdateListener(mWcmListener);
@@ -528,6 +529,67 @@
     }
 
     /**
+     * Verifies the modification of a single network will remove its bssid from
+     * the blocklist.
+     */
+    @Test
+    public void testUpdateSingleOpenNetworkInBlockList() {
+        ArgumentCaptor<WifiConfiguration> wifiConfigCaptor =
+                ArgumentCaptor.forClass(WifiConfiguration.class);
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        List<WifiConfiguration> networks = new ArrayList<>();
+        networks.add(openNetwork);
+
+        verifyAddNetworkToWifiConfigManager(openNetwork);
+        verify(mWcmListener).onNetworkAdded(wifiConfigCaptor.capture());
+        assertEquals(openNetwork.networkId, wifiConfigCaptor.getValue().networkId);
+        reset(mWcmListener);
+
+        // mock the simplest bssid block list
+        Map<String, String> mBssidStatusMap = new ArrayMap<>();
+        doAnswer(new AnswerWithArguments() {
+            public void answer(String ssid) {
+                mBssidStatusMap.entrySet().removeIf(e -> e.getValue().equals(ssid));
+            }
+        }).when(mBssidBlocklistMonitor).clearBssidBlocklistForSsid(
+                anyString());
+        doAnswer(new AnswerWithArguments() {
+            public int answer(String ssid) {
+                return (int) mBssidStatusMap.entrySet().stream()
+                        .filter(e -> e.getValue().equals(ssid)).count();
+            }
+        }).when(mBssidBlocklistMonitor).getNumBlockedBssidsForSsid(
+                anyString());
+        // add bssid to the blocklist
+        mBssidStatusMap.put(TEST_BSSID, openNetwork.SSID);
+        mBssidStatusMap.put("aa:bb:cc:dd:ee:ff", openNetwork.SSID);
+
+        // Now change BSSID for the network.
+        assertAndSetNetworkBSSID(openNetwork, TEST_BSSID);
+        // Change the trusted bit.
+        openNetwork.trusted = false;
+        verifyUpdateNetworkToWifiConfigManagerWithoutIpChange(openNetwork);
+
+        // Now verify that the modification has been effective.
+        List<WifiConfiguration> retrievedNetworks =
+                mWifiConfigManager.getConfiguredNetworksWithPasswords();
+        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
+                networks, retrievedNetworks);
+        verify(mWcmListener).onNetworkUpdated(
+                wifiConfigCaptor.capture(), wifiConfigCaptor.capture());
+        WifiConfiguration newConfig = wifiConfigCaptor.getAllValues().get(1);
+        WifiConfiguration oldConfig = wifiConfigCaptor.getAllValues().get(0);
+        assertEquals(openNetwork.networkId, newConfig.networkId);
+        assertFalse(newConfig.trusted);
+        assertEquals(TEST_BSSID, newConfig.BSSID);
+        assertEquals(openNetwork.networkId, oldConfig.networkId);
+        assertTrue(oldConfig.trusted);
+        assertNull(oldConfig.BSSID);
+
+        assertEquals(0, mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(openNetwork.SSID));
+    }
+
+    /**
      * Verifies that the device owner could modify other other fields in the Wificonfiguration
      * but not the macRandomizationSetting field.
      */
@@ -1935,7 +1997,8 @@
 
         assertFalse(pskNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X));
         pskNetwork.allowedKeyManagement.clear();
-        pskNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+        pskNetwork.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+        pskNetwork.requirePmf = true;
         verifyUpdateNetworkWithCredentialChangeHasEverConnectedFalse(pskNetwork);
     }
 
@@ -2059,7 +2122,7 @@
     @Test
     public void testUpdateIgnoresMaskedPasswords() {
         WifiConfiguration someRandomNetworkWithAllMaskedFields =
-                WifiConfigurationTestUtil.createEapNetwork();
+                WifiConfigurationTestUtil.createPskNetwork();
         someRandomNetworkWithAllMaskedFields.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS;
         someRandomNetworkWithAllMaskedFields.preSharedKey = WifiConfigurationTestUtil.TEST_PSK;
         someRandomNetworkWithAllMaskedFields.enterpriseConfig.setPassword(
@@ -2167,6 +2230,22 @@
     }
 
     /**
+     * Verify that when DeviceConfigFacade#isEnhancedMacRandomizationEnabled returns true, any
+     * networks that already use randomized MAC use enhanced MAC randomization instead.
+     */
+    @Test
+    public void testEnhanecedMacRandomizationIsEnabledGlobally() {
+        when(mFrameworkFacade.getIntegerSetting(eq(mContext),
+                eq(WifiConfigManager.ENHANCED_MAC_RANDOMIZATION_FEATURE_FORCE_ENABLE_FLAG),
+                anyInt())).thenReturn(1);
+        WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
+        assertTrue(mWifiConfigManager.shouldUseAggressiveRandomization(config));
+
+        config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
+        assertFalse(mWifiConfigManager.shouldUseAggressiveRandomization(config));
+    }
+
+    /**
      * Verifies that getRandomizedMacAndUpdateIfNeeded updates the randomized MAC address and
      * |randomizedMacExpirationTimeMs| correctly.
      *
@@ -2379,7 +2458,7 @@
      */
     @Test
     public void testGetConfiguredNetworksMasksPasswords() {
-        WifiConfiguration networkWithPasswords = WifiConfigurationTestUtil.createEapNetwork();
+        WifiConfiguration networkWithPasswords = WifiConfigurationTestUtil.createPskNetwork();
         networkWithPasswords.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS;
         networkWithPasswords.preSharedKey = WifiConfigurationTestUtil.TEST_PSK;
         networkWithPasswords.enterpriseConfig.setPassword(
@@ -4214,7 +4293,7 @@
 
     /**
      * {@link WifiConfigManager#resetSimNetworks()} should reset all non-PEAP SIM networks, no
-     * matter if {@link TelephonyUtil#getSimIdentity()} returns null or not.
+     * matter if {@link WifiCarrierInfoManager#getSimIdentity()} returns null or not.
      */
     @Test
     public void testResetSimNetworks_getSimIdentityNull_shouldResetAllNonPeapSimIdentities() {
@@ -4521,7 +4600,7 @@
     private void createWifiConfigManager() {
         mWifiConfigManager =
                 new WifiConfigManager(
-                        mContext, mClock, mUserManager, mTelephonyUtil,
+                        mContext, mClock, mUserManager, mWifiCarrierInfoManager,
                         mWifiKeyStore, mWifiConfigStore,
                         mWifiPermissionsUtil, mWifiPermissionsWrapper, mWifiInjector,
                         mNetworkListSharedStoreData, mNetworkListUserStoreData,
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
index 61b79fc..8d7f5c6 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -473,6 +473,22 @@
     }
 
     /**
+     * Verify that the validate method fails to validate WifiConfiguration with bad KeyMgmt value.
+     */
+    @Test
+    public void testValidateNegativeCases_InvalidKeyMgmtWithPreSharedKey() {
+        WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork();
+        assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD));
+
+        config.allowedKeyManagement.clear();
+        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN);
+        assertTrue(WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD));
+        // Verify we reset the KeyMgmt
+        assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OSEN));
+    }
+
+    /**
      * Verify that the validate method fails to validate WifiConfiguration with bad Protocol value.
      */
     @Test
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index d66f6dd..f03c536 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -107,8 +107,6 @@
         mWifiConnectivityHelper = mockWifiConnectivityHelper();
         mWifiNS = mockWifiNetworkSelector();
         when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
-        when(mWifiInjector.getWifiNetworkSuggestionsManager())
-                .thenReturn(mWifiNetworkSuggestionsManager);
         when(mWifiNetworkSuggestionsManager.retrieveHiddenNetworkList())
                 .thenReturn(new ArrayList<>());
         when(mWifiNetworkSuggestionsManager.getAllNetworkSuggestions())
@@ -122,7 +120,10 @@
         when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean()))
                 .thenReturn(new ArrayList<>());
         mWifiConnectivityManager = createConnectivityManager();
-        verify(mWifiConfigManager).addOnNetworkUpdateListener(anyObject());
+        verify(mWifiConfigManager).addOnNetworkUpdateListener(
+                mNetworkUpdateListenerCaptor.capture());
+        verify(mWifiNetworkSuggestionsManager).addOnSuggestionUpdateListener(
+                mSuggestionUpdateListenerCaptor.capture());
         mWifiConnectivityManager.setTrustedConnectionAllowed(true);
         mWifiConnectivityManager.setWifiEnabled(true);
         when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
@@ -208,6 +209,8 @@
     @Captor ArgumentCaptor<ArrayList<String>> mSsidWhitelistCaptor;
     @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener>
             mNetworkUpdateListenerCaptor;
+    @Captor ArgumentCaptor<WifiNetworkSuggestionsManager.OnSuggestionUpdateListener>
+            mSuggestionUpdateListenerCaptor;
     private MockResources mResources;
     private int mMinPacketRateActiveTraffic;
 
@@ -385,8 +388,6 @@
         networkList.add(config);
         when(wifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
         when(wifiConfigManager.getSavedNetworks(anyInt())).thenReturn(networkList);
-        doNothing().when(wifiConfigManager).addOnNetworkUpdateListener(
-                mNetworkUpdateListenerCaptor.capture());
 
         return wifiConfigManager;
     }
@@ -394,8 +395,8 @@
     WifiConnectivityManager createConnectivityManager() {
         return new WifiConnectivityManager(mContext,
                 mScoringParams,
-                mClientModeImpl, mWifiInjector,
-                mWifiConfigManager, mWifiInfo, mWifiNS, mWifiConnectivityHelper,
+                mClientModeImpl, mWifiInjector, mWifiConfigManager, mWifiNetworkSuggestionsManager,
+                mWifiInfo, mWifiNS, mWifiConnectivityHelper,
                 mWifiLastResortWatchdog, mOpenNetworkNotifier,
                 mWifiMetrics, new Handler(mLooper.getLooper()), mClock,
                 mLocalLog, mWifiScoreCard);
@@ -3161,4 +3162,31 @@
         assertEquals(maxListSize, results.size());
         assertFalse(results.contains(freqs.get(0).get(2)));
     }
+
+    @Test
+    public void restartPnoScanForNetworkChanges() {
+        mWifiConnectivityManager.setWifiEnabled(true);
+
+        // starts a PNO scan
+        mWifiConnectivityManager.handleConnectionStateChanged(
+                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
+        mWifiConnectivityManager.setTrustedConnectionAllowed(true);
+
+        InOrder inOrder = inOrder(mWifiScanner);
+
+        inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any());
+
+        // Add or update suggestions.
+        mSuggestionUpdateListenerCaptor.getValue().onSuggestionsAddedOrUpdated(
+                Arrays.asList(mWifiNetworkSuggestion));
+        // Ensure that we restarted PNO.
+        inOrder.verify(mWifiScanner).stopPnoScan(any());
+        inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any());
+
+        // Add saved network
+        mNetworkUpdateListenerCaptor.getValue().onNetworkAdded(new WifiConfiguration());
+        // Ensure that we restarted PNO.
+        inOrder.verify(mWifiScanner).stopPnoScan(any());
+        inOrder.verify(mWifiScanner).startDisconnectedPnoScan(any(), any(), any(), any());
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index dde6369..d9a4357 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -111,6 +111,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WpsMetrics;
 import com.android.server.wifi.rtt.RttMetrics;
 import com.android.server.wifi.util.ExternalCallbackTracker;
+import com.android.server.wifi.util.InformationElementUtil;
 import com.android.wifi.resources.R;
 
 import org.junit.Before;
@@ -474,6 +475,8 @@
     private static final long NUM_MBO_CELL_DATA_AWARE_NETWORKS_SCAN_RESULTS = 2;
     private static final long NUM_OCE_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
     private static final long NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS = 2;
+    private static final long NUM_11AX_NETWORKS_SCAN_RESULTS = 3;
+    private static final long NUM_6G_NETWORKS_SCAN_RESULTS = 2;
     private static final long NUM_BSSID_FILTERED_DUE_TO_MBO_ASSOC_DISALLOW_IND = 3;
     private static final long NUM_CONNECT_TO_MBO_SUPPORTED_NETWORKS = 4;
     private static final long NUM_CONNECT_TO_OCE_SUPPORTED_NETWORKS = 3;
@@ -486,6 +489,8 @@
     public static final int FEATURE_MBO = 1 << 0;
     public static final int FEATURE_MBO_CELL_DATA_AWARE = 1 << 1;
     public static final int FEATURE_OCE = 1 << 2;
+    public static final int FEATURE_11AX = 1 << 3;
+    public static final int FEATURE_6G = 1 << 4;
 
     private ScanDetail buildMockScanDetail(boolean hidden, NetworkDetail.HSRelease hSRelease,
             String capabilities, int supportedFeatures) {
@@ -506,6 +511,13 @@
         if ((supportedFeatures & FEATURE_OCE) != 0) {
             when(mockNetworkDetail.isOceSupported()).thenReturn(true);
         }
+        if ((supportedFeatures & FEATURE_11AX) != 0) {
+            when(mockNetworkDetail.getWifiMode())
+                    .thenReturn(InformationElementUtil.WifiMode.MODE_11AX);
+        }
+        if ((supportedFeatures & FEATURE_6G) != 0) {
+            when(mockScanResult.is6GHz()).thenReturn(true);
+        }
         return mockScanDetail;
     }
 
@@ -555,16 +567,18 @@
     private List<ScanDetail> buildMockScanDetailList() {
         List<ScanDetail> mockScanDetails = new ArrayList<ScanDetail>();
         mockScanDetails.add(buildMockScanDetail(true, null, "[ESS]", 0));
-        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]", 0));
+        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-PSK-CCMP][ESS]", FEATURE_11AX));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", 0));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]", FEATURE_MBO));
-        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]", 0));
+        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA-PSK-CCMP]",
+                FEATURE_11AX | FEATURE_6G));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WEP]", 0));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-SAE-CCMP]",
                 FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-OWE-CCMP]",
                 FEATURE_MBO | FEATURE_MBO_CELL_DATA_AWARE | FEATURE_OCE));
-        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-EAP-SUITE-B-192]", 0));
+        mockScanDetails.add(buildMockScanDetail(false, null, "[WPA2-EAP-SUITE-B-192]",
+                FEATURE_11AX | FEATURE_6G));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-PSK-SMS4-SMS4]", 0));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
@@ -1218,6 +1232,10 @@
                 mDecodedProto.numOceSupportedNetworkScanResults);
         assertEquals(NUM_FILS_SUPPORTED_NETWORKS_SCAN_RESULTS * NUM_SCANS,
                 mDecodedProto.numFilsSupportedNetworkScanResults);
+        assertEquals(NUM_11AX_NETWORKS_SCAN_RESULTS * NUM_SCANS,
+                mDecodedProto.num11AxNetworkScanResults);
+        assertEquals(NUM_6G_NETWORKS_SCAN_RESULTS * NUM_SCANS,
+                mDecodedProto.num6GNetworkScanResults);
         assertEquals(NUM_SCANS,
                 mDecodedProto.numScans);
         assertEquals(NUM_CONNECTIVITY_ONESHOT_SCAN_EVENT,
@@ -4662,4 +4680,51 @@
         assertHistogramBucketsEqual(expectedRxAbove2GHistogramMbps,
                 mDecodedProto.throughputMbpsHistogram.rxAbove2G);
     }
+
+    /**
+     * Test the Initial partial scan statistics
+     */
+    @Test
+    public void testInitPartialScan() throws Exception {
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(4, true);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(2, false);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(1, false);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(7, true);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(15, false);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(2, true);
+        mWifiMetrics.incrementInitialPartialScanCount();
+        mWifiMetrics.reportInitialPartialScan(10, true);
+
+        dumpProtoAndDeserialize();
+
+        assertEquals(9, mDecodedProto.initPartialScanStats.numScans);
+        assertEquals(4, mDecodedProto.initPartialScanStats.numSuccessScans);
+        assertEquals(3, mDecodedProto.initPartialScanStats.numFailureScans);
+
+        HistogramBucketInt32[] expectedSuccessScanHistogram = {
+                buildHistogramBucketInt32(1, 3, 1),
+                buildHistogramBucketInt32(3, 5, 1),
+                buildHistogramBucketInt32(5, 10, 1),
+                buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
+        };
+
+        HistogramBucketInt32[] expectedFailureScanHistogram = {
+                buildHistogramBucketInt32(1, 3, 2),
+                buildHistogramBucketInt32(10, Integer.MAX_VALUE, 1),
+        };
+
+        assertHistogramBucketsEqual(expectedSuccessScanHistogram,
+                mDecodedProto.initPartialScanStats.successfulScanChannelCountHistogram);
+
+        assertHistogramBucketsEqual(expectedFailureScanHistogram,
+                mDecodedProto.initPartialScanStats.failedScanChannelCountHistogram);
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
index 6652e9b..24bb968 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
@@ -39,7 +39,6 @@
 import com.android.server.wifi.MboOceController.BtmFrameData;
 import com.android.server.wifi.hotspot2.AnqpEvent;
 import com.android.server.wifi.hotspot2.IconEvent;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -264,8 +263,8 @@
         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mHandlerSpy).handleMessage(messageCaptor.capture());
         assertEquals(WifiMonitor.SUP_REQUEST_SIM_AUTH, messageCaptor.getValue().what);
-        TelephonyUtil.SimAuthRequestData authData =
-                (TelephonyUtil.SimAuthRequestData) messageCaptor.getValue().obj;
+        WifiCarrierInfoManager.SimAuthRequestData authData =
+                (WifiCarrierInfoManager.SimAuthRequestData) messageCaptor.getValue().obj;
         assertEquals(networkId, authData.networkId);
         assertEquals(ssid, authData.ssid);
         assertEquals(WifiEnterpriseConfig.Eap.SIM, authData.protocol);
@@ -288,8 +287,8 @@
         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mHandlerSpy).handleMessage(messageCaptor.capture());
         assertEquals(WifiMonitor.SUP_REQUEST_SIM_AUTH, messageCaptor.getValue().what);
-        TelephonyUtil.SimAuthRequestData authData =
-                (TelephonyUtil.SimAuthRequestData) messageCaptor.getValue().obj;
+        WifiCarrierInfoManager.SimAuthRequestData authData =
+                (WifiCarrierInfoManager.SimAuthRequestData) messageCaptor.getValue().obj;
         assertEquals(networkId, authData.networkId);
         assertEquals(ssid, authData.ssid);
         assertEquals(WifiEnterpriseConfig.Eap.AKA, authData.protocol);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index 684fd14..b495b49 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -1579,6 +1579,36 @@
     }
 
     /**
+     * Verify handling of request release after starting connection to the network.
+     */
+    @Test
+    public void testHandleNetworkReleaseWithSpecifierAfterConnectionStart() throws Exception {
+        sendNetworkRequestAndSetupForConnectionStatus();
+
+        assertNotNull(mSelectedNetwork);
+
+        // Now release the network request.
+        WifiConfiguration wcmNetwork = new WifiConfiguration(mSelectedNetwork);
+        wcmNetwork.networkId = TEST_NETWORK_ID_1;
+        wcmNetwork.creatorUid = TEST_UID_1;
+        wcmNetwork.creatorName = TEST_PACKAGE_NAME_1;
+        wcmNetwork.shared = false;
+        wcmNetwork.fromWifiNetworkSpecifier = true;
+        wcmNetwork.ephemeral = true;
+        when(mWifiConfigManager.getConfiguredNetwork(wcmNetwork.getKey()))
+                .thenReturn(wcmNetwork);
+        mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
+        // verify we canceled the timeout alarm.
+        verify(mAlarmManager).cancel(mConnectionTimeoutAlarmListenerArgumentCaptor.getValue());
+        // Verify that we triggered a disconnect.
+        verify(mClientModeImpl, times(2)).disconnectCommand();
+        verify(mWifiConfigManager).removeNetwork(
+                TEST_NETWORK_ID_1, TEST_UID_1, TEST_PACKAGE_NAME_1);
+        // Re-enable connectivity manager .
+        verify(mWifiConnectivityManager).setSpecificNetworkRequestInProgress(false);
+    }
+
+    /**
      * Verify handling of request release after connecting to the network.
      */
     @Test
@@ -1601,9 +1631,10 @@
         wcmNetwork.networkId = TEST_NETWORK_ID_1;
         wcmNetwork.creatorUid = TEST_UID_1;
         wcmNetwork.creatorName = TEST_PACKAGE_NAME_1;
+        wcmNetwork.shared = false;
         wcmNetwork.fromWifiNetworkSpecifier = true;
         wcmNetwork.ephemeral = true;
-        when(mWifiConfigManager.getConfiguredNetwork(mSelectedNetwork.getKey()))
+        when(mWifiConfigManager.getConfiguredNetwork(wcmNetwork.getKey()))
                 .thenReturn(wcmNetwork);
         mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest);
         // Verify that we triggered a disconnect.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
index 39316a4..6f98f6a 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wifi;
 
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_SAE;
+import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_WAPI_PSK;
 import static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig;
 
 import static org.junit.Assert.*;
@@ -277,7 +280,10 @@
 
             configs[index] = generateWifiConfig(id.intValue(), 0, ssids[index], false, true, null,
                     null, securities[index]);
-            configs[index].preSharedKey = "\"PA55W0RD\""; // needed to validate with PSK
+            if (securities[index] == SECURITY_PSK || securities[index] == SECURITY_SAE
+                    || securities[index] == SECURITY_WAPI_PSK) {
+                configs[index].preSharedKey = "\"PA55W0RD\""; // needed to validate with PSK
+            }
             if (!WifiConfigurationUtil.validate(configs[index], true)) {
                 throw new IllegalArgumentException("Invalid generated config: " + configs[index]);
             }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index f512078..7db13a1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wifi;
 
-import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
@@ -28,9 +26,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION;
-import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION;
 import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION;
-import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION;
 import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION;
 
 import static org.junit.Assert.assertEquals;
@@ -82,7 +78,6 @@
 import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo;
 import com.android.server.wifi.hotspot2.PasspointManager;
 import com.android.server.wifi.util.LruConnectionTracker;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiPermissionsUtil;
 import com.android.wifi.resources.R;
 
@@ -128,6 +123,7 @@
     private static final int TEST_SUBID = 1;
     private static final int TEST_NETWORK_ID = 110;
     private static final int TEST_CARRIER_ID = 1911;
+    private static final String TEST_IMSI = "123456*";
 
     private @Mock WifiContext mContext;
     private @Mock Resources mResources;
@@ -141,9 +137,8 @@
     private @Mock WifiConfigStore mWifiConfigStore;
     private @Mock WifiConfigManager mWifiConfigManager;
     private @Mock NetworkSuggestionStoreData mNetworkSuggestionStoreData;
-    private @Mock ImsiPrivacyProtectionExemptionStoreData mImsiPrivacyProtectionExemptionStoreData;
     private @Mock WifiMetrics mWifiMetrics;
-    private @Mock TelephonyUtil mTelephonyUtil;
+    private @Mock WifiCarrierInfoManager mWifiCarrierInfoManager;
     private @Mock PasspointManager mPasspointManager;
     private @Mock ISuggestionConnectionStatusListener mListener;
     private @Mock IBinder mBinder;
@@ -160,12 +155,14 @@
             ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class);
     private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
             ArgumentCaptor.forClass(BroadcastReceiver.class);
+    private ArgumentCaptor<WifiCarrierInfoManager.OnUserApproveCarrierListener>
+            mUserApproveCarrierListenerArgumentCaptor = ArgumentCaptor.forClass(
+            WifiCarrierInfoManager.OnUserApproveCarrierListener.class);
 
     private InOrder mInorder;
 
     private WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
     private NetworkSuggestionStoreData.DataSource mDataSource;
-    private ImsiPrivacyProtectionExemptionStoreData.DataSource mImsiDataSource;
 
     /**
      * Setup the mocks.
@@ -179,8 +176,6 @@
 
         when(mWifiInjector.makeNetworkSuggestionStoreData(any()))
                 .thenReturn(mNetworkSuggestionStoreData);
-        when(mWifiInjector.makeImsiProtectionExemptionStoreData(any()))
-                .thenReturn(mImsiPrivacyProtectionExemptionStoreData);
         when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade);
         when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
         when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
@@ -232,30 +227,6 @@
         when(mResources.getText(eq(R.string.wifi_suggestion_action_disallow_app)))
                 .thenReturn("blah");
 
-        // setup resource strings for IMSI protection notification.
-        when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_title), anyString()))
-                .thenAnswer(s -> "blah" + s.getArguments()[1]);
-        when(mResources.getString(eq(R.string.wifi_suggestion_imsi_privacy_content)))
-                .thenReturn("blah");
-        when(mResources.getText(
-                eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_carrier)))
-                .thenReturn("blah");
-        when(mResources.getText(
-                eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier)))
-                .thenReturn("blah");
-        when(mResources.getString(
-                eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_title)))
-                .thenReturn("blah");
-        when(mResources.getString(
-                eq(R.string.wifi_suggestion_imsi_privacy_exemption_confirmation_content),
-                anyString())).thenAnswer(s -> "blah" + s.getArguments()[1]);
-        when(mResources.getText(
-                eq(R.string.wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation)))
-                .thenReturn("blah");
-        when(mResources.getText(
-                eq(R.string.wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation)))
-                .thenReturn("blah");
-
 
         // Our app Info. Needed for notification builder.
         ApplicationInfo ourAppInfo = new ApplicationInfo();
@@ -269,7 +240,7 @@
         when(mPackageManager.getApplicationInfoAsUser(eq(TEST_PACKAGE_2), eq(0), any()))
             .thenReturn(appInfO2);
         when(mPackageManager.getApplicationLabel(appInfO2)).thenReturn(TEST_APP_NAME_2);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(any())).thenReturn(
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(any())).thenReturn(
                 TelephonyManager.UNKNOWN_CARRIER_ID);
 
         when(mWifiKeyStore.updateNetworkKeys(any(), any())).thenReturn(true);
@@ -277,7 +248,8 @@
         mWifiNetworkSuggestionsManager =
                 new WifiNetworkSuggestionsManager(mContext, new Handler(mLooper.getLooper()),
                         mWifiInjector, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore,
-                        mWifiMetrics, mTelephonyUtil, mWifiKeyStore, mLruConnectionTracker);
+                        mWifiMetrics, mWifiCarrierInfoManager, mWifiKeyStore,
+                        mLruConnectionTracker);
         verify(mContext).getResources();
         verify(mContext).getSystemService(Context.APP_OPS_SERVICE);
         verify(mContext).getSystemService(Context.NOTIFICATION_SERVICE);
@@ -291,13 +263,8 @@
         mDataSource = dataSourceArgumentCaptor.getValue();
         assertNotNull(mDataSource);
 
-        ArgumentCaptor<ImsiPrivacyProtectionExemptionStoreData.DataSource>
-                imsiDataSourceArgumentCaptor =
-                ArgumentCaptor.forClass(ImsiPrivacyProtectionExemptionStoreData.DataSource.class);
-        verify(mWifiInjector).makeImsiProtectionExemptionStoreData(imsiDataSourceArgumentCaptor
-                .capture());
-        mImsiDataSource = imsiDataSourceArgumentCaptor.getValue();
-        assertNotNull(mImsiDataSource);
+        verify(mWifiCarrierInfoManager).addImsiExemptionUserApprovalListener(
+                mUserApproveCarrierListenerArgumentCaptor.capture());
 
         mWifiNetworkSuggestionsManager.enableVerboseLogging(1);
     }
@@ -1095,7 +1062,7 @@
         assertTrue(mWifiNetworkSuggestionsManager
                 .registerSuggestionConnectionStatusListener(mBinder, mListener,
                         NETWORK_CALLBACK_ID, TEST_PACKAGE_1));
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TEST_CARRIER_ID);
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
                 WifiConfigurationTestUtil.createPskNetwork(), null, true, false, true, true);
@@ -2887,18 +2854,6 @@
         assertEquals(expectedNetworkSuggestion, networkSuggestion);
     }
 
-    private void validateImsiProtectionNotification(String carrierName) {
-        verify(mNotificationManger, atLeastOnce()).notify(
-                eq(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE),
-                eq(mNotification));
-        ArgumentCaptor<CharSequence> contentCaptor =
-                ArgumentCaptor.forClass(CharSequence.class);
-        verify(mNotificationBuilder, atLeastOnce()).setContentTitle(contentCaptor.capture());
-        CharSequence content = contentCaptor.getValue();
-        assertNotNull(content);
-        assertTrue(content.toString().contains(carrierName));
-    }
-
     private void validateUserApprovalDialog(String... anyOfExpectedAppNames) {
         verify(mAlertDialog, atLeastOnce()).show();
         ArgumentCaptor<CharSequence> contentCaptor =
@@ -2942,16 +2897,6 @@
         mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
     }
 
-    private void sendBroadcastForUserActionOnImsi(String action, String carrierName,
-            int carrierId) {
-        Intent intent = new Intent()
-                .setAction(action)
-                .putExtra(WifiNetworkSuggestionsManager.EXTRA_CARRIER_NAME, carrierName)
-                .putExtra(WifiNetworkSuggestionsManager.EXTRA_CARRIER_ID, carrierId);
-        assertNotNull(mBroadcastReceiverCaptor.getValue());
-        mBroadcastReceiverCaptor.getValue().onReceive(mContext, intent);
-    }
-
     @Test
     public void testAddSuggestionWithValidCarrierIdWithCarrierProvisionPermission() {
         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
@@ -3102,7 +3047,7 @@
         assertTrue(mWifiNetworkSuggestionsManager
                 .isPasspointSuggestionSharedWithUser(dummyConfiguration));
         dummyConfiguration.meteredHint = true;
-        when(mTelephonyUtil.isCarrierNetworkFromNonDefaultDataSim(dummyConfiguration))
+        when(mWifiCarrierInfoManager.isCarrierNetworkFromNonDefaultDataSim(dummyConfiguration))
                 .thenReturn(true);
         assertFalse(mWifiNetworkSuggestionsManager
                 .isPasspointSuggestionSharedWithUser(dummyConfiguration));
@@ -3216,7 +3161,7 @@
         networkSuggestionList.add(networkSuggestion);
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(false);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID);
         int status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
@@ -3239,7 +3184,7 @@
         networkSuggestionList.add(networkSuggestion);
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(false);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(VALID_CARRIER_ID);
         int status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
@@ -3262,7 +3207,7 @@
         networkSuggestionList.add(networkSuggestion);
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(true);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID);
         int status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
@@ -3285,12 +3230,12 @@
         networkSuggestionList.add(networkSuggestion);
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(false);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(VALID_CARRIER_ID);
-        when(mTelephonyUtil.getMatchingSubId(VALID_CARRIER_ID)).thenReturn(TEST_SUBID);
-        when(mTelephonyUtil.isSimPresent(TEST_SUBID)).thenReturn(true);
-        when(mTelephonyUtil.requiresImsiEncryption(TEST_SUBID)).thenReturn(true);
-        when(mTelephonyUtil.isImsiEncryptionInfoAvailable(TEST_SUBID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.getMatchingSubId(VALID_CARRIER_ID)).thenReturn(TEST_SUBID);
+        when(mWifiCarrierInfoManager.isSimPresent(TEST_SUBID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUBID)).thenReturn(true);
+        when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(TEST_SUBID)).thenReturn(true);
         ScanDetail scanDetail = createScanDetailForNetwork(config);
         int status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
@@ -3321,13 +3266,13 @@
         networkSuggestionList.add(networkSuggestion);
         when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1))
                 .thenReturn(false);
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(VALID_CARRIER_ID);
         int status = mWifiNetworkSuggestionsManager
                 .add(networkSuggestionList, TEST_UID_1, TEST_PACKAGE_1, TEST_FEATURE);
         assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, status);
         verify(mNotificationManger, never()).notify(anyInt(), any());
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TelephonyManager.UNKNOWN_CARRIER_ID);
         mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps();
         assertEquals(0,  mWifiNetworkSuggestionsManager.get(TEST_PACKAGE_1).size());
@@ -3562,56 +3507,56 @@
     }
 
     /**
-     * Test the IMSI protection notification and user click on the allow.
+     * Verify when matching a SIM-Based network without IMSI protection, framework will mark it
+     * auto-join disable and send notification. If user click on allow, will restore the auto-join
+     * config.
      */
     @Test
     public void testSendImsiProtectionNotificationOnUserAllowed() {
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
+        when(mWifiCarrierInfoManager.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
                 .thenReturn(TEST_CARRIER_ID);
-        when(mTelephonyUtil.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(TEST_SUBID);
-        when(mTelephonyUtil.getCarrierNameforSubId(TEST_SUBID)).thenReturn(TEST_CARRIER_NAME);
-        when(mTelephonyUtil.requiresImsiEncryption(TEST_SUBID)).thenReturn(false);
+        when(mWifiCarrierInfoManager.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(TEST_SUBID);
+        when(mWifiCarrierInfoManager.getCarrierNameforSubId(TEST_SUBID))
+                .thenReturn(TEST_CARRIER_NAME);
+        when(mWifiCarrierInfoManager.requiresImsiEncryption(TEST_SUBID)).thenReturn(false);
+        when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
+                .thenReturn(false);
+        when(mPasspointManager.addOrUpdateProvider(any(), anyInt(), anyString(), anyBoolean(),
+                anyBoolean())).thenReturn(true);
+
         WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createEapNetwork(
                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
+        PasspointConfiguration passpointConfiguration =
+                createTestConfigWithSimCredential(TEST_FQDN, TEST_IMSI, TEST_REALM);
+        WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN);
+        dummyConfiguration.setPasspointUniqueId(passpointConfiguration.getUniqueId());
         WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
                 eapSimConfig, null, true, false, true, true);
+        WifiNetworkSuggestion passpointSuggestion = new WifiNetworkSuggestion(
+                dummyConfiguration, passpointConfiguration, true, false, true, true);
         List<WifiNetworkSuggestion> networkSuggestionList =
-                new ArrayList<WifiNetworkSuggestion>() {{
-                    add(networkSuggestion);
-                }};
+                Arrays.asList(networkSuggestion, passpointSuggestion);
+
         assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
                 mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
                         TEST_PACKAGE_1, TEST_FEATURE));
+
         verifyNoMoreInteractions(mNotificationManger);
         Set<ExtendedWifiNetworkSuggestion> matchedSuggestion = mWifiNetworkSuggestionsManager
                 .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig));
-        validateImsiProtectionNotification(TEST_CARRIER_NAME);
+        verify(mWifiCarrierInfoManager)
+                .sendImsiProtectionExemptionNotificationIfRequired(TEST_CARRIER_ID);
         for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) {
             assertFalse(ewns.isAutojoinEnabled);
         }
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_ALLOWED_CARRIER_INTENT_ACTION,
-                TEST_CARRIER_NAME, TEST_CARRIER_ID);
-        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-        validateUserApprovalDialog(TEST_CARRIER_NAME);
 
-        // Simulate user clicking on allow in the dialog.
-        ArgumentCaptor<DialogInterface.OnClickListener> clickListenerCaptor =
-                ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
-        verify(mAlertDialogBuilder, atLeastOnce()).setPositiveButton(
-                any(), clickListenerCaptor.capture());
-        assertNotNull(clickListenerCaptor.getValue());
-        clickListenerCaptor.getValue().onClick(mAlertDialog, 0);
-        mLooper.dispatchAll();
-        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext).sendBroadcast(intentCaptor.capture());
-        assertEquals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intentCaptor.getValue().getAction());
-        verify(mWifiConfigManager, times(2)).saveToStore(true);
-        assertTrue(mImsiDataSource.hasNewDataToSerialize());
+        // Simulate user approved carrier
+        mUserApproveCarrierListenerArgumentCaptor.getValue().onUserAllowed(TEST_CARRIER_ID);
+        when(mWifiCarrierInfoManager.hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID))
+                .thenReturn(true);
+        verify(mPasspointManager).enableAutojoin(anyString(), any(), anyBoolean());
         matchedSuggestion = mWifiNetworkSuggestionsManager
                 .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig));
-        verifyNoMoreInteractions(mNotificationManger);
-        assertTrue(mWifiNetworkSuggestionsManager
-                .hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID));
 
         for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) {
             assertTrue(ewns.isAutojoinEnabled);
@@ -3619,84 +3564,6 @@
     }
 
     /**
-     * Test the IMSI protection notification and user click on the disallow.
-     */
-    @Test
-    public void testSendImsiProtectionNotificationOnUserDisallowed() {
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
-                .thenReturn(TEST_CARRIER_ID);
-        when(mTelephonyUtil.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(TEST_SUBID);
-        when(mTelephonyUtil.getCarrierNameforSubId(TEST_SUBID)).thenReturn(TEST_CARRIER_NAME);
-        when(mTelephonyUtil.requiresImsiEncryption(TEST_SUBID)).thenReturn(false);
-        WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createEapNetwork(
-                WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
-        WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
-                eapSimConfig, null, true, false, true, true);
-        List<WifiNetworkSuggestion> networkSuggestionList =
-                new ArrayList<WifiNetworkSuggestion>() {{
-                    add(networkSuggestion);
-                }};
-        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
-                mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
-                        TEST_PACKAGE_1, TEST_FEATURE));
-        Set<ExtendedWifiNetworkSuggestion> matchedSuggestion = mWifiNetworkSuggestionsManager
-                .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig));
-        validateImsiProtectionNotification(TEST_CARRIER_NAME);
-        for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) {
-            assertFalse(ewns.isAutojoinEnabled);
-        }
-        sendBroadcastForUserActionOnImsi(NOTIFICATION_USER_DISALLOWED_CARRIER_INTENT_ACTION,
-                TEST_CARRIER_NAME, TEST_CARRIER_ID);
-        verify(mNotificationManger).cancel(SystemMessage.NOTE_NETWORK_SUGGESTION_AVAILABLE);
-
-        verify(mWifiConfigManager, times(2)).saveToStore(true);
-        assertTrue(mImsiDataSource.hasNewDataToSerialize());
-        matchedSuggestion = mWifiNetworkSuggestionsManager
-                .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig));
-        verifyNoMoreInteractions(mNotificationManger);
-        assertFalse(mWifiNetworkSuggestionsManager
-                .hasUserApprovedImsiPrivacyExemptionForCarrier(TEST_CARRIER_ID));
-
-        for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) {
-            assertFalse(ewns.isAutojoinEnabled);
-        }
-    }
-
-    /**
-     * Test when carrier start to support IMSI protection, imsiExemptionMap will update too.
-     */
-    @Test
-    public void testUpdateImsiExemptionMapWhenCarrierFromWithoutProtectionToWithProtection() {
-        // Simulate user click on disallow before.
-        mWifiNetworkSuggestionsManager
-                .setHasUserApprovedImsiPrivacyExemptionForCarrier(false, TEST_CARRIER_ID);
-        verifyNoMoreInteractions(mNotificationManger);
-        // Now carrier upgrade to support Imsi protection
-        when(mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(TEST_PACKAGE_1))
-                .thenReturn(TEST_CARRIER_ID);
-        when(mTelephonyUtil.getMatchingSubId(TEST_CARRIER_ID)).thenReturn(TEST_SUBID);
-        when(mTelephonyUtil.requiresImsiEncryption(TEST_SUBID)).thenReturn(true);
-        WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createEapNetwork(
-                WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
-        WifiNetworkSuggestion networkSuggestion = new WifiNetworkSuggestion(
-                eapSimConfig, null, true, false, true, true);
-        List<WifiNetworkSuggestion> networkSuggestionList =
-                new ArrayList<WifiNetworkSuggestion>() {{
-                    add(networkSuggestion);
-                }};
-        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
-                mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1,
-                        TEST_PACKAGE_1, TEST_FEATURE));
-        Set<ExtendedWifiNetworkSuggestion> matchedSuggestion = mWifiNetworkSuggestionsManager
-                .getNetworkSuggestionsForScanDetail(createScanDetailForNetwork(eapSimConfig));
-        // Should be no more notification and suggestion restore to the initial auto join configure.
-        verifyNoMoreInteractions(mNotificationManger);
-        for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestion) {
-            assertTrue(ewns.isAutojoinEnabled);
-        }
-    }
-
-    /**
      * Verify adding invalid suggestions will return right error reason code.
      */
     @Test
@@ -3818,6 +3685,32 @@
         verify(mLruConnectionTracker, never()).addNetwork(any());
     }
 
+    @Test
+    public void testOnSuggestionUpdateListener() {
+        WifiNetworkSuggestionsManager.OnSuggestionUpdateListener listener =
+                mock(WifiNetworkSuggestionsManager.OnSuggestionUpdateListener.class);
+        mWifiNetworkSuggestionsManager.addOnSuggestionUpdateListener(listener);
+
+        WifiConfiguration dummyConfiguration = createDummyWifiConfigurationForPasspoint(TEST_FQDN);
+        dummyConfiguration.FQDN = TEST_FQDN;
+        WifiNetworkSuggestion networkSuggestion1 = new WifiNetworkSuggestion(
+                WifiConfigurationTestUtil.createOpenNetwork(), null, false, false, true, true);
+
+        List<WifiNetworkSuggestion> networkSuggestionList1 =
+                new ArrayList<WifiNetworkSuggestion>() {{
+                    add(networkSuggestion1);
+                }};
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.add(networkSuggestionList1, TEST_UID_1,
+                        TEST_PACKAGE_1, TEST_FEATURE));
+        verify(listener).onSuggestionsAddedOrUpdated(networkSuggestionList1);
+
+        assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+                mWifiNetworkSuggestionsManager.remove(networkSuggestionList1, TEST_UID_1,
+                        TEST_PACKAGE_1));
+        verify(listener).onSuggestionsRemoved(networkSuggestionList1);
+    }
+
     /**
      * Helper function for creating a test configuration with user credential.
      *
@@ -3861,7 +3754,7 @@
         homeSp.setFriendlyName(TEST_FRIENDLY_NAME);
         config.setHomeSp(homeSp);
         Credential credential = new Credential();
-        credential.setRealm(TEST_REALM);
+        credential.setRealm(realm);
         Credential.SimCredential simCredential = new Credential.SimCredential();
         simCredential.setImsi(imsi);
         simCredential.setEapType(EAPConstants.EAP_SIM);
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java
index cfa6044..697f831 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java
@@ -36,9 +36,9 @@
 
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.wifi.WifiBaseTest;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiConfigStore;
 import com.android.server.wifi.WifiKeyStore;
-import com.android.server.wifi.util.TelephonyUtil;
 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
 
 import org.junit.Before;
@@ -77,7 +77,7 @@
     private static final boolean TEST_SHARED = false;
 
     @Mock WifiKeyStore mKeyStore;
-    @Mock TelephonyUtil mTelephonyUtil;
+    @Mock WifiCarrierInfoManager mWifiCarrierInfoManager;
     @Mock PasspointConfigUserStoreData.DataSource mDataSource;
     PasspointConfigUserStoreData mConfigStoreData;
 
@@ -85,7 +85,8 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mConfigStoreData = new PasspointConfigUserStoreData(mKeyStore, mTelephonyUtil, mDataSource);
+        mConfigStoreData = new PasspointConfigUserStoreData(mKeyStore, mWifiCarrierInfoManager,
+                mDataSource);
     }
 
     /**
@@ -251,12 +252,12 @@
         // Setup expected data.
         List<PasspointProvider> providerList = new ArrayList<>();
         PasspointProvider provider1 = new PasspointProvider(createFullPasspointConfiguration(),
-                mKeyStore, mTelephonyUtil, TEST_PROVIDER_ID, TEST_CREATOR_UID, TEST_CREATOR_PACKAGE,
-                false, Arrays.asList(TEST_CA_CERTIFICATE_ALIAS),
+                mKeyStore, mWifiCarrierInfoManager, TEST_PROVIDER_ID, TEST_CREATOR_UID,
+                TEST_CREATOR_PACKAGE, false, Arrays.asList(TEST_CA_CERTIFICATE_ALIAS),
                 TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, null,
                 TEST_HAS_EVER_CONNECTED, TEST_SHARED);
         PasspointProvider provider2 = new PasspointProvider(createFullPasspointConfiguration(),
-                mKeyStore, mTelephonyUtil, TEST_PROVIDER_ID_2, TEST_CREATOR_UID,
+                mKeyStore, mWifiCarrierInfoManager, TEST_PROVIDER_ID_2, TEST_CREATOR_UID,
                 TEST_CREATOR_PACKAGE, true,
                 Arrays.asList(TEST_CA_CERTIFICATE_ALIAS, TEST_CA_CERTIFICATE_ALIAS_2),
                 TEST_CLIENT_PRIVATE_KEY_AND_CERT_ALIAS, TEST_REMEDIATION_CA_CERTIFICATE_ALIAS,
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index 3f92809..73c5713 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -92,9 +92,11 @@
 import com.android.server.wifi.FrameworkFacade;
 import com.android.server.wifi.NetworkUpdateResult;
 import com.android.server.wifi.WifiBaseTest;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiConfigManager;
 import com.android.server.wifi.WifiConfigStore;
 import com.android.server.wifi.WifiConfigurationTestUtil;
+import com.android.server.wifi.WifiContext;
 import com.android.server.wifi.WifiInjector;
 import com.android.server.wifi.WifiKeyStore;
 import com.android.server.wifi.WifiMetrics;
@@ -108,7 +110,6 @@
 import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo;
 import com.android.server.wifi.util.InformationElementUtil;
 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -204,7 +205,7 @@
     PasspointManager mManager;
     ArgumentCaptor<AppOpsManager.OnOpChangedListener> mAppOpChangedListenerCaptor =
             ArgumentCaptor.forClass(AppOpsManager.OnOpChangedListener.class);
-    TelephonyUtil mTelephonyUtil;
+    WifiCarrierInfoManager mWifiCarrierInfoManager;
 
     /** Sets up test. */
     @Before
@@ -226,13 +227,14 @@
         when(mWifiInjector.getClientModeImpl()).thenReturn(mClientModeImpl);
         when(mWifiInjector.getWifiNetworkSuggestionsManager())
                 .thenReturn(mWifiNetworkSuggestionsManager);
-        mTelephonyUtil = new TelephonyUtil(mTelephonyManager, mSubscriptionManager,
-                mock(FrameworkFacade.class), mock(Context.class), mock(Handler.class));
+        mWifiCarrierInfoManager = new WifiCarrierInfoManager(mTelephonyManager,
+                mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
+                mock(WifiContext.class), mWifiConfigStore, mock(Handler.class));
         mLooper = new TestLooper();
         mHandler = new Handler(mLooper.getLooper());
         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mTelephonyUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
         verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class),
@@ -242,8 +244,8 @@
         verify(mObjectFactory).makePasspointConfigSharedStoreData(sharedDataSource.capture());
         ArgumentCaptor<PasspointConfigUserStoreData.DataSource> userDataSource =
                 ArgumentCaptor.forClass(PasspointConfigUserStoreData.DataSource.class);
-        verify(mObjectFactory).makePasspointConfigUserStoreData(
-                any(WifiKeyStore.class), any(TelephonyUtil.class), userDataSource.capture());
+        verify(mObjectFactory).makePasspointConfigUserStoreData(any(WifiKeyStore.class),
+                any(WifiCarrierInfoManager.class), userDataSource.capture());
         mCallbacks = callbacks.getValue();
         mSharedDataSource = sharedDataSource.getValue();
         mUserDataSource = userDataSource.getValue();
@@ -399,7 +401,7 @@
         wifiConfig.setPasspointUniqueId(config.getUniqueId());
         PasspointProvider provider = createMockProvider(config, wifiConfig, isSuggestion);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(isSuggestion))).thenReturn(provider);
         when(provider.getPackageName()).thenReturn(packageName);
         assertTrue(mManager.addOrUpdateProvider(
@@ -642,7 +644,7 @@
         PasspointProvider provider = createMockProvider(config);
         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                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));
@@ -784,7 +786,7 @@
                 TEST_REALM);
         PasspointProvider provider = createMockProvider(config);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                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));
@@ -846,7 +848,7 @@
                 .thenReturn(true);
         PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, spyFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mTelephonyUtil);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
 
         assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -873,7 +875,7 @@
                 TEST_REALM);
         PasspointProvider origProvider = createMockProvider(origConfig);
         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(false))).thenReturn(origProvider);
         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
                 false, true));
@@ -917,7 +919,7 @@
                 TEST_FRIENDLY_NAME);
         PasspointProvider newProvider = createMockProvider(newConfig);
         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(false))).thenReturn(newProvider);
         when(mWifiConfigManager.getConfiguredNetwork(origProvider.getWifiConfig().getKey()))
                 .thenReturn(origWifiConfig);
@@ -954,7 +956,8 @@
                 TEST_FRIENDLY_NAME);
         PasspointProvider provider = mock(PasspointProvider.class);
         when(provider.installCertsAndKeys()).thenReturn(false);
-        when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore), eq(mTelephonyUtil),
+        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));
@@ -974,7 +977,7 @@
                 TEST_FRIENDLY_NAME);
         PasspointProvider provider = createMockProvider(config);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                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));
@@ -996,7 +999,7 @@
         config.setUpdateIdentifier(1);
         PasspointProvider provider = createMockProvider(config);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                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));
@@ -1603,7 +1606,7 @@
         PasspointProvider provider = createMockProvider(config);
         // Verify the provider ID used to create the new provider.
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), eq(providerIndex), eq(TEST_CREATOR_UID),
+                eq(mWifiCarrierInfoManager), eq(providerIndex), eq(TEST_CREATOR_UID),
                 eq(TEST_PACKAGE), eq(false))).thenReturn(provider);
 
         assertTrue(
@@ -1960,7 +1963,7 @@
                 TEST_REALM);
         PasspointProvider provider = createMockProvider(config);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                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));
@@ -2003,7 +2006,7 @@
         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(provider.isFromSuggestion()).thenReturn(true);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(provider);
         assertTrue(mManager.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -2073,7 +2076,7 @@
         PasspointProvider origProvider = createMockProvider(origConfig);
         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(origProvider);
         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -2120,7 +2123,7 @@
         when(newProvider.isFromSuggestion()).thenReturn(true);
         when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(newProvider);
         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -2153,7 +2156,7 @@
         PasspointProvider origProvider = createMockProvider(origConfig);
         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(origProvider);
         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -2174,7 +2177,7 @@
                 TEST_FRIENDLY_NAME);
         PasspointProvider newProvider = createMockProvider(newConfig);
         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(false))).thenReturn(newProvider);
         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE,
                 false, true));
@@ -2206,7 +2209,7 @@
         PasspointProvider origProvider = createMockProvider(origConfig);
         when(origProvider.getPackageName()).thenReturn(TEST_PACKAGE);
         when(mObjectFactory.makePasspointProvider(eq(origConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(false))).thenReturn(origProvider);
         assertTrue(mManager.addOrUpdateProvider(origConfig, TEST_CREATOR_UID, TEST_PACKAGE, false,
                 true));
@@ -2231,7 +2234,7 @@
         when(newProvider.isFromSuggestion()).thenReturn(true);
         when(newProvider.getPackageName()).thenReturn(TEST_PACKAGE1);
         when(mObjectFactory.makePasspointProvider(eq(newConfig), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE1),
                 eq(true))).thenReturn(newProvider);
         assertTrue(mManager.addOrUpdateProvider(newConfig, TEST_CREATOR_UID, TEST_PACKAGE1, true,
                 true));
@@ -2411,7 +2414,7 @@
                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
         PasspointProvider provider = createMockProvider(config, wifiConfig, true);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(provider);
         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
         assertTrue(mManager.addOrUpdateProvider(
@@ -2430,7 +2433,7 @@
                 createTestConfigWithUserCredential(TEST_FQDN, TEST_FRIENDLY_NAME);
         PasspointProvider provider = createMockProvider(config, wifiConfig, false);
         when(mObjectFactory.makePasspointProvider(eq(config), eq(mWifiKeyStore),
-                eq(mTelephonyUtil), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
+                eq(mWifiCarrierInfoManager), anyLong(), eq(TEST_CREATOR_UID), eq(TEST_PACKAGE),
                 eq(true))).thenReturn(provider);
         when(provider.getPackageName()).thenReturn(TEST_PACKAGE);
         assertFalse(mManager.addOrUpdateProvider(
@@ -2447,7 +2450,7 @@
         PasspointConfiguration config = mock(PasspointConfiguration.class);
         PasspointProvider mockProvider = mock(PasspointProvider.class);
         when(mObjectFactory.makePasspointProvider(config, null,
-                mTelephonyUtil, 0, 0, null, false))
+                mWifiCarrierInfoManager, 0, 0, null, false))
                 .thenReturn(mockProvider);
         List<ScanResult> scanResults = new ArrayList<>() {{
                 add(mock(ScanResult.class));
@@ -2469,7 +2472,7 @@
         PasspointConfiguration config = mock(PasspointConfiguration.class);
         PasspointProvider mockProvider = mock(PasspointProvider.class);
         when(mObjectFactory.makePasspointProvider(config, null,
-                mTelephonyUtil, 0, 0, null, false))
+                mWifiCarrierInfoManager, 0, 0, null, false))
                 .thenReturn(mockProvider);
         List<ScanResult> scanResults = new ArrayList<>() {{
                 add(mock(ScanResult.class));
@@ -2493,7 +2496,7 @@
         PasspointProvider mockProvider = mock(PasspointProvider.class);
 
         when(mObjectFactory.makePasspointProvider(config, null,
-                mTelephonyUtil, 0, 0, null, false))
+                mWifiCarrierInfoManager, 0, 0, null, false))
                 .thenReturn(mockProvider);
 
         List<ScanResult> scanResults = new ArrayList<>() {{
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
index 5a20ef5..19ced12 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointProviderTest.java
@@ -39,6 +39,7 @@
 
 import com.android.server.wifi.FakeKeys;
 import com.android.server.wifi.WifiBaseTest;
+import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiKeyStore;
 import com.android.server.wifi.hotspot2.anqp.ANQPElement;
 import com.android.server.wifi.hotspot2.anqp.CellularNetwork;
@@ -53,7 +54,6 @@
 import com.android.server.wifi.hotspot2.anqp.eap.NonEAPInnerAuth;
 import com.android.server.wifi.util.ArrayUtils;
 import com.android.server.wifi.util.InformationElementUtil.RoamingConsortium;
-import com.android.server.wifi.util.TelephonyUtil;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -118,7 +118,8 @@
     }
 
     @Mock WifiKeyStore mKeyStore;
-    @Mock TelephonyUtil mTelephonyUtil;
+    @Mock
+    WifiCarrierInfoManager mWifiCarrierInfoManager;
     @Mock RoamingConsortium mRoamingConsortium;
     PasspointProvider mProvider;
     X509Certificate mRemediationCaCertificate;
@@ -152,8 +153,8 @@
      * @return {@link com.android.server.wifi.hotspot2.PasspointProvider}
      */
     private PasspointProvider createProvider(PasspointConfiguration config) {
-        return new PasspointProvider(config, mKeyStore, mTelephonyUtil, PROVIDER_ID, CREATOR_UID,
-                CREATOR_PACKAGE, false);
+        return new PasspointProvider(config, mKeyStore, mWifiCarrierInfoManager, PROVIDER_ID,
+                CREATOR_UID, CREATOR_PACKAGE, false);
     }
 
     /**
@@ -704,7 +705,7 @@
         // Setup test provider.
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI))
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
         mProvider = createProvider(config);
 
@@ -729,7 +730,7 @@
         // Setup test provider.
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI))
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
         mProvider = createProvider(config);
 
@@ -758,7 +759,7 @@
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
         mProvider = createProvider(config);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(
                 eq(config.getCredential().getSimCredential().getImsi())))
                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
 
@@ -941,7 +942,7 @@
         // Setup test provider.
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI))
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
         mProvider = createProvider(config);
 
@@ -971,7 +972,7 @@
         // Setup test provider.
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(TEST_IMSI))
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(TEST_IMSI))
                 .thenReturn(new Pair<String, Integer>(TEST_IMSI, VALID_CARRIER_ID));
         mProvider = createProvider(config);
 
@@ -1001,7 +1002,7 @@
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
         config.setCarrierId(VALID_CARRIER_ID);
-        when(mTelephonyUtil.getMatchingImsi(eq(VALID_CARRIER_ID)))
+        when(mWifiCarrierInfoManager.getMatchingImsi(eq(VALID_CARRIER_ID)))
                 .thenReturn(null);
         mProvider = createProvider(config);
 
@@ -1029,7 +1030,7 @@
         // Setup test provider.
         PasspointConfiguration config = generateTestPasspointConfiguration(
                 CredentialType.SIM, false);
-        when(mTelephonyUtil.getMatchingImsiCarrierId(eq(TEST_IMSI)))
+        when(mWifiCarrierInfoManager.getMatchingImsiCarrierId(eq(TEST_IMSI)))
                 .thenReturn(null);
         mProvider = createProvider(config);