Merge "Test case clean up." into qt-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 08d5634..2eae4df 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2203,10 +2203,10 @@
     <string name="wifi_dpp_wifi_password">Wi\u2011Fi password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
     <!-- Hint for Wi-Fi hotspot password [CHAR LIMIT=50]  -->
     <string name="wifi_dpp_hotspot_password">Hotspot password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
-    <!-- Label for "Connect to this network using a QR code" [CHAR LIMIT=50]  -->
+    <!-- Label for "Use a QR code to add a device to this network" [CHAR LIMIT=50]  -->
     <string name="wifi_dpp_add_device">Add device</string>
     <!-- Hint for "Add device" [CHAR LIMIT=NONE]  -->
-    <string name="wifi_dpp_connect_network_using_qr_code">Connect to this network using a QR code</string>
+    <string name="wifi_dpp_connect_network_using_qr_code">Use a QR code to add a device to this network</string>
      <!-- Label for the try again button [CHAR LIMIT=20]-->
     <string name="retry">Retry</string>
     <!-- Label for the check box to share a network with other users on the same device -->
@@ -7652,19 +7652,19 @@
     <string name="zen_mode_sound_summary_on">On</string>
 
     <!--  Do not disturb: Summary for zen mode duration setting indicating user will be prompted to set dnd duration whenever dnd is manually toggled on [CHAR LIMIT=NONE]-->
-    <string name="zen_mode_duration_summary_always_prompt">Ask every time (unless turned on automatically)</string>
+    <string name="zen_mode_duration_summary_always_prompt">Ask every time</string>
 
     <!--  Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
-    <string name="zen_mode_duration_summary_forever">Until you turn off (unless turned on automatically)</string>
+    <string name="zen_mode_duration_summary_forever">Until you turn off</string>
 
     <!--  Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
     <plurals name="zen_mode_duration_summary_time_hours">
-        <item quantity="one">1 hour (unless turned on automatically)</item>
-        <item quantity="other"><xliff:g id="num_hours" example="3">%d</xliff:g> hours (unless turned on automatically)</item>
+        <item quantity="one">1 hour</item>
+        <item quantity="other"><xliff:g id="num_hours" example="3">%d</xliff:g> hours</item>
     </plurals>
 
     <!--  Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when toggled on -->
-    <string name="zen_mode_duration_summary_time_minutes"><xliff:g id="num_minutes" example="5">%d</xliff:g> minutes (unless turned on automatically)</string>
+    <string name="zen_mode_duration_summary_time_minutes"><xliff:g id="num_minutes" example="5">%d</xliff:g> minutes</string>
 
     <!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
     <plurals name="zen_mode_sound_summary_summary_off_info">
diff --git a/src/com/android/settings/development/SystemServerHeapDumpPreferenceController.java b/src/com/android/settings/development/SystemServerHeapDumpPreferenceController.java
index 599162e..e6701ce 100644
--- a/src/com/android/settings/development/SystemServerHeapDumpPreferenceController.java
+++ b/src/com/android/settings/development/SystemServerHeapDumpPreferenceController.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.util.Log;
@@ -47,7 +48,7 @@
         super(context);
 
         mUserManager = context.getSystemService(UserManager.class);
-        mHandler = new Handler();
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
index 5f58fcf..f2c8252 100644
--- a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -139,12 +139,11 @@
      * Enables the specified overlay package.
      */
     static void setNavBarInteractionMode(IOverlayManager overlayManager, String overlayPackage) {
-        setOverlayEnabled(overlayManager, NAV_BAR_MODE_3BUTTON_OVERLAY,
-                overlayPackage == NAV_BAR_MODE_3BUTTON_OVERLAY);
-        setOverlayEnabled(overlayManager, NAV_BAR_MODE_2BUTTON_OVERLAY,
-                overlayPackage == NAV_BAR_MODE_2BUTTON_OVERLAY);
-        setOverlayEnabled(overlayManager, NAV_BAR_MODE_GESTURAL_OVERLAY,
-                overlayPackage == NAV_BAR_MODE_GESTURAL_OVERLAY);
+        try {
+            overlayManager.setEnabledExclusiveInCategory(overlayPackage, USER_CURRENT);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     static boolean isSwipeUpEnabled(Context context) {
@@ -159,12 +158,4 @@
         return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
                 com.android.internal.R.integer.config_navBarInteractionMode);
     }
-
-    static void setOverlayEnabled(IOverlayManager overlayManager, String pkg, boolean enabled) {
-        try {
-            overlayManager.setEnabled(pkg, enabled, USER_CURRENT);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
 }
diff --git a/src/com/android/settings/network/MobileNetworkListController.java b/src/com/android/settings/network/MobileNetworkListController.java
index a2e4116..d0e14ce 100644
--- a/src/com/android/settings/network/MobileNetworkListController.java
+++ b/src/com/android/settings/network/MobileNetworkListController.java
@@ -98,7 +98,7 @@
         mPreferences = new ArrayMap<>();
 
         final List<SubscriptionInfo> subscriptions = SubscriptionUtil.getAvailableSubscriptions(
-                mSubscriptionManager);
+                mContext);
         for (SubscriptionInfo info : subscriptions) {
             final int subId = info.getSubscriptionId();
             Preference pref = existingPreferences.remove(subId);
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index ae115eb..9498c4e 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.euicc.EuiccManager;
@@ -99,7 +100,7 @@
     @Override
     public CharSequence getSummary() {
         final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
-                mSubscriptionManager);
+                mContext);
         if (subs.isEmpty()) {
             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
                 return mContext.getResources().getString(
@@ -132,7 +133,7 @@
         mPreference.setEnabled(!mChangeListener.isAirplaneModeOn());
 
         final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
-                mSubscriptionManager);
+                mContext);
 
         if (subs.isEmpty()) {
             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
@@ -154,6 +155,7 @@
             if (subs.size() == 1) {
                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
                     final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
+                    intent.putExtra(Settings.EXTRA_SUB_ID, subs.get(0).getSubscriptionId());
                     mContext.startActivity(intent);
                     return true;
                 });
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 5f1beca..86655d4 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -16,8 +16,15 @@
 
 package com.android.settings.network;
 
+import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
+
+import static com.android.internal.util.CollectionUtils.emptyIfNull;
+
+import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.UiccSlotInfo;
 import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
@@ -27,6 +34,7 @@
 import java.util.List;
 
 public class SubscriptionUtil {
+    private static final String TAG = "SubscriptionUtil";
     private static List<SubscriptionInfo> sAvailableResultsForTesting;
     private static List<SubscriptionInfo> sActiveResultsForTesting;
 
@@ -44,21 +52,56 @@
         if (sActiveResultsForTesting != null) {
             return sActiveResultsForTesting;
         }
-        List<SubscriptionInfo> subscriptions = manager.getActiveSubscriptionInfoList(true);
+        final List<SubscriptionInfo> subscriptions = manager.getActiveSubscriptionInfoList(true);
         if (subscriptions == null) {
             return new ArrayList<>();
         }
         return subscriptions;
     }
 
-    public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
+    private static boolean isInactiveInsertedPSim(UiccSlotInfo slotInfo) {
+        return !slotInfo.getIsEuicc() && !slotInfo.getIsActive() &&
+                slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT;
+    }
+
+    public static List<SubscriptionInfo> getAvailableSubscriptions(Context context) {
         if (sAvailableResultsForTesting != null) {
             return sAvailableResultsForTesting;
         }
-        List<SubscriptionInfo> subscriptions = manager.getSelectableSubscriptionInfoList();
-        if (subscriptions == null) {
-            subscriptions = new ArrayList<>();
+        final SubscriptionManager subMgr = context.getSystemService(SubscriptionManager.class);
+        final TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
+
+        List<SubscriptionInfo> subscriptions =
+                new ArrayList<>(emptyIfNull(subMgr.getSelectableSubscriptionInfoList()));
+
+        // Look for inactive but present physical SIMs that are missing from the selectable list.
+        final List<UiccSlotInfo> missing = new ArrayList<>();
+        UiccSlotInfo[] slotsInfo =  telMgr.getUiccSlotsInfo();
+        for (int i = 0; slotsInfo != null && i < slotsInfo.length; i++) {
+            final UiccSlotInfo slotInfo = slotsInfo[i];
+            if (isInactiveInsertedPSim(slotInfo)) {
+                final int index = slotInfo.getLogicalSlotIdx();
+                final String cardId = slotInfo.getCardId();
+
+                final boolean found = subscriptions.stream().anyMatch(info ->
+                        index == info.getSimSlotIndex() && cardId.equals(info.getCardString()));
+                if (!found) {
+                    missing.add(slotInfo);
+                }
+            }
         }
+        if (!missing.isEmpty()) {
+            for (SubscriptionInfo info : subMgr.getAllSubscriptionInfoList()) {
+                for (UiccSlotInfo slotInfo : missing) {
+                    if (info.getSimSlotIndex() == slotInfo.getLogicalSlotIdx() &&
+                    info.getCardString().equals(slotInfo.getCardId())) {
+                        subscriptions.add(info);
+                        break;
+                    }
+                }
+            }
+        }
+
         // With some carriers such as Google Fi which provide a sort of virtual service that spans
         // across multiple underlying networks, we end up with subscription entries for the
         // underlying networks that need to be hidden from the user in the UI.
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 47eb66b..b8ed31f 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -40,6 +40,7 @@
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.SettingsBaseActivity;
 import com.android.settings.development.featureflags.FeatureFlagPersistent;
+import com.android.settings.network.SubscriptionUtil;
 
 import com.google.android.material.bottomnavigation.BottomNavigationView;
 
@@ -165,7 +166,7 @@
             final int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, SUB_ID_NULL);
             if (subId != SUB_ID_NULL) {
                 for (SubscriptionInfo subscription :
-                        mSubscriptionManager.getSelectableSubscriptionInfoList()) {
+                        SubscriptionUtil.getAvailableSubscriptions(this)) {
                     if (subscription.getSubscriptionId() == subId) {
                         return subscription;
                     }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
index fd296ec..2037adc 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
@@ -94,8 +94,9 @@
             return;
         }
         final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
-                mSubscriptionManager);
-        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID || subs.size() < 2) {
+                mContext);
+        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID ||
+                mSubscriptionManager.isSubscriptionEnabled(mSubId) && subs.size() < 2) {
             mSwitchBar.hide();
             return;
         }
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index 73f6e06..d9d2b9b 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.notification;
 
+import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
+
 import android.app.Activity;
 import android.app.Application;
 import android.app.settings.SettingsEnums;
@@ -24,10 +26,13 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.SearchIndexableResource;
+import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
@@ -62,10 +67,11 @@
     static final String KEY_NOTIFICATION_ASSISTANT = "notification_assistant";
 
     private static final String KEY_NOTI_DEFAULT_RINGTONE = "notification_default_ringtone";
-
-    private RingtonePreference mRequestPreference;
     private static final int REQUEST_CODE = 200;
     private static final String SELECTED_PREFERENCE_KEY = "selected_preference";
+    private static final String KEY_ADVANCED_CATEGORY = "configure_notifications_advanced";
+
+    private RingtonePreference mRequestPreference;
 
     @Override
     public int getMetricsCategory() {
@@ -119,6 +125,27 @@
     }
 
     @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        final PreferenceScreen screen = getPreferenceScreen();
+        final Bundle arguments = getArguments();
+
+        if (screen == null) {
+            return;
+        }
+        if (arguments != null) {
+            final String highlightKey = arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
+            if (!TextUtils.isEmpty(highlightKey)) {
+                final PreferenceCategory advancedCategory =
+                        screen.findPreference(KEY_ADVANCED_CATEGORY);
+                // Has highlight row - expand everything
+                advancedCategory.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
+                scrollToPreference(advancedCategory);
+            }
+        }
+    }
+
+    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (preference instanceof RingtonePreference) {
             mRequestPreference = (RingtonePreference) preference;
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index ae96ed3..f98dc58 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -146,7 +146,8 @@
     private static final long TIMEOUT = Duration.ofSeconds(10).toMillis();
 
     // Be static to avoid too much object not be reset.
-    private static CountDownTimer mTimer;
+    @VisibleForTesting
+    static CountDownTimer mTimer;
 
     private AccessPoint mAccessPoint;
     private final ConnectivityManager mConnectivityManager;
@@ -256,20 +257,15 @@
 
         @Override
         public void onLost(Network network) {
-            final boolean lostCurrentNetwork = network.equals(mNetwork);
-            if (lostCurrentNetwork) {
-                // Should update as disconnect but not exit. Except for ephemeral network which
-                // should not show on saved network list.
-                if (!mIsEphemeral) {
-                    return;
-                }
-
+            // Ephemeral network not a saved network, leave detail page once disconnected
+            if (mIsEphemeral && network.equals(mNetwork)) {
                 exitActivity();
             }
         }
     };
 
-    private final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+    @VisibleForTesting
+    final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
         /** Called when the state of Wifi has changed. */
         public void onWifiStateChanged(int state) {
             Log.d(TAG, "onWifiStateChanged(" + state + ")");
@@ -284,16 +280,7 @@
 
         /** Called when the connection state of wifi has changed. */
         public void onConnectedChanged() {
-            updateAccessPointFromScannedList();
-            if (mConnected != mAccessPoint.isActive()) {
-                Log.d(TAG, "Connection state changed!");
-                mConnected = mAccessPoint.isActive();
-                if (mAccessPoint.isActive()) {
-                    updateConnectingState(STATE_CONNECTED);
-                } else {
-                    updateConnectingState(STATE_DISCONNECTED);
-                }
-            }
+            refreshPage();
         }
 
         /**
@@ -516,42 +503,41 @@
         refreshMacAddress();
     }
 
-    private boolean updateAccessPoint() {
+    @VisibleForTesting
+    boolean updateAccessPoint() {
         boolean changed = false;
-        if (mWifiTracker != null) {
-            // remember mIsOutOfRange as old before updated
-            boolean oldState = mIsOutOfRange;
-            updateAccessPointFromScannedList();
-            // refresh UI if signal level changed for disconnect network.
-            changed = mRssiSignalLevel != mAccessPoint.getLevel();
-            changed |= oldState != mIsOutOfRange;
-        }
+        // remember mIsOutOfRange as old before updated
+        boolean oldState = mIsOutOfRange;
+        updateAccessPointFromScannedList();
 
         if (mAccessPoint.isActive()) {
-            // Sometimes {@link WifiManager#getCurrentNetwork()} return null after connected,
-            // refresh it if needed.
-            if (mNetwork == null) {
-                updateNetworkInfo();
-            }
+            updateNetworkInfo();
             mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
             mWifiInfo = mWifiManager.getConnectionInfo();
             if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
-                // Once connected, can't get mNetworkInfo immediately, return false and wait for
-                // next time to update UI.
+                // Once connected, can't get mNetwork immediately, return false and wait for
+                // next time to update UI. also reset {@code mIsOutOfRange}
+                mIsOutOfRange = oldState;
                 return false;
             }
-
             changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
-            // If feature for saved network not enabled, always return true.
-            return mWifiTracker == null || changed;
+        }
+
+        // signal level changed
+        changed |= mRssiSignalLevel != mAccessPoint.getLevel();
+        // In/Out of range changed
+        changed |= oldState != mIsOutOfRange;
+        // connect state changed
+        if (mConnected != mAccessPoint.isActive()) {
+            mConnected = mAccessPoint.isActive();
+            changed = true;
+            updateConnectingState(mAccessPoint.isActive() ? STATE_CONNECTED : STATE_DISCONNECTED);
         }
 
         return changed;
     }
 
     private void updateAccessPointFromScannedList() {
-        if (mWifiTracker == null) return;
-
         mIsOutOfRange = true;
 
         for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
@@ -899,13 +885,19 @@
     /**
      * Show QR code to share the network represented by this preference.
      */
-    public void launchWifiDppConfiguratorActivity() {
+    private void launchWifiDppConfiguratorActivity() {
         final Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntentOrNull(mContext,
                 mWifiManager, mAccessPoint);
 
         if (intent == null) {
             Log.e(TAG, "Launch Wi-Fi DPP QR code generator with a wrong Wi-Fi network!");
         } else {
+            mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_SETTINGS_SHARE_WIFI_QR_CODE,
+                    SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR,
+                    /* key */ null,
+                    /* value */ Integer.MIN_VALUE);
+
             mContext.startActivity(intent);
         }
     }
@@ -967,7 +959,8 @@
         return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER);
     }
 
-    private void connectNetwork() {
+    @VisibleForTesting
+    void connectNetwork() {
         final Activity activity = mFragment.getActivity();
         // error handling, connected/saved network should have mWifiConfig.
         if (mWifiConfig == null) {
@@ -1045,7 +1038,6 @@
                                     mAccessPoint.getTitle()),
                             Toast.LENGTH_SHORT).show();
 
-                    updateNetworkInfo();
                     refreshPage();
                 } else if (state == STATE_NOT_IN_RANGE) {
                     Log.d(TAG, "AP not in range");
@@ -1084,7 +1076,11 @@
                         .setButton3Enabled(false);
                 break;
             case STATE_CONNECTED:
-                mButtonsPref.setButton3Visible(false);
+                // init button state and set as invisible
+                mButtonsPref.setButton3Text(R.string.wifi_connect)
+                        .setButton3Icon(R.drawable.ic_settings_wireless)
+                        .setButton3Enabled(true)
+                        .setButton3Visible(false);
                 break;
             case STATE_DISCONNECTED:
             case STATE_NOT_IN_RANGE:
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index d0322b7..0cd7f09 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -193,6 +193,13 @@
                         return;
                     }
 
+                    mMetricsFeatureProvider.action(
+                            mMetricsFeatureProvider.getAttribution(getActivity()),
+                            SettingsEnums.ACTION_SETTINGS_ENROLL_WIFI_QR_CODE,
+                            SettingsEnums.SETTINGS_WIFI_DPP_ENROLLEE,
+                            /* key */ null,
+                            /* value */ Integer.MIN_VALUE);
+
                     notifyUserForQrCodeRecognition();
                     break;
 
diff --git a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
index ee15820..f1b0b6f 100644
--- a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
+++ b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
@@ -43,17 +43,21 @@
                 WifiDialogActivity.KEY_ACCESS_POINT_STATE);
 
         if (network != null) {
+            WifiScanWorker.clearClickedWifi();
             final ConnectivityManager cm = getSystemService(ConnectivityManager.class);
             // start captive portal app to sign in to network
             cm.startCaptivePortalApp(network);
         } else if (accessPointState != null) {
             connect(new AccessPoint(this, accessPointState));
         }
+
         finish();
     }
 
     @VisibleForTesting
     void connect(AccessPoint accessPoint) {
+        WifiScanWorker.saveClickedWifi(accessPoint);
+
         final WifiConnectListener connectListener = new WifiConnectListener(this);
         switch (WifiUtils.getConnectingType(accessPoint)) {
             case WifiUtils.CONNECT_TYPE_OSU_PROVISION:
diff --git a/src/com/android/settings/wifi/slice/WifiScanWorker.java b/src/com/android/settings/wifi/slice/WifiScanWorker.java
index b846228..e438443 100644
--- a/src/com/android/settings/wifi/slice/WifiScanWorker.java
+++ b/src/com/android/settings/wifi/slice/WifiScanWorker.java
@@ -20,6 +20,7 @@
 import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
 
 import android.content.Context;
+import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.Network;
@@ -27,9 +28,12 @@
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
 import android.net.Uri;
+import android.net.wifi.WifiInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -55,22 +59,21 @@
     CaptivePortalNetworkCallback mCaptivePortalNetworkCallback;
 
     private final Context mContext;
+    private final ConnectivityManager mConnectivityManager;
+    private final WifiTracker mWifiTracker;
 
-    private WifiTracker mWifiTracker;
-    private ConnectivityManager mConnectivityManager;
+    private static String sClickedWifiSsid;
 
     public WifiScanWorker(Context context, Uri uri) {
         super(context, uri);
         mContext = context;
         mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+        mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
+                true /* includeSaved */, true /* includeScans */);
     }
 
     @Override
     protected void onSlicePinned() {
-        if (mWifiTracker == null) {
-            mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
-                    true /* includeSaved */, true /* includeScans */);
-        }
         mWifiTracker.onStart();
         onAccessPointsChanged();
     }
@@ -79,6 +82,7 @@
     protected void onSliceUnpinned() {
         mWifiTracker.onStop();
         unregisterCaptivePortalNetworkCallback();
+        clearClickedWifi();
     }
 
     @Override
@@ -146,6 +150,19 @@
         return null;
     }
 
+    static void saveClickedWifi(AccessPoint accessPoint) {
+        sClickedWifiSsid = accessPoint.getSsidStr();
+    }
+
+    static void clearClickedWifi() {
+        sClickedWifiSsid = null;
+    }
+
+    static boolean isWifiClicked(WifiInfo info) {
+        final String ssid = WifiInfo.removeDoubleQuotes(info.getSSID());
+        return !TextUtils.isEmpty(ssid) && TextUtils.equals(ssid, sClickedWifiSsid);
+    }
+
     public void registerCaptivePortalNetworkCallback(Network wifiNetwork) {
         if (wifiNetwork == null) {
             return;
@@ -191,7 +208,7 @@
         @Override
         public void onCapabilitiesChanged(Network network,
                 NetworkCapabilities networkCapabilities) {
-            if (!mNetwork.equals(network)) {
+            if (!isSameNetwork(network)) {
                 return;
             }
 
@@ -202,6 +219,19 @@
 
             mIsCaptivePortal = isCaptivePortal;
             notifySliceChange();
+
+            // Automatically start captive portal
+            if (mIsCaptivePortal) {
+                if (!isWifiClicked(mWifiTracker.getManager().getConnectionInfo())) {
+                    return;
+                }
+
+                final Intent intent = new Intent(mContext, ConnectToWifiHandler.class)
+                        .putExtra(ConnectivityManager.EXTRA_NETWORK, network)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                // Starting activity in the system process needs to specify a user
+                mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            }
         }
 
         /**
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
index b7ddcae..1197db4 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.wifi.tether;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
 import android.net.wifi.WifiConfiguration;
@@ -27,9 +28,12 @@
 import androidx.preference.Preference;
 
 import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.ValidatedEditTextPreference;
 import com.android.settings.wifi.dpp.WifiDppUtils;
 
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
 public class WifiTetherSSIDPreferenceController extends WifiTetherBasePreferenceController
         implements ValidatedEditTextPreference.Validator {
 
@@ -41,10 +45,14 @@
     private String mSSID;
     private WifiDeviceNameTextValidator mWifiDeviceNameTextValidator;
 
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+
     public WifiTetherSSIDPreferenceController(Context context,
             OnTetherConfigUpdateListener listener) {
         super(context, listener);
+
         mWifiDeviceNameTextValidator = new WifiDeviceNameTextValidator();
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @Override
@@ -104,7 +112,15 @@
     }
 
     private void shareHotspotNetwork(Intent intent) {
-        WifiDppUtils.showLockScreen(mContext, () -> mContext.startActivity(intent));
+        WifiDppUtils.showLockScreen(mContext, () -> {
+            mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_SETTINGS_SHARE_WIFI_HOTSPOT_QR_CODE,
+                    SettingsEnums.SETTINGS_WIFI_DPP_CONFIGURATOR,
+                    /* key */ null,
+                    /* value */ Integer.MIN_VALUE);
+
+            mContext.startActivity(intent);
+        });
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
index b8ba63c..a623850 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java
@@ -34,6 +34,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
@@ -151,8 +152,11 @@
         mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mContext).startActivity(intentCaptor.capture());
-        assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
+        Intent intent = intentCaptor.getValue();
+        assertThat(intent.getComponent().getClassName()).isEqualTo(
                 MobileNetworkActivity.class.getName());
+        assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(sub1.getSubscriptionId());
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
index c074466..28a390d 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -16,14 +16,21 @@
 
 package com.android.settings.network;
 
+import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_ABSENT;
+import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.UiccSlotInfo;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -39,17 +46,25 @@
 @RunWith(RobolectricTestRunner.class)
 public class SubscriptionUtilTest {
     @Mock
-    private SubscriptionManager mManager;
+    private Context mContext;
+    @Mock
+    private SubscriptionManager mSubMgr;
+    @Mock
+    private TelephonyManager mTelMgr;
+
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        doReturn(mSubMgr).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelMgr).when(mContext).getSystemService(TelephonyManager.class);
+        when(mTelMgr.getUiccSlotsInfo()).thenReturn(null);
     }
 
     @Test
     public void getAvailableSubscriptions_nullInfoFromSubscriptionManager_nonNullResult() {
-        when(mManager.getSelectableSubscriptionInfoList()).thenReturn(null);
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(null);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
         assertThat(subs).isNotNull();
         assertThat(subs).isEmpty();
     }
@@ -58,8 +73,8 @@
     public void getAvailableSubscriptions_oneSubscription_oneResult() {
         final SubscriptionInfo info = mock(SubscriptionInfo.class);
         when(info.getMncString()).thenReturn("fake1234");
-        when(mManager.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(1);
     }
@@ -70,8 +85,8 @@
         final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
         when(info1.getMncString()).thenReturn("fake1234");
         when(info2.getMncString()).thenReturn("fake5678");
-        when(mManager.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(2);
     }
@@ -83,9 +98,9 @@
         final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
         when(info1.getSubscriptionId()).thenReturn(1);
         when(info1.getMncString()).thenReturn("fake1234");
-        when(mManager.getSelectableSubscriptionInfoList()).thenReturn(
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(
                 new ArrayList<>(Arrays.asList(info1, info2, info3)));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(1);
         assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
@@ -101,9 +116,9 @@
         when(info1.getMncString()).thenReturn("fake1234");
         when(info4.getSubscriptionId()).thenReturn(4);
         when(info4.getMncString()).thenReturn("fake5678");
-        when(mManager.getSelectableSubscriptionInfoList()).thenReturn(new ArrayList<>(
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(new ArrayList<>(
                 Arrays.asList(info1, info2, info3, info4)));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mManager);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(2);
         assertThat(subs.get(0).getSubscriptionId()).isEqualTo(1);
@@ -111,9 +126,86 @@
     }
 
     @Test
+    public void getAvailableSubscriptions_oneSelectableOneDisabledPSim_twoResults() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+
+        when(info1.getSubscriptionId()).thenReturn(111);
+        when(info1.getMncString()).thenReturn("fake111");
+        when(info1.getSimSlotIndex()).thenReturn(-1);
+        when(info1.getCardString()).thenReturn("info1_cardid");
+
+        when(info2.getSubscriptionId()).thenReturn(222);
+        when(info2.getMncString()).thenReturn("fake222");
+        when(info2.getSimSlotIndex()).thenReturn(0);
+        when(info2.getCardString()).thenReturn("info2_cardid");
+
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info1));
+        when(mSubMgr.getAllSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2));
+
+        final UiccSlotInfo info2slot = mock(UiccSlotInfo.class);
+        when(info2slot.getCardStateInfo()).thenReturn(CARD_STATE_INFO_PRESENT);
+        when(info2slot.getLogicalSlotIdx()).thenReturn(0);
+        when(info2slot.getCardId()).thenReturn("info2_cardid");
+
+        final UiccSlotInfo[] slotInfos = {info2slot};
+        when(mTelMgr.getUiccSlotsInfo()).thenReturn(slotInfos);
+
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
+        assertThat(subs).hasSize(2);
+        assertThat(subs.get(0).getSubscriptionId()).isEqualTo(111);
+        assertThat(subs.get(1).getSubscriptionId()).isEqualTo(222);
+    }
+
+
+    @Test
+    public void getAvailableSubscriptions_oneSelectableTwoDisabledPSimsOneAbsent_twoResults() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info3 = mock(SubscriptionInfo.class);
+
+        when(info1.getSubscriptionId()).thenReturn(111);
+        when(info1.getMncString()).thenReturn("fake111");
+        when(info1.getSimSlotIndex()).thenReturn(-1);
+        when(info1.getCardString()).thenReturn("info1_cardid");
+
+        when(info2.getSubscriptionId()).thenReturn(222);
+        when(info2.getMncString()).thenReturn("fake222");
+        when(info2.getSimSlotIndex()).thenReturn(-1);
+        when(info2.getCardString()).thenReturn("info2_cardid");
+
+        when(info3.getSubscriptionId()).thenReturn(333);
+        when(info3.getMncString()).thenReturn("fake333");
+        when(info3.getSimSlotIndex()).thenReturn(0);
+        when(info3.getCardString()).thenReturn("info3_cardid");
+
+        when(mSubMgr.getSelectableSubscriptionInfoList()).thenReturn(Arrays.asList(info1));
+        when(mSubMgr.getAllSubscriptionInfoList()).thenReturn(Arrays.asList(info1, info2, info3));
+
+        final UiccSlotInfo info2slot = mock(UiccSlotInfo.class);
+        final UiccSlotInfo info3slot = mock(UiccSlotInfo.class);
+
+        when(info2slot.getLogicalSlotIdx()).thenReturn(-1);
+        when(info2slot.getCardStateInfo()).thenReturn(CARD_STATE_INFO_ABSENT);
+        when(info2slot.getCardId()).thenReturn("info2_cardid");
+
+        when(info3slot.getLogicalSlotIdx()).thenReturn(0);
+        when(info3slot.getCardStateInfo()).thenReturn(CARD_STATE_INFO_PRESENT);
+        when(info3slot.getCardId()).thenReturn("info3_cardid");
+
+        final UiccSlotInfo[] slotInfos = {info2slot, info3slot};
+        when(mTelMgr.getUiccSlotsInfo()).thenReturn(slotInfos);
+
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(mContext);
+        assertThat(subs).hasSize(2);
+        assertThat(subs.get(0).getSubscriptionId()).isEqualTo(111);
+        assertThat(subs.get(1).getSubscriptionId()).isEqualTo(333);
+    }
+
+    @Test
     public void getActiveSubscriptions_nullInfoFromSubscriptionManager_nonNullResult() {
-        when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(null);
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
+        when(mSubMgr.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(null);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mSubMgr);
         assertThat(subs).isNotNull();
         assertThat(subs).isEmpty();
     }
@@ -121,8 +213,8 @@
     @Test
     public void getActiveSubscriptions_oneSubscription_oneResult() {
         final SubscriptionInfo info = mock(SubscriptionInfo.class);
-        when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(Arrays.asList(info));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
+        when(mSubMgr.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(Arrays.asList(info));
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mSubMgr);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(1);
     }
@@ -131,9 +223,9 @@
     public void getActiveSubscriptions_twoSubscriptions_twoResults() {
         final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
         final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
-        when(mManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
+        when(mSubMgr.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
                 Arrays.asList(info1, info2));
-        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mManager);
+        final List<SubscriptionInfo> subs = SubscriptionUtil.getActiveSubscriptions(mSubMgr);
         assertThat(subs).isNotNull();
         assertThat(subs).hasSize(2);
     }
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
index 68f8c91..f38f2a2 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
@@ -33,15 +33,18 @@
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.view.Menu;
 import android.view.View;
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.android.settings.R;
+import com.android.settings.network.SubscriptionUtil;
 
 import com.google.android.material.bottomnavigation.BottomNavigationView;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,6 +55,7 @@
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import androidx.fragment.app.Fragment;
@@ -73,6 +77,8 @@
     @Mock
     private SubscriptionManager mSubscriptionManager;
     @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
     private SubscriptionInfo mSubscriptionInfo;
     @Mock
     private SubscriptionInfo mSubscriptionInfo2;
@@ -99,6 +105,8 @@
 
         doReturn(mSubscriptionManager).when(mMobileNetworkActivity).getSystemService(
                 SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mMobileNetworkActivity).getSystemService(
+                TelephonyManager.class);
         doReturn(mBottomNavigationView).when(mMobileNetworkActivity).findViewById(R.id.bottom_nav);
         doReturn(mFragmentManager).when(mMobileNetworkActivity).getSupportFragmentManager();
         doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
@@ -108,6 +116,11 @@
                 MOBILE_SETTINGS_TAG + CURRENT_SUB_ID);
     }
 
+    @After
+    public void tearDown() {
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
+    }
+
     @Test
     public void updateBottomNavigationView_oneSubscription_shouldBeGone() {
         mSubscriptionInfos.add(mSubscriptionInfo);
@@ -169,7 +182,7 @@
         doReturn(intent).when(mMobileNetworkActivity).getIntent();
         mSubscriptionInfos.add(mSubscriptionInfo);
         mSubscriptionInfos.add(mSubscriptionInfo2);
-        doReturn(mSubscriptionInfos).when(mSubscriptionManager).getSelectableSubscriptionInfoList();
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(mSubscriptionInfos);
         doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(CURRENT_SUB_ID);
 
         assertThat(mMobileNetworkActivity.getSubscriptionId()).isEqualTo(CURRENT_SUB_ID);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
index 6d85826..a10227f 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -99,13 +100,22 @@
     }
 
     @Test
-    public void displayPreference_onlyOneSubscription_switchBarHidden() {
+    public void displayPreference_oneEnabledSubscription_switchBarHidden() {
+        doReturn(true).when(mSubscriptionManager).isSubscriptionEnabled(mSubId);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
         mController.displayPreference(mScreen);
         assertThat(mSwitchBar.isShowing()).isFalse();
     }
 
     @Test
+    public void displayPreference_oneDisabledSubscription_switchBarNotHidden() {
+        doReturn(false).when(mSubscriptionManager).isSubscriptionEnabled(mSubId);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
+        mController.displayPreference(mScreen);
+        assertThat(mSwitchBar.isShowing()).isTrue();
+    }
+
+    @Test
     public void displayPreference_subscriptionEnabled_switchIsOn() {
         when(mSubscriptionManager.isSubscriptionEnabled(mSubId)).thenReturn(true);
         mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 906c55c..d4ce481 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -35,6 +35,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
@@ -83,7 +84,6 @@
 import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -96,6 +96,7 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowToast;
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
@@ -106,7 +107,6 @@
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
-@Ignore("b/130896210")
 public class WifiDetailPreferenceControllerTest {
 
     private static final int LEVEL = 1;
@@ -118,6 +118,7 @@
     private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
     private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
     private static final String SECURITY = "None";
+    private static final String FQDN = "fqdn";
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private PreferenceScreen mockScreen;
@@ -299,7 +300,7 @@
         list.add(mockAccessPoint);
         when(mockWifiTracker.getAccessPoints()).thenReturn(list);
         WifiTrackerFactory.setTestingWifiTracker(mockWifiTracker);
-        when(mockAccessPoint.matches(any(WifiConfiguration.class))).thenReturn(true);
+        when(mockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
         when(mockAccessPoint.isReachable()).thenReturn(true);
 
         mController = newWifiDetailPreferenceController();
@@ -311,7 +312,7 @@
         list.add(mockAccessPoint);
         when(mockWifiTracker.getAccessPoints()).thenReturn(list);
         WifiTrackerFactory.setTestingWifiTracker(mockWifiTracker);
-        when(mockAccessPoint.matches(any(WifiConfiguration.class))).thenReturn(true);
+        when(mockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
         when(mockAccessPoint.isReachable()).thenReturn(true);
 
         mController = newWifiDetailPreferenceController();
@@ -323,7 +324,7 @@
         list.add(mockAccessPoint);
         when(mockWifiTracker.getAccessPoints()).thenReturn(list);
         WifiTrackerFactory.setTestingWifiTracker(mockWifiTracker);
-        when(mockAccessPoint.matches(any(WifiConfiguration.class))).thenReturn(false);
+        when(mockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
         when(mockAccessPoint.isReachable()).thenReturn(false);
 
         mController = newWifiDetailPreferenceController();
@@ -1114,12 +1115,13 @@
         FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, false);
 
         mockWifiConfig.networkId = 5;
-        when(mockWifiConfig.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.getPasspointFqdn()).thenReturn(FQDN);
 
         mController.displayPreference(mockScreen);
         mForgetClickListener.getValue().onClick(null);
 
-        verify(mockWifiManager).removePasspointConfiguration(mockWifiConfig.FQDN);
+        verify(mockWifiManager).removePasspointConfiguration(FQDN);
         verify(mockMetricsFeatureProvider)
                 .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
     }
@@ -1130,13 +1132,14 @@
         final WifiDetailPreferenceController spyController = spy(mController);
 
         mockWifiConfig.networkId = 5;
-        when(mockWifiConfig.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.isPasspoint()).thenReturn(true);
+        when(mockAccessPoint.getPasspointFqdn()).thenReturn(FQDN);
         spyController.displayPreference(mockScreen);
         FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
 
         mForgetClickListener.getValue().onClick(null);
 
-        verify(mockWifiManager, times(0)).removePasspointConfiguration(mockWifiConfig.FQDN);
+        verify(mockWifiManager, times(0)).removePasspointConfiguration(FQDN);
         verify(mockMetricsFeatureProvider, times(0))
                 .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
         verify(spyController).showConfirmForgetDialog();
@@ -1310,6 +1313,406 @@
     }
 
     @Test
+    public void testConnectButton_shouldInvisibleForConnectNetwork() {
+        setUpForConnectedNetwork();
+
+        displayAndResume();
+
+        verify(mockButtonsPref, times(1)).setButton3Visible(false);
+    }
+
+    @Test
+    public void testConnectButton_shouldVisibleForDisconnectNetwork() {
+        setUpForDisconnectedNetwork();
+
+        displayAndResume();
+
+        verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+    }
+
+    private void setUpForToast() {
+        Resources res = mContext.getResources();
+        when(mockActivity.getResources()).thenReturn(res);
+    }
+
+    @Test
+    public void testConnectButton_clickConnect_displayAsSuccess() {
+        setUpForDisconnectedNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+        InOrder inOrder = inOrder(mockButtonsPref);
+        String label = "title";
+        when(mockAccessPoint.getTitle()).thenReturn(label);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check display button as connecting
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as connected
+        when(mockAccessPoint.isActive()).thenReturn(true);
+        mController.updateAccessPoint();
+
+        // check connect button invisible, be init as default state and toast success message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(false);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_connected_to_message, label));
+    }
+
+    @Test
+    public void testConnectButton_clickConnectButFailed_displayFailMessage() {
+        setUpForDisconnectedNetwork();
+        ArgumentCaptor<WifiManager.ActionListener> connectListenerCaptor =
+                ArgumentCaptor.forClass(WifiManager.ActionListener.class);
+        when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check display button as connecting
+        verify(mockWifiManager, times(1)).connect(anyInt(), connectListenerCaptor.capture());
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as failed
+        connectListenerCaptor.getValue().onFailure(-1);
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_failed_connect_message));
+    }
+
+    private void verifyConnectBtnSetUpAsVisible(InOrder inOrder) {
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+    }
+
+    private void verifyConnectBtnSetUpAsConnecting(InOrder inOrder) {
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connecting);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Enabled(false);
+    }
+
+    private void verifyConnectBtnBeInitAsDefault(InOrder inOrder) {
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Enabled(true);
+    }
+
+    @Test
+    public void testConnectButton_clickConnectButTimeout_displayFailMessage() {
+        setUpForDisconnectedNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check display button as connecting
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as failed
+        mController.mTimer.onFinish();
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_failed_connect_message));
+    }
+
+    @Test
+    public void testConnectButton_clickConnectButTimeout_displayNotInRangeMessage() {
+        setUpForNotInRangeNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check display button as connecting
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as failed
+        mController.mTimer.onFinish();
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_not_in_range_message));
+    }
+
+    @Test
+    public void testConnectButton_clickConnectWhenWiFiDisabled_displaySuccessMessage() {
+        setUpForDisconnectedNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+        InOrder inOrder = inOrder(mockButtonsPref);
+        String label = "title";
+        when(mockAccessPoint.getTitle()).thenReturn(label);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+        verify(mockWifiManager, times(1)).setWifiEnabled(true);
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_turned_on_message));
+
+        // notify Wi-Fi enabled
+        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+        // check had connect network and icon display as expected
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as connected
+        when(mockAccessPoint.isActive()).thenReturn(true);
+        mController.updateAccessPoint();
+
+        // check connect button invisible, be init as default state and toast success message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(false);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_connected_to_message, label));
+    }
+
+    @Test
+    public void testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWiFi() {
+        setUpForDisconnectedNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+        verify(mockWifiManager, times(1)).setWifiEnabled(true);
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_turned_on_message));
+
+        // notify Wi-Fi enabled
+        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+        // check had connect network and icon display as expected
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as failed
+        mController.mTimer.onFinish();
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_failed_connect_message));
+    }
+
+    @Test
+    public void
+            testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWifiBecauseNotInRange() {
+        setUpForNotInRangeNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+        verify(mockWifiManager, times(1)).setWifiEnabled(true);
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_turned_on_message));
+
+        // notify Wi-Fi enabled
+        mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+        // check had connect network and icon display as expected
+        verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+
+        // update as failed
+        mController.mTimer.onFinish();
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_not_in_range_message));
+    }
+
+    @Test
+    public void testConnectButton_clickConnectWhenWiFiDisabled_failedToEnableWifi() {
+        setUpForDisconnectedNetwork();
+        when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+        InOrder inOrder = inOrder(mockButtonsPref);
+        setUpForToast();
+
+        displayAndResume();
+
+        // check connect button exist
+        verifyConnectBtnSetUpAsVisible(inOrder);
+
+        // click connect button
+        mController.connectNetwork();
+
+        // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+        verify(mockWifiManager, times(1)).setWifiEnabled(true);
+        verifyConnectBtnSetUpAsConnecting(inOrder);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_turned_on_message));
+
+        // notify turn on Wi-Fi failed
+        mController.mTimer.onFinish();
+
+        // check connect button visible, be init as default and toast failed message
+        verifyConnectBtnBeInitAsDefault(inOrder);
+        inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_failed_connect_message));
+    }
+
+    @Test
+    public void updateAccessPoint_returnFalseForNothingChanged() {
+        setUpForDisconnectedNetwork();
+
+        displayAndResume();
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isFalse();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForSignalLevelChanged() {
+        setUpForDisconnectedNetwork();
+
+        displayAndResume();
+
+        // Level changed
+        when(mockAccessPoint.getLevel()).thenReturn(LEVEL + 1);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForChangeAsNotInRange() {
+        setUpForDisconnectedNetwork();
+
+        displayAndResume();
+
+        // change as not in range
+        when(mockAccessPoint.matches(any(AccessPoint.class))).thenReturn(false);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForChangeAsInRange() {
+        setUpForNotInRangeNetwork();
+
+        displayAndResume();
+
+        // change as in range
+        when(mockAccessPoint.matches(any(AccessPoint.class))).thenReturn(true);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForChangeAsConnected() {
+        setUpForDisconnectedNetwork();
+
+        displayAndResume();
+
+        // change as connected
+        when(mockAccessPoint.isActive()).thenReturn(true);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForChangeAsDisconnected() {
+        setUpForConnectedNetwork();
+
+        displayAndResume();
+
+        // change as disconnected
+        when(mockAccessPoint.isActive()).thenReturn(false);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
+    public void updateAccessPoint_returnTrueForAccessPointUpdated() {
+        setUpForConnectedNetwork();
+
+        displayAndResume();
+
+        // change as disconnected
+        when(mockAccessPoint.update(mockWifiConfig, mockWifiInfo, mockNetworkInfo))
+                .thenReturn(true);
+        boolean changed = mController.updateAccessPoint();
+
+        assertThat(changed).isTrue();
+    }
+
+    @Test
     public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSameForConnectedNetwork() {
         setUpForConnectedNetwork();
         displayAndResume();
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ConnectToWifiHandlerTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ConnectToWifiHandlerTest.java
index b18102d..cea8365 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/ConnectToWifiHandlerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ConnectToWifiHandlerTest.java
@@ -27,7 +27,6 @@
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.net.wifi.WifiManager;
 
-import com.android.settings.testutils.shadow.ShadowConnectivityManager;
 import com.android.settings.testutils.shadow.ShadowWifiManager;
 import com.android.settingslib.wifi.AccessPoint;
 
@@ -41,13 +40,10 @@
 import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {
-        ShadowConnectivityManager.class,
-        ShadowWifiManager.class,
-})
+@Config(shadows = ShadowWifiManager.class)
 public class ConnectToWifiHandlerTest {
 
-    private static final String AP1_SSID = "\"ap1\"";
+    private static final String AP_SSID = "\"ap\"";
     private ConnectToWifiHandler mHandler;
     private WifiConfiguration mWifiConfig;
     @Mock
@@ -59,7 +55,7 @@
 
         mHandler = Robolectric.setupActivity(ConnectToWifiHandler.class);
         mWifiConfig = new WifiConfiguration();
-        mWifiConfig.SSID = AP1_SSID;
+        mWifiConfig.SSID = AP_SSID;
         doReturn(mWifiConfig).when(mAccessPoint).getConfig();
     }
 
@@ -70,7 +66,7 @@
 
         mHandler.connect(mAccessPoint);
 
-        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP1_SSID);
+        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
     }
 
     @Test
@@ -91,7 +87,7 @@
 
         mHandler.connect(mAccessPoint);
 
-        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP1_SSID);
+        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
     }
 
     @Test
@@ -104,7 +100,7 @@
 
         mHandler.connect(mAccessPoint);
 
-        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP1_SSID);
+        assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP_SSID);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
index 30e289b..19d3e40 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
@@ -20,36 +20,54 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiSsid;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import androidx.slice.SliceProvider;
 import androidx.slice.widget.SliceLiveData;
 
+import com.android.settings.testutils.shadow.ShadowWifiManager;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowWifiManager.class,
+        WifiScanWorkerTest.ShadowWifiTracker.class,
+})
 public class WifiScanWorkerTest {
 
     private static final String AP_NAME = "ap";
@@ -59,6 +77,7 @@
     private WifiManager mWifiManager;
     private ConnectivityManager mConnectivityManager;
     private WifiScanWorker mWifiScanWorker;
+    private ConnectToWifiHandler mConnectToWifiHandler;
 
     @Before
     public void setUp() {
@@ -73,6 +92,12 @@
 
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
         mWifiScanWorker = new WifiScanWorker(mContext, WIFI_SLICE_URI);
+        mConnectToWifiHandler = Robolectric.setupActivity(ConnectToWifiHandler.class);
+    }
+
+    @After
+    public void tearDown() {
+        mWifiScanWorker.clearClickedWifi();
     }
 
     @Test
@@ -131,4 +156,82 @@
 
         verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
     }
+
+    private AccessPoint createAccessPoint(String ssid) {
+        final AccessPoint accessPoint = mock(AccessPoint.class);
+        doReturn(ssid).when(accessPoint).getSsidStr();
+        return accessPoint;
+    }
+
+    private void setConnectionInfoSSID(String ssid) {
+        final WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(ssid));
+        ShadowWifiManager.get().setConnectionInfo(wifiInfo);
+    }
+
+    @Test
+    public void NetworkCallback_onCapabilitiesChanged_isClickedWifi_shouldStartActivity() {
+        final AccessPoint accessPoint = createAccessPoint("ap1");
+        setConnectionInfoSSID("ap1");
+        final Network network = mConnectivityManager.getActiveNetwork();
+        mWifiScanWorker.registerCaptivePortalNetworkCallback(network);
+
+        mConnectToWifiHandler.connect(accessPoint);
+        mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network,
+                WifiSliceTest.makeCaptivePortalNetworkCapabilities());
+
+        verify(mContext).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
+    }
+
+    @Test
+    public void NetworkCallback_onCapabilitiesChanged_isNotClickedWifi_shouldNotStartActivity() {
+        final AccessPoint accessPoint = createAccessPoint("ap1");
+        setConnectionInfoSSID("ap2");
+        final Network network = mConnectivityManager.getActiveNetwork();
+        mWifiScanWorker.registerCaptivePortalNetworkCallback(network);
+
+        mConnectToWifiHandler.connect(accessPoint);
+        mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network,
+                WifiSliceTest.makeCaptivePortalNetworkCapabilities());
+
+        verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
+    }
+
+    @Test
+    public void NetworkCallback_onCapabilitiesChanged_neverClickWifi_shouldNotStartActivity() {
+        setConnectionInfoSSID("ap1");
+        final Network network = mConnectivityManager.getActiveNetwork();
+        mWifiScanWorker.registerCaptivePortalNetworkCallback(network);
+
+        mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network,
+                WifiSliceTest.makeCaptivePortalNetworkCapabilities());
+
+        verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
+    }
+
+    @Test
+    public void NetworkCallback_onCapabilitiesChanged_sliceIsUnpinned_shouldNotStartActivity() {
+        final AccessPoint accessPoint = createAccessPoint("ap1");
+        setConnectionInfoSSID("ap1");
+        final Network network = mConnectivityManager.getActiveNetwork();
+        mWifiScanWorker.registerCaptivePortalNetworkCallback(network);
+        final WifiScanWorker.CaptivePortalNetworkCallback callback =
+                mWifiScanWorker.mCaptivePortalNetworkCallback;
+
+        mWifiScanWorker.onSlicePinned();
+        mConnectToWifiHandler.connect(accessPoint);
+        mWifiScanWorker.onSliceUnpinned();
+        callback.onCapabilitiesChanged(network,
+                WifiSliceTest.makeCaptivePortalNetworkCapabilities());
+
+        verify(mContext, never()).startActivityAsUser(any(Intent.class), eq(UserHandle.CURRENT));
+    }
+
+    @Implements(WifiTracker.class)
+    public static class ShadowWifiTracker {
+        @Implementation
+        public void onStart() {
+            // do nothing
+        }
+    }
 }