Rework Add Wifi page for cleaner code

Connect button is only usable if the security type is None. Otherwise,
connection goes through the password edit text preference.

If a password is added without a network name set, the confirmation will
show a toast asking the user to set a network name.

Bug: 131921349
Test: manual, robolectric
Change-Id: Id2a5060ab61aa393e2a38d78547d2b33e2c5c77d
diff --git a/res/values/preference_keys.xml b/res/values/preference_keys.xml
index ea66364..a97df25 100644
--- a/res/values/preference_keys.xml
+++ b/res/values/preference_keys.xml
@@ -86,7 +86,6 @@
     <string name="pk_add_wifi" translatable="false">add_wifi</string>
     <string name="pk_wifi_status" translatable="false">wifi_status</string>
     <string name="pk_add_wifi_network_name" translatable="false">add_wifi_network_name</string>
-    <string name="pk_add_wifi_security_group" translatable="false">add_wifi_security_group</string>
     <string name="pk_add_wifi_security" translatable="false">add_wifi_security</string>
     <string name="pk_add_wifi_password" translatable="false">add_wifi_password</string>
     <string name="pk_wifi_preferences" translatable="false">wifi_preferences</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5133e26..2d349bc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -137,6 +137,8 @@
     <string name="wifi_password">Password</string>
     <!-- Label for the check box to show password -->
     <string name="wifi_show_password">Show password</string>
+    <!-- Toast message when trying to connect to a hidden wifi network without a network name. [CHAR LIMIT=NONE] -->
+    <string name="wifi_no_network_name">Please enter a network name</string>
     <!-- Label for the SSID of the network -->
     <string name="wifi_ssid">Network name</string>
     <!-- Hint for a text field to enter the SSID of a hidden wifi network. [CHAR LIMIT=35] -->
diff --git a/res/xml/add_wifi_fragment.xml b/res/xml/add_wifi_fragment.xml
index 0b812b6..c164f77 100644
--- a/res/xml/add_wifi_fragment.xml
+++ b/res/xml/add_wifi_fragment.xml
@@ -21,9 +21,20 @@
     android:title="@string/wifi_setup_add_network">
     <EditTextPreference
         android:key="@string/pk_add_wifi_network_name"
+        android:persistent="false"
         android:title="@string/wifi_ssid"
         settings:controller="com.android.car.settings.wifi.NetworkNamePreferenceController"/>
-    <com.android.car.settings.common.LogicalPreferenceGroup
-        android:key="@string/pk_add_wifi_security_group"
-        settings:controller="com.android.car.settings.wifi.NetworkSecurityGroupPreferenceController"/>
+    <ListPreference
+        android:dialogTitle="@string/wifi_security"
+        android:key="@string/pk_add_wifi_security"
+        android:persistent="false"
+        android:title="@string/wifi_security"
+        settings:controller="com.android.car.settings.wifi.NetworkSecurityPreferenceController"/>
+    <com.android.car.settings.common.PasswordEditTextPreference
+        android:dialogTitle="@string/wifi_password"
+        android:key="@string/pk_add_wifi_password"
+        android:persistent="false"
+        android:summary="@string/default_password_summary"
+        android:title="@string/wifi_password"
+        settings:controller="com.android.car.settings.wifi.NetworkPasswordPreferenceController"/>
 </PreferenceScreen>
diff --git a/res/xml/wifi_list_fragment.xml b/res/xml/wifi_list_fragment.xml
index 9151312..bcd287f 100644
--- a/res/xml/wifi_list_fragment.xml
+++ b/res/xml/wifi_list_fragment.xml
@@ -25,6 +25,7 @@
         settings:controller="com.android.car.settings.wifi.AccessPointListPreferenceController"/>
     <Preference
         android:fragment="com.android.car.settings.wifi.AddWifiFragment"
+        android:icon="@drawable/ic_add"
         android:key="@string/pk_add_wifi"
         android:title="@string/wifi_setup_add_network"
         settings:controller="com.android.car.settings.wifi.AddWifiPreferenceController"/>
diff --git a/src/com/android/car/settings/wifi/AddNetworkBasePreferenceController.java b/src/com/android/car/settings/wifi/AddNetworkBasePreferenceController.java
deleted file mode 100644
index 8cb248e..0000000
--- a/src/com/android/car/settings/wifi/AddNetworkBasePreferenceController.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settings.wifi;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-
-import androidx.preference.Preference;
-
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.PreferenceController;
-import com.android.settingslib.wifi.AccessPoint;
-
-/**
- * Common code for preference controllers related to adding a new network.
- *
- * @param <V> the upper bound on the type of {@link Preference} on which the controller
- *            expects to operate.
- */
-public abstract class AddNetworkBasePreferenceController<V extends Preference> extends
-        PreferenceController<V> {
-
-    private AccessPoint mAccessPoint;
-
-    public AddNetworkBasePreferenceController(Context context, String preferenceKey,
-            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
-        super(context, preferenceKey, fragmentController, uxRestrictions);
-    }
-
-    /** Sets the access point. */
-    public void setAccessPoint(AccessPoint accessPoint) {
-        mAccessPoint = accessPoint;
-    }
-
-    /** Returns the access point. */
-    public AccessPoint getAccessPoint() {
-        return mAccessPoint;
-    }
-
-    /** Returns {@code true} if access point was set. */
-    public boolean hasAccessPoint() {
-        return mAccessPoint != null;
-    }
-}
diff --git a/src/com/android/car/settings/wifi/AddWifiFragment.java b/src/com/android/car/settings/wifi/AddWifiFragment.java
index 0690eca..000a53a 100644
--- a/src/com/android/car/settings/wifi/AddWifiFragment.java
+++ b/src/com/android/car/settings/wifi/AddWifiFragment.java
@@ -16,31 +16,55 @@
 
 package com.android.car.settings.wifi;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.net.wifi.WifiManager;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.widget.Button;
 
 import androidx.annotation.LayoutRes;
 import androidx.annotation.XmlRes;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
 import com.android.car.settings.R;
 import com.android.car.settings.common.Logger;
 import com.android.car.settings.common.SettingsFragment;
+import com.android.settingslib.wifi.AccessPoint;
 
 /**
- * Adds a wifi network, the network can be public or private. If ADD_NETWORK_MODE is not specified
- * in the intent, then it needs to contain AccessPoint information, which is be use that to
- * render UI, e.g. show SSID etc.
+ * Adds a hidden wifi network. The connect button on the fragment is only used for unsecure hidden
+ * networks. The remaining security types can be connected via pressing connect on the password
+ * dialog.
  */
 public class AddWifiFragment extends SettingsFragment {
     private static final Logger LOG = new Logger(AddWifiFragment.class);
+    private static final String KEY_NETWORK_NAME = "network_name";
+    private static final String KEY_SECURITY_TYPE = "security_type";
 
-    private WifiManager mWifiManager;
+    private final BroadcastReceiver mNameChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mNetworkName = intent.getStringExtra(
+                    NetworkNamePreferenceController.KEY_NETWORK_NAME);
+            setButtonEnabledState();
+        }
+    };
+
+    private final BroadcastReceiver mSecurityChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mSecurityType = intent.getIntExtra(
+                    NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                    AccessPoint.SECURITY_NONE);
+            setButtonEnabledState();
+        }
+    };
+
     private Button mAddWifiButton;
-
-    private int mSelectedPosition = AccessPointSecurity.SECURITY_NONE_POSITION;
+    private String mNetworkName;
+    private int mSecurityType = AccessPoint.SECURITY_NONE;
 
     @Override
     @XmlRes
@@ -55,16 +79,19 @@
     }
 
     @Override
-    public void onAttach(Context context) {
-        super.onAttach(context);
-        mWifiManager = getContext().getSystemService(WifiManager.class);
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (savedInstanceState != null) {
+            mNetworkName = savedInstanceState.getString(KEY_NETWORK_NAME);
+            mSecurityType = savedInstanceState.getInt(KEY_SECURITY_TYPE, AccessPoint.SECURITY_NONE);
+        }
+    }
 
-        use(NetworkNamePreferenceController.class, R.string.pk_add_wifi_network_name)
-                .setTextChangeListener(newName -> {
-                    if (mAddWifiButton != null) {
-                        mAddWifiButton.setEnabled(!TextUtils.isEmpty(newName));
-                    }
-                });
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putString(KEY_NETWORK_NAME, mNetworkName);
+        outState.putInt(KEY_SECURITY_TYPE, mSecurityType);
     }
 
     @Override
@@ -73,19 +100,12 @@
 
         mAddWifiButton = getActivity().findViewById(R.id.action_button1);
         mAddWifiButton.setText(R.string.wifi_setup_connect);
-        mAddWifiButton.setEnabled(false);
+        setButtonEnabledState();
 
-        // This only needs to handle hidden networks.
+        // This only needs to handle hidden/unsecure networks.
         mAddWifiButton.setOnClickListener(v -> {
-            // TODO: revisit to remove references to controllers here.
-            NetworkNamePreferenceController useController = use(
-                    NetworkNamePreferenceController.class, R.string.pk_add_wifi_network_name);
-            NetworkSecurityGroupPreferenceController controller = use(
-                    NetworkSecurityGroupPreferenceController.class,
-                    R.string.pk_add_wifi_security_group);
-            int netId = WifiUtil.connectToAccessPoint(getContext(), useController.getNetworkName(),
-                    controller.getSelectedSecurityType(),
-                    controller.getPasswordText(), /* hidden= */ true);
+            int netId = WifiUtil.connectToAccessPoint(getContext(), mNetworkName,
+                    AccessPoint.SECURITY_NONE, /* password= */ null, /* hidden= */ true);
 
             LOG.d("connected to netId: " + netId);
             if (netId != WifiUtil.INVALID_NET_ID) {
@@ -93,4 +113,27 @@
             }
         });
     }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        LocalBroadcastManager.getInstance(getContext()).registerReceiver(mNameChangeReceiver,
+                new IntentFilter(NetworkNamePreferenceController.ACTION_NAME_CHANGE));
+        LocalBroadcastManager.getInstance(getContext()).registerReceiver(mSecurityChangeReceiver,
+                new IntentFilter(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE));
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mNameChangeReceiver);
+        LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mSecurityChangeReceiver);
+    }
+
+    private void setButtonEnabledState() {
+        if (mAddWifiButton != null) {
+            mAddWifiButton.setEnabled(
+                    !TextUtils.isEmpty(mNetworkName) && mSecurityType == AccessPoint.SECURITY_NONE);
+        }
+    }
 }
diff --git a/src/com/android/car/settings/wifi/NetworkNamePreferenceController.java b/src/com/android/car/settings/wifi/NetworkNamePreferenceController.java
index d08e5cd..b58f5c7 100644
--- a/src/com/android/car/settings/wifi/NetworkNamePreferenceController.java
+++ b/src/com/android/car/settings/wifi/NetworkNamePreferenceController.java
@@ -18,18 +18,24 @@
 
 import android.car.drivingstate.CarUxRestrictions;
 import android.content.Context;
+import android.content.Intent;
 import android.text.TextUtils;
 
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import androidx.preference.EditTextPreference;
 
 import com.android.car.settings.R;
 import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceController;
 
 /** Business logic for adding/displaying the network name. */
-public class NetworkNamePreferenceController extends
-        AddNetworkBasePreferenceController<EditTextPreference> {
+public class NetworkNamePreferenceController extends PreferenceController<EditTextPreference> {
 
-    private NetworkNameChangeListener mListener;
+    /** Action used in the {@link Intent} sent by the {@link LocalBroadcastManager}. */
+    public static final String ACTION_NAME_CHANGE =
+            "com.android.car.settings.wifi.NameChangeAction";
+    /** Key used to store the name of the network. */
+    public static final String KEY_NETWORK_NAME = "network_name";
 
     public NetworkNamePreferenceController(Context context, String preferenceKey,
             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
@@ -41,26 +47,6 @@
         return EditTextPreference.class;
     }
 
-    /** Returns the currently inputted network name. */
-    public String getNetworkName() {
-        return getPreference().getText();
-    }
-
-    /** Sets the listener that is triggered on network name change. */
-    public void setTextChangeListener(NetworkNameChangeListener listener) {
-        mListener = listener;
-    }
-
-    @Override
-    protected void onStartInternal() {
-        if (hasAccessPoint()) {
-            getPreference().setText(getAccessPoint().getSsid().toString());
-            getPreference().setSelectable(false);
-        } else {
-            getPreference().setText(null);
-        }
-    }
-
     @Override
     protected void updateState(EditTextPreference preference) {
         preference.setSummary(TextUtils.isEmpty(preference.getText()) ? getContext().getString(
@@ -69,20 +55,16 @@
 
     @Override
     protected boolean handlePreferenceChanged(EditTextPreference preference, Object newValue) {
-        preference.setText(newValue.toString());
-        if (mListener != null) {
-            mListener.onNetworkNameChanged(newValue.toString());
-        }
+        String name = newValue.toString();
+        preference.setText(name);
+        notifyNameChange(name);
         refreshUi();
         return true;
     }
 
-    /** A listener associated with the network name. */
-    public interface NetworkNameChangeListener {
-        /**
-         * This method is called when the network name has changed. The new name is provided as an
-         * argument.
-         */
-        void onNetworkNameChanged(String newName);
+    private void notifyNameChange(String newName) {
+        Intent intent = new Intent(ACTION_NAME_CHANGE);
+        intent.putExtra(KEY_NETWORK_NAME, newName);
+        LocalBroadcastManager.getInstance(getContext()).sendBroadcastSync(intent);
     }
 }
diff --git a/src/com/android/car/settings/wifi/NetworkPasswordPreferenceController.java b/src/com/android/car/settings/wifi/NetworkPasswordPreferenceController.java
new file mode 100644
index 0000000..0b82f11
--- /dev/null
+++ b/src/com/android/car/settings/wifi/NetworkPasswordPreferenceController.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.settings.wifi;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.TextUtils;
+import android.widget.Toast;
+
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.Logger;
+import com.android.car.settings.common.PasswordEditTextPreference;
+import com.android.car.settings.common.PreferenceController;
+import com.android.settingslib.wifi.AccessPoint;
+
+/** Business logic relating to the security type and associated password. */
+public class NetworkPasswordPreferenceController extends
+        PreferenceController<PasswordEditTextPreference> {
+
+    private static final Logger LOG = new Logger(NetworkPasswordPreferenceController.class);
+
+    private final BroadcastReceiver mNameChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mNetworkName = intent.getStringExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME);
+            refreshUi();
+        }
+    };
+
+    private final BroadcastReceiver mSecurityChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mSecurityType = intent.getIntExtra(
+                    NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                    AccessPoint.SECURITY_NONE);
+            refreshUi();
+        }
+    };
+
+    private String mNetworkName;
+    private int mSecurityType = AccessPoint.SECURITY_NONE;
+
+    public NetworkPasswordPreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+    }
+
+    @Override
+    protected Class<PasswordEditTextPreference> getPreferenceType() {
+        return PasswordEditTextPreference.class;
+    }
+
+    @Override
+    protected void onStartInternal() {
+        LocalBroadcastManager.getInstance(getContext()).registerReceiver(mNameChangeReceiver,
+                new IntentFilter(NetworkNamePreferenceController.ACTION_NAME_CHANGE));
+        LocalBroadcastManager.getInstance(getContext()).registerReceiver(mSecurityChangeReceiver,
+                new IntentFilter(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE));
+    }
+
+    @Override
+    protected void onStopInternal() {
+        LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mNameChangeReceiver);
+        LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mSecurityChangeReceiver);
+    }
+
+    @Override
+    protected void updateState(PasswordEditTextPreference preference) {
+        if (TextUtils.isEmpty(mNetworkName)) {
+            getPreference().setDialogTitle(R.string.wifi_password);
+        } else {
+            getPreference().setDialogTitle(mNetworkName);
+        }
+        preference.setVisible(mSecurityType != AccessPoint.SECURITY_NONE);
+    }
+
+    @Override
+    protected boolean handlePreferenceChanged(PasswordEditTextPreference preference,
+            Object newValue) {
+        if (TextUtils.isEmpty(mNetworkName)) {
+            Toast.makeText(getContext(), R.string.wifi_no_network_name, Toast.LENGTH_SHORT).show();
+            return true;
+        }
+
+        String password = newValue.toString();
+        int netId = WifiUtil.connectToAccessPoint(getContext(), mNetworkName, mSecurityType,
+                password, /* hidden= */ true);
+
+        LOG.d("connected to netId: " + netId);
+        if (netId != WifiUtil.INVALID_NET_ID) {
+            getFragmentController().goBack();
+        }
+
+        return true;
+    }
+}
diff --git a/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceController.java b/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceController.java
deleted file mode 100644
index b93ae50..0000000
--- a/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceController.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settings.wifi;
-
-import android.car.drivingstate.CarUxRestrictions;
-import android.content.Context;
-import android.text.InputType;
-import android.text.TextUtils;
-
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceGroup;
-
-import com.android.car.settings.R;
-import com.android.car.settings.common.FragmentController;
-import com.android.car.settings.common.PasswordEditTextPreference;
-import com.android.settingslib.wifi.AccessPoint;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Business logic relating to the security type and associated password. */
-public class NetworkSecurityGroupPreferenceController extends
-        AddNetworkBasePreferenceController<PreferenceGroup> {
-
-    private static final Map<Integer, Integer> SECURITY_TYPE_TO_DESC_RES = new HashMap<>();
-
-    static {
-        SECURITY_TYPE_TO_DESC_RES.put(AccessPoint.SECURITY_NONE, R.string.wifi_security_none);
-        SECURITY_TYPE_TO_DESC_RES.put(AccessPoint.SECURITY_WEP, R.string.wifi_security_wep);
-        SECURITY_TYPE_TO_DESC_RES.put(AccessPoint.SECURITY_PSK, R.string.wifi_security_psk_generic);
-        SECURITY_TYPE_TO_DESC_RES.put(AccessPoint.SECURITY_EAP, R.string.wifi_security_eap);
-    }
-
-    private static final List<Integer> SECURITY_TYPES = Arrays.asList(
-            AccessPoint.SECURITY_NONE,
-            AccessPoint.SECURITY_WEP,
-            AccessPoint.SECURITY_PSK,
-            AccessPoint.SECURITY_EAP);
-
-    private final CharSequence[] mSecurityTypeNames;
-    private final CharSequence[] mSecurityTypeIds;
-    private ListPreference mSecurityTypePreference;
-    private PasswordEditTextPreference mPasswordTextPreference;
-    private int mSelectedSecurityType;
-
-    public NetworkSecurityGroupPreferenceController(Context context, String preferenceKey,
-            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
-        super(context, preferenceKey, fragmentController, uxRestrictions);
-
-        // Security type setup.
-        mSecurityTypeNames = new CharSequence[SECURITY_TYPES.size()];
-        mSecurityTypeIds = new CharSequence[SECURITY_TYPES.size()];
-        mSelectedSecurityType = AccessPoint.SECURITY_NONE;
-
-        for (int i = 0; i < SECURITY_TYPES.size(); i++) {
-            int type = SECURITY_TYPES.get(i);
-            mSecurityTypeNames[i] = getContext().getString(SECURITY_TYPE_TO_DESC_RES.get(type));
-            mSecurityTypeIds[i] = Integer.toString(type);
-        }
-    }
-
-    /** Returns the current password text. */
-    public String getPasswordText() {
-        return mPasswordTextPreference.getSummary() != null
-                ? mPasswordTextPreference.getSummary().toString() : "";
-    }
-
-    /** Returns the currently selected security type. */
-    public int getSelectedSecurityType() {
-        return mSelectedSecurityType;
-    }
-
-    @Override
-    protected Class<PreferenceGroup> getPreferenceType() {
-        return PreferenceGroup.class;
-    }
-
-    @Override
-    protected void onCreateInternal() {
-        mSecurityTypePreference = createSecurityTypePreference();
-        mPasswordTextPreference = createPasswordTextPreference();
-        getPreference().addPreference(mSecurityTypePreference);
-        getPreference().addPreference(mPasswordTextPreference);
-    }
-
-    @Override
-    protected void updateState(PreferenceGroup preferenceGroup) {
-        if (hasAccessPoint()) {
-            mSecurityTypePreference.setVisible(false);
-        } else {
-            mSecurityTypePreference.setSummary(
-                    SECURITY_TYPE_TO_DESC_RES.get(mSelectedSecurityType));
-            mPasswordTextPreference.setVisible(mSelectedSecurityType != AccessPoint.SECURITY_NONE);
-        }
-    }
-
-    private ListPreference createSecurityTypePreference() {
-        ListPreference preference = new ListPreference(getContext());
-        preference.setKey(getContext().getString(R.string.pk_add_wifi_security));
-        preference.setTitle(R.string.wifi_security);
-        preference.setDialogTitle(R.string.wifi_security);
-        preference.setEntries(mSecurityTypeNames);
-        preference.setEntryValues(mSecurityTypeIds);
-        preference.setDefaultValue(Integer.toString(AccessPoint.SECURITY_NONE));
-        preference.setPersistent(false);
-
-        preference.setOnPreferenceChangeListener((pref, newValue) -> {
-            mSelectedSecurityType = Integer.parseInt(newValue.toString());
-            refreshUi();
-            return true;
-        });
-
-        return preference;
-    }
-
-    private PasswordEditTextPreference createPasswordTextPreference() {
-        PasswordEditTextPreference preference = new PasswordEditTextPreference(getContext());
-        preference.setKey(getContext().getString(R.string.pk_add_wifi_password));
-        preference.setTitle(R.string.wifi_password);
-        preference.setDialogTitle(R.string.wifi_password);
-        preference.setSummary(R.string.default_password_summary);
-
-        preference.setOnPreferenceChangeListener((pref, password) -> {
-            CharSequence value = password.toString();
-            if (TextUtils.isEmpty(value)) {
-                value = getContext().getString(R.string.default_password_summary);
-                preference.setSummaryInputType(InputType.TYPE_CLASS_TEXT);
-            } else {
-                preference.setSummaryInputType(InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-            }
-            preference.setSummary(value);
-            return true;
-        });
-
-        return preference;
-    }
-}
diff --git a/src/com/android/car/settings/wifi/NetworkSecurityPreferenceController.java b/src/com/android/car/settings/wifi/NetworkSecurityPreferenceController.java
new file mode 100644
index 0000000..0d180b2
--- /dev/null
+++ b/src/com/android/car/settings/wifi/NetworkSecurityPreferenceController.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.settings.wifi;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+import androidx.preference.ListPreference;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.FragmentController;
+import com.android.car.settings.common.PreferenceController;
+import com.android.settingslib.wifi.AccessPoint;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Business logic to select the security type when adding a hidden network. */
+public class NetworkSecurityPreferenceController extends PreferenceController<ListPreference> {
+
+    /** Action used in the {@link Intent} sent by the {@link LocalBroadcastManager}. */
+    public static final String ACTION_SECURITY_CHANGE =
+            "com.android.car.settings.wifi.SecurityChangeAction";
+    /** Key used to store the selected security type. */
+    public static final String KEY_SECURITY_TYPE = "security_type";
+
+    private static final Map<Integer, Integer> SECURITY_TYPE_TO_DESC_RES =
+            createSecurityTypeDescMap();
+
+    private static final List<Integer> SECURITY_TYPES = Arrays.asList(
+            AccessPoint.SECURITY_NONE,
+            AccessPoint.SECURITY_WEP,
+            AccessPoint.SECURITY_PSK,
+            AccessPoint.SECURITY_EAP);
+
+    private CharSequence[] mSecurityTypeNames;
+    private CharSequence[] mSecurityTypeIds;
+    private int mSelectedSecurityType;
+
+    public NetworkSecurityPreferenceController(Context context, String preferenceKey,
+            FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
+        super(context, preferenceKey, fragmentController, uxRestrictions);
+    }
+
+    @Override
+    protected Class<ListPreference> getPreferenceType() {
+        return ListPreference.class;
+    }
+
+    @Override
+    protected void onCreateInternal() {
+        // Security type setup.
+        mSecurityTypeNames = new CharSequence[SECURITY_TYPES.size()];
+        mSecurityTypeIds = new CharSequence[SECURITY_TYPES.size()];
+        mSelectedSecurityType = AccessPoint.SECURITY_NONE;
+
+        for (int i = 0; i < SECURITY_TYPES.size(); i++) {
+            int type = SECURITY_TYPES.get(i);
+            mSecurityTypeNames[i] = getContext().getString(SECURITY_TYPE_TO_DESC_RES.get(type));
+            mSecurityTypeIds[i] = Integer.toString(type);
+        }
+
+        getPreference().setEntries(mSecurityTypeNames);
+        getPreference().setEntryValues(mSecurityTypeIds);
+        getPreference().setDefaultValue(Integer.toString(AccessPoint.SECURITY_NONE));
+    }
+
+    @Override
+    protected void updateState(ListPreference preference) {
+        preference.setSummary(SECURITY_TYPE_TO_DESC_RES.get(mSelectedSecurityType));
+    }
+
+    @Override
+    protected boolean handlePreferenceChanged(ListPreference preference, Object newValue) {
+        mSelectedSecurityType = Integer.parseInt(newValue.toString());
+        notifySecurityChange(mSelectedSecurityType);
+        refreshUi();
+        return true;
+    }
+
+    private void notifySecurityChange(int securityType) {
+        Intent intent = new Intent(ACTION_SECURITY_CHANGE);
+        intent.putExtra(KEY_SECURITY_TYPE, securityType);
+        LocalBroadcastManager.getInstance(getContext()).sendBroadcastSync(intent);
+    }
+
+    private static Map<Integer, Integer> createSecurityTypeDescMap() {
+        Map<Integer, Integer> map = new HashMap<>();
+        map.put(AccessPoint.SECURITY_NONE, R.string.wifi_security_none);
+        map.put(AccessPoint.SECURITY_WEP, R.string.wifi_security_wep);
+        map.put(AccessPoint.SECURITY_PSK, R.string.wifi_security_psk_generic);
+        map.put(AccessPoint.SECURITY_EAP, R.string.wifi_security_eap);
+        return map;
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/wifi/AddWifiFragmentTest.java b/tests/robotests/src/com/android/car/settings/wifi/AddWifiFragmentTest.java
new file mode 100644
index 0000000..b48d36f
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/wifi/AddWifiFragmentTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.widget.Button;
+
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
+import com.android.car.settings.testutils.FragmentController;
+import com.android.car.settings.testutils.ShadowLocalBroadcastManager;
+import com.android.car.settings.testutils.ShadowWifiManager;
+import com.android.settingslib.wifi.AccessPoint;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowLocalBroadcastManager.class, ShadowWifiManager.class})
+public class AddWifiFragmentTest {
+
+    private Context mContext;
+    private LocalBroadcastManager mLocalBroadcastManager;
+    private AddWifiFragment mFragment;
+    private FragmentController<AddWifiFragment> mFragmentController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
+        mFragment = new AddWifiFragment();
+        mFragmentController = FragmentController.of(mFragment);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowLocalBroadcastManager.reset();
+        ShadowWifiManager.reset();
+    }
+
+    @Test
+    public void onStart_registersNameChangeListener() {
+        mFragmentController.create().start();
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkNamePreferenceController.ACTION_NAME_CHANGE)).isTrue();
+    }
+
+    @Test
+    public void onStart_registersSecurityChangeListener() {
+        mFragmentController.create().start();
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE)).isTrue();
+    }
+
+    @Test
+    public void onStop_unregistersNameChangeListener() {
+        mFragmentController.create().start();
+        mFragmentController.stop();
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkNamePreferenceController.ACTION_NAME_CHANGE)).isFalse();
+    }
+
+    @Test
+    public void onStop_unregistersSecurityChangeListener() {
+        mFragmentController.create().start();
+        mFragmentController.stop();
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE)).isFalse();
+    }
+
+    @Test
+    public void initialState_buttonDisabled() {
+        mFragmentController.setup();
+        assertThat(getAddWifiButton().isEnabled()).isFalse();
+    }
+
+    @Test
+    public void receiveNameChangeIntent_emptyName_buttonDisabled() {
+        mFragmentController.setup();
+        Intent intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, "");
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(getAddWifiButton().isEnabled()).isFalse();
+    }
+
+    @Test
+    public void receiveNameChangeIntent_name_buttonEnabled() {
+        mFragmentController.setup();
+        String networkName = "test_network_name";
+        Intent intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, networkName);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(getAddWifiButton().isEnabled()).isTrue();
+    }
+
+    @Test
+    public void receiveSecurityChangeIntent_nameSet_buttonDisabled() {
+        mFragmentController.setup();
+        String networkName = "test_network_name";
+        Intent intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, networkName);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_PSK);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(getAddWifiButton().isEnabled()).isFalse();
+    }
+
+    private Button getAddWifiButton() {
+        return mFragment.requireActivity().findViewById(R.id.action_button1);
+    }
+
+    private boolean isReceiverRegisteredForAction(String action) {
+        List<ShadowLocalBroadcastManager.Wrapper> receivers =
+                ShadowLocalBroadcastManager.getRegisteredBroadcastReceivers();
+
+        boolean found = false;
+        for (ShadowLocalBroadcastManager.Wrapper receiver : receivers) {
+            if (receiver.getIntentFilter().hasAction(action)) {
+                found = true;
+            }
+        }
+
+        return found;
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/wifi/NetworkNamePreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/wifi/NetworkNamePreferenceControllerTest.java
index b68c637..6f8364a 100644
--- a/tests/robotests/src/com/android/car/settings/wifi/NetworkNamePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/car/settings/wifi/NetworkNamePreferenceControllerTest.java
@@ -18,90 +18,76 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import android.content.Context;
+import android.content.Intent;
 
 import androidx.lifecycle.Lifecycle;
 import androidx.preference.EditTextPreference;
 
 import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
 import com.android.car.settings.common.PreferenceControllerTestHelper;
-import com.android.settingslib.wifi.AccessPoint;
+import com.android.car.settings.testutils.ShadowLocalBroadcastManager;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
 
 @RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowLocalBroadcastManager.class})
 public class NetworkNamePreferenceControllerTest {
 
     private static final String TEST_SSID = "test_ssid";
 
     private Context mContext;
     private EditTextPreference mEditTextPreference;
-    private PreferenceControllerTestHelper<NetworkNamePreferenceController>
-            mPreferenceControllerHelper;
     private NetworkNamePreferenceController mController;
-    @Mock
-    private AccessPoint mAccessPoint;
-    @Mock
-    private NetworkNamePreferenceController.NetworkNameChangeListener mNetworkNameChangeListener;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mEditTextPreference = new EditTextPreference(mContext);
-        mPreferenceControllerHelper = new PreferenceControllerTestHelper<>(mContext,
-                NetworkNamePreferenceController.class, mEditTextPreference);
-        mController = mPreferenceControllerHelper.getController();
-        mController.setTextChangeListener(mNetworkNameChangeListener);
-        when(mAccessPoint.getSsid()).thenReturn(TEST_SSID);
+        PreferenceControllerTestHelper<NetworkNamePreferenceController> controllerHelper =
+                new PreferenceControllerTestHelper<>(mContext,
+                        NetworkNamePreferenceController.class, mEditTextPreference);
+        mController = controllerHelper.getController();
+        controllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowLocalBroadcastManager.reset();
     }
 
     @Test
-    public void testOnStartInternal_hasAccessPoint_textIsSet() {
-        mController.setAccessPoint(mAccessPoint);
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
-        assertThat(mEditTextPreference.getText()).isEqualTo(TEST_SSID);
+    public void refreshUi_defaultState_showsDefaultString() {
+        mController.refreshUi();
+        assertThat(mEditTextPreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.default_network_name_summary));
     }
 
     @Test
-    public void testOnStartInternal_noAccessPoint_textIsNotSet() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
-        assertThat(mEditTextPreference.getText()).isNull();
-    }
-
-    @Test
-    public void testOnStartInternal_hasAccessPoint_isNotSelectable() {
-        mController.setAccessPoint(mAccessPoint);
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
-        assertThat(mEditTextPreference.isSelectable()).isFalse();
-    }
-
-    @Test
-    public void testOnStartInternal_noAccessPoint_isSelectable() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
-        assertThat(mEditTextPreference.isSelectable()).isTrue();
-    }
-
-    @Test
-    public void testHandlePreferenceChanged_newTextIsSet() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
+    public void handlePreferenceChanged_newTextIsSet() {
         mEditTextPreference.setText("Old value");
         mEditTextPreference.callChangeListener("New value");
         assertThat(mEditTextPreference.getSummary()).isEqualTo("New value");
     }
 
     @Test
-    public void testHandlePreferenceChanged_listenerIsCalled() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        mEditTextPreference.callChangeListener("New value");
-        verify(mNetworkNameChangeListener).onNetworkNameChanged("New value");
+    public void handlePreferenceChanged_broadcastIsSent() {
+        String value = "New value";
+        mEditTextPreference.callChangeListener(value);
+
+        List<Intent> intents = ShadowLocalBroadcastManager.getSentBroadcastIntents();
+        assertThat(intents).hasSize(1);
+        assertThat(intents.get(0).getAction()).isEqualTo(
+                NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        assertThat(intents.get(0).getStringExtra(
+                NetworkNamePreferenceController.KEY_NETWORK_NAME)).isEqualTo(value);
     }
 }
diff --git a/tests/robotests/src/com/android/car/settings/wifi/NetworkPasswordPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/wifi/NetworkPasswordPreferenceControllerTest.java
new file mode 100644
index 0000000..fc14fa9
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/wifi/NetworkPasswordPreferenceControllerTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2018 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.util.Pair;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
+import com.android.car.settings.common.PasswordEditTextPreference;
+import com.android.car.settings.common.PreferenceControllerTestHelper;
+import com.android.car.settings.testutils.ShadowLocalBroadcastManager;
+import com.android.car.settings.testutils.ShadowWifiManager;
+import com.android.settingslib.wifi.AccessPoint;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowToast;
+
+import java.util.List;
+
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowLocalBroadcastManager.class, ShadowWifiManager.class})
+public class NetworkPasswordPreferenceControllerTest {
+
+    private Context mContext;
+    private LocalBroadcastManager mLocalBroadcastManager;
+    private PasswordEditTextPreference mPasswordEditTextPreference;
+    private PreferenceControllerTestHelper<NetworkPasswordPreferenceController>
+            mPreferenceControllerHelper;
+    private NetworkPasswordPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext);
+        mPasswordEditTextPreference = new PasswordEditTextPreference(mContext);
+        mPreferenceControllerHelper = new PreferenceControllerTestHelper<>(mContext,
+                NetworkPasswordPreferenceController.class, mPasswordEditTextPreference);
+        mController = mPreferenceControllerHelper.getController();
+    }
+
+    @After
+    public void tearDown() {
+        ShadowLocalBroadcastManager.reset();
+        ShadowWifiManager.reset();
+    }
+
+    @Test
+    public void onStart_registersNameChangeListener() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkNamePreferenceController.ACTION_NAME_CHANGE)).isTrue();
+    }
+
+    @Test
+    public void onStart_registersSecurityChangeListener() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE)).isTrue();
+    }
+
+    @Test
+    public void onStop_unregistersNameChangeListener() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_STOP);
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkNamePreferenceController.ACTION_NAME_CHANGE)).isFalse();
+    }
+
+    @Test
+    public void onStop_unregistersSecurityChangeListener() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_STOP);
+
+        assertThat(isReceiverRegisteredForAction(
+                NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE)).isFalse();
+    }
+
+    @Test
+    public void receiveNameChangeIntent_emptyName_dialogNameRemoved() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        Intent intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, "");
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(mPasswordEditTextPreference.getDialogTitle()).isEqualTo(
+                mContext.getString(R.string.wifi_password));
+    }
+
+    @Test
+    public void receiveNameChangeIntent_name_dialogNameSet() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        String networkName = "test_network_name";
+        Intent intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, networkName);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(mPasswordEditTextPreference.getDialogTitle()).isEqualTo(networkName);
+    }
+
+    @Test
+    public void receiveSecurityChangeIntent_setUnsecureType_preferenceHidden() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        Intent intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_NONE);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(mPasswordEditTextPreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void receiveSecurityChangeIntent_setSecureType_preferenceVisible() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        Intent intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_PSK);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        assertThat(mPasswordEditTextPreference.isVisible()).isTrue();
+    }
+
+    @Test
+    public void handlePreferenceChanged_hasSecurity_noNetworkNameSet_showToast() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        Intent intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_PSK);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, "");
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        mPasswordEditTextPreference.callChangeListener("password");
+        assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+                mContext.getString(R.string.wifi_no_network_name));
+    }
+
+    @Test
+    public void handlePreferenceChanged_hasSecurity_networkNameSet_wifiAdded() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        String networkName = "network_name";
+        String password = "password";
+        Intent intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_PSK);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, networkName);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+        mPasswordEditTextPreference.callChangeListener(password);
+
+        WifiConfiguration lastAdded = getShadowWifiManager().getLastAddedNetworkConfiguration();
+        assertThat(lastAdded.SSID).contains(networkName);
+        assertThat(lastAdded.getAuthType()).isEqualTo(WifiConfiguration.KeyMgmt.WPA_PSK);
+        assertThat(lastAdded.preSharedKey).contains(password);
+    }
+
+    @Test
+    public void handlePreferenceChanged_hasSecurity_networkNameSet_wifiEnabled() {
+        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_START);
+        String networkName = "network_name";
+        String password = "password";
+        Intent intent = new Intent(NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        intent.putExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_PSK);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+
+        intent = new Intent(NetworkNamePreferenceController.ACTION_NAME_CHANGE);
+        intent.putExtra(NetworkNamePreferenceController.KEY_NETWORK_NAME, networkName);
+        mLocalBroadcastManager.sendBroadcastSync(intent);
+        mPasswordEditTextPreference.callChangeListener(password);
+
+        Pair<Integer, Boolean> lastEnabled = getShadowWifiManager().getLastEnabledNetwork();
+        // Enable should be called on the most recently added network id.
+        assertThat(lastEnabled.first).isEqualTo(getShadowWifiManager().getLastAddedNetworkId());
+        // WifiUtil will try to enable the network right away.
+        assertThat(lastEnabled.second).isTrue();
+    }
+
+    private ShadowWifiManager getShadowWifiManager() {
+        return Shadow.extract(mContext.getSystemService(WifiManager.class));
+    }
+
+    private boolean isReceiverRegisteredForAction(String action) {
+        List<ShadowLocalBroadcastManager.Wrapper> receivers =
+                ShadowLocalBroadcastManager.getRegisteredBroadcastReceivers();
+
+        boolean found = false;
+        for (ShadowLocalBroadcastManager.Wrapper receiver : receivers) {
+            if (receiver.getIntentFilter().hasAction(action)) {
+                found = true;
+            }
+        }
+
+        return found;
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceControllerTest.java
deleted file mode 100644
index d5f2197..0000000
--- a/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityGroupPreferenceControllerTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car.settings.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.text.InputType;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.preference.EditTextPreference;
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceGroup;
-
-import com.android.car.settings.CarSettingsRobolectricTestRunner;
-import com.android.car.settings.R;
-import com.android.car.settings.common.LogicalPreferenceGroup;
-import com.android.car.settings.common.PasswordEditTextPreference;
-import com.android.car.settings.common.PreferenceControllerTestHelper;
-import com.android.settingslib.wifi.AccessPoint;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(CarSettingsRobolectricTestRunner.class)
-public class NetworkSecurityGroupPreferenceControllerTest {
-
-    private Context mContext;
-    private PreferenceGroup mPreferenceGroup;
-    private PreferenceControllerTestHelper<NetworkSecurityGroupPreferenceController>
-            mPreferenceControllerHelper;
-    private NetworkSecurityGroupPreferenceController mController;
-    @Mock
-    private AccessPoint mAccessPoint;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mPreferenceGroup = new LogicalPreferenceGroup(mContext);
-        mPreferenceControllerHelper = new PreferenceControllerTestHelper<>(mContext,
-                NetworkSecurityGroupPreferenceController.class, mPreferenceGroup);
-        mController = mPreferenceControllerHelper.getController();
-    }
-
-    @Test
-    public void testOnCreate_hasElements() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
-    }
-
-    @Test
-    public void testRefreshUi_hasAccessPoint_securityTypePreferenceNotVisible() {
-        mController.setAccessPoint(mAccessPoint);
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        assertThat(securityTypePreference.isVisible()).isFalse();
-    }
-
-    @Test
-    public void testRefreshUi_hasAccessPoint_passwordTextPreferenceIsVisible() {
-        mController.setAccessPoint(mAccessPoint);
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        EditTextPreference passwordTextPreference =
-                (EditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        assertThat(passwordTextPreference.isVisible()).isTrue();
-    }
-
-    @Test
-    public void testRefreshUi_noAccessPoint_securityTypePreferenceIsVisible() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        assertThat(securityTypePreference.isVisible()).isTrue();
-    }
-
-    @Test
-    public void testRefreshUi_noAccessPoint_noSecurity_passwordTextPreferenceNotVisible() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        securityTypePreference.callChangeListener(Integer.toString(AccessPoint.SECURITY_NONE));
-        EditTextPreference passwordTextPreference =
-                (EditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        assertThat(passwordTextPreference.isVisible()).isFalse();
-    }
-
-    @Test
-    public void testRefreshUi_noAccessPoint_wepSecurity_passwordTextPreferenceIsVisible() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        securityTypePreference.callChangeListener(Integer.toString(AccessPoint.SECURITY_WEP));
-        EditTextPreference passwordTextPreference =
-                (EditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        assertThat(passwordTextPreference.isVisible()).isTrue();
-    }
-
-    @Test
-    public void testRefreshUi_noAccessPoint_pskSecurity_passwordTextPreferenceIsVisible() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        securityTypePreference.callChangeListener(Integer.toString(AccessPoint.SECURITY_PSK));
-        EditTextPreference passwordTextPreference =
-                (EditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        assertThat(passwordTextPreference.isVisible()).isTrue();
-    }
-
-    @Test
-    public void testRefreshUi_noAccessPoint_eapSecurity_passwordTextPreferenceIsVisible() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        ListPreference securityTypePreference =
-                (ListPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_security));
-        securityTypePreference.callChangeListener(Integer.toString(AccessPoint.SECURITY_EAP));
-        EditTextPreference passwordTextPreference =
-                (EditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        assertThat(passwordTextPreference.isVisible()).isTrue();
-    }
-
-    @Test
-    public void onPasswordEntryEmpty_shouldShowDefaultPreferenceSummary() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        PasswordEditTextPreference passwordTextPreference =
-                (PasswordEditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        passwordTextPreference.callChangeListener("");
-
-        assertThat(passwordTextPreference.getSummaryInputType()).isEqualTo(
-                InputType.TYPE_CLASS_TEXT);
-        assertThat(passwordTextPreference.getSummary()).isEqualTo(
-                mContext.getString(R.string.default_password_summary));
-    }
-
-    @Test
-    public void onPasswordEntryNotEmpty_shouldShowObscuredPasswordPreferenceSummary() {
-        mPreferenceControllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
-        PasswordEditTextPreference passwordTextPreference =
-                (PasswordEditTextPreference) mPreferenceGroup.findPreference(
-                        mContext.getString(R.string.pk_add_wifi_password));
-        String testPassword = "TEST_PASSWORD";
-        passwordTextPreference.callChangeListener(testPassword);
-
-        assertThat(passwordTextPreference.getSummaryInputType()).isEqualTo(
-                (InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_PASSWORD));
-        assertThat(passwordTextPreference.getSummary()).isEqualTo(testPassword);
-    }
-}
diff --git a/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityPreferenceControllerTest.java
new file mode 100644
index 0000000..361e107
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/wifi/NetworkSecurityPreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.settings.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.ListPreference;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
+import com.android.car.settings.common.PreferenceControllerTestHelper;
+import com.android.car.settings.testutils.ShadowLocalBroadcastManager;
+import com.android.settingslib.wifi.AccessPoint;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowLocalBroadcastManager.class})
+public class NetworkSecurityPreferenceControllerTest {
+
+    private Context mContext;
+    private ListPreference mListPreference;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mListPreference = new ListPreference(mContext);
+        PreferenceControllerTestHelper<NetworkSecurityPreferenceController> controllerHelper =
+                new PreferenceControllerTestHelper<>(mContext,
+                        NetworkSecurityPreferenceController.class, mListPreference);
+        controllerHelper.sendLifecycleEvent(Lifecycle.Event.ON_CREATE);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowLocalBroadcastManager.reset();
+    }
+
+    @Test
+    public void handlePreferenceChanged_unsecureNetwork_summaryUpdated() {
+        String value = Integer.toString(AccessPoint.SECURITY_NONE);
+        mListPreference.callChangeListener(value);
+
+        assertThat(mListPreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.wifi_security_none));
+    }
+
+    @Test
+    public void handlePreferenceChanged_pskNetwork_summaryUpdated() {
+        String value = Integer.toString(AccessPoint.SECURITY_PSK);
+        mListPreference.callChangeListener(value);
+
+        assertThat(mListPreference.getSummary()).isEqualTo(
+                mContext.getString(R.string.wifi_security_psk_generic));
+    }
+
+    @Test
+    public void handlePreferenceChanged_broadcastIsSent() {
+        String value = Integer.toString(AccessPoint.SECURITY_PSK);
+        mListPreference.callChangeListener(value);
+
+        List<Intent> intents = ShadowLocalBroadcastManager.getSentBroadcastIntents();
+        assertThat(intents).hasSize(1);
+        assertThat(intents.get(0).getAction()).isEqualTo(
+                NetworkSecurityPreferenceController.ACTION_SECURITY_CHANGE);
+        assertThat(intents.get(0).getIntExtra(NetworkSecurityPreferenceController.KEY_SECURITY_TYPE,
+                AccessPoint.SECURITY_NONE)).isEqualTo(Integer.parseInt(value));
+    }
+}