Merge "Calling dataChanged() for Net Policy Restrictions" into mm-wireless-dev
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 84d98da..5233e5e 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -107,7 +107,7 @@
                             android:prompt="@string/wifi_eap_method"
                             android:entries="@array/wifi_eap_method" />
                 </LinearLayout>
-                
+
                 <LinearLayout android:id="@+id/l_phase2"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
@@ -145,6 +145,36 @@
                             android:prompt="@string/wifi_eap_ca_cert" />
                 </LinearLayout>
 
+                <LinearLayout android:id="@+id/no_ca_cert_warning"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:visibility="gone"
+                        style="@style/wifi_item" >
+                    <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_warning"
+                            android:text="@string/wifi_do_not_validate_eap_server_warning" />
+                </LinearLayout>
+
+                <LinearLayout android:id="@+id/l_domain"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/wifi_item" >
+                    <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_label"
+                            android:text="@string/wifi_eap_domain" />
+
+                    <EditText android:id="@+id/domain"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_edit_content"
+                            android:singleLine="true"
+                            android:inputType="textNoSuggestions" />
+                </LinearLayout>
+
                 <LinearLayout android:id="@+id/l_user_cert"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
@@ -301,7 +331,7 @@
                     android:layout_height="wrap_content"
                     style="@style/wifi_section"
                     android:visibility="gone">
-                <LinearLayout 
+                <LinearLayout
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
                         style="@style/wifi_item">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ddc8ded..795c58d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1560,6 +1560,8 @@
     <string name="please_select_phase2">Phase 2 authentication</string>
     <!-- Label for the EAP CA certificate of the network -->
     <string name="wifi_eap_ca_cert">CA certificate</string>
+    <!-- Label for the domain name that the EAP CA certificate(s) can be used to validate. -->
+    <string name="wifi_eap_domain">Domain</string>
     <!-- Label for the EAP user certificate of the network -->
     <string name="wifi_eap_user_cert">User certificate</string>
     <!-- Label for the EAP identity of the network -->
@@ -1581,7 +1583,15 @@
     <!-- Hint for unchanged fields -->
     <string name="wifi_unchanged">(unchanged)</string>
     <!-- Hint for unspecified fields -->
-    <string name="wifi_unspecified">(unspecified)</string>
+    <string name="wifi_unspecified">Please select</string>
+    <!-- Hint for multiple certificates being added to the configuration -->
+    <string name="wifi_multiple_cert_added">(Multiple certificates added)</string>
+    <!-- Menu option for not providing an EAP user certificate -->
+    <string name="wifi_do_not_provide_eap_user_cert">Do not provide</string>
+    <!-- Menu option for not validating the EAP server -->
+    <string name="wifi_do_not_validate_eap_server">Do not validate</string>
+    <!-- Warning message displayed if user choses not to validate the EAP server -->
+    <string name="wifi_do_not_validate_eap_server_warning">No certificate specified. Your connection will not be private.</string>
     <!-- Substring of status line when Wi-Fi Protected Setup (WPS) is available and
          string is listed first [CHAR LIMIT=20]-->
     <string name="wifi_wps_available_first_item">WPS available</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 387acf5..46ef73c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -204,6 +204,14 @@
         <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
+    <style name="wifi_item_warning">
+        <item name="android:paddingStart">8dip</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:textAlignment">viewStart</item>
+        <item name="android:textAppearance">@android:style/TextAppearance.Material.Body1</item>
+        <item name="android:textColor">@color/warning</item>
+    </style>
+
     <style name="wifi_item_content">
         <item name="android:textAlignment">viewStart</item>
         <item name="android:textAppearance">@android:style/TextAppearance.Material.Subhead</item>
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 774c54b..d108af4 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -39,8 +39,8 @@
 import android.security.KeyStore;
 import android.text.Editable;
 import android.text.InputType;
-import android.text.TextWatcher;
 import android.text.TextUtils;
+import android.text.TextWatcher;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -56,19 +56,21 @@
 
 import com.android.settings.ProxySelector;
 import com.android.settings.R;
-import com.android.settingslib.wifi.AccessPoint;
 import com.android.settings.Utils;
+import com.android.settingslib.wifi.AccessPoint;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 
 /**
  * The class for allowing UIs like {@link WifiDialog} and {@link WifiConfigUiBase} to
  * share the logic for controlling buttons, text fields, etc.
  */
-public class WifiConfigController implements TextWatcher,
-       AdapterView.OnItemSelectedListener, OnCheckedChangeListener {
+public class WifiConfigController
+        implements TextWatcher, AdapterView.OnItemSelectedListener, OnCheckedChangeListener {
     private static final String TAG = "WifiConfigController";
 
     private final WifiConfigUiBase mConfigUi;
@@ -94,14 +96,14 @@
     public static final int WIFI_EAP_METHOD_AKA_PRIME  = 6;
 
     /* These values come from "wifi_peap_phase2_entries" resource array */
-    public static final int WIFI_PEAP_PHASE2_NONE 	    = 0;
-    public static final int WIFI_PEAP_PHASE2_MSCHAPV2 	= 1;
+    public static final int WIFI_PEAP_PHASE2_NONE       = 0;
+    public static final int WIFI_PEAP_PHASE2_MSCHAPV2   = 1;
     public static final int WIFI_PEAP_PHASE2_GTC        = 2;
 
     /* Phase2 methods supported by PEAP are limited */
-    private final ArrayAdapter<String> PHASE2_PEAP_ADAPTER;
+    private final ArrayAdapter<String> mPhase2PeapAdapter;
     /* Full list of phase2 methods */
-    private final ArrayAdapter<String> PHASE2_FULL_ADAPTER;
+    private final ArrayAdapter<String> mPhase2FullAdapter;
 
     private final Handler mTextViewChangedHandler;
 
@@ -109,14 +111,21 @@
     private int mAccessPointSecurity;
     private TextView mPasswordView;
 
-    private String unspecifiedCert = "unspecified";
-    private static final int unspecifiedCertIndex = 0;
+    private String mUnspecifiedCertString;
+    private String mMultipleCertSetString;
+    private static final int UNSPECIFIED_CERT_INDEX = 0;
+    private static final int NO_CERT_INDEX = 1;
+    private static final int MULTIPLE_CERT_SET_INDEX = 2;
+
+    private String mDoNotProvideEapUserCertString;
+    private String mDoNotValidateEapServerString;
 
     private Spinner mSecuritySpinner;
     private Spinner mEapMethodSpinner;
     private Spinner mEapCaCertSpinner;
+    private TextView mEapDomainView;
     private Spinner mPhase2Spinner;
-    // Associated with mPhase2Spinner, one of PHASE2_FULL_ADAPTER or PHASE2_PEAP_ADAPTER
+    // Associated with mPhase2Spinner, one of mPhase2FullAdapter or mPhase2PeapAdapter
     private ArrayAdapter<String> mPhase2Adapter;
     private Spinner mEapUserCertSpinner;
     private TextView mEapIdentityView;
@@ -164,17 +173,23 @@
         final Resources res = mContext.getResources();
 
         mLevels = res.getStringArray(R.array.wifi_signal);
-        PHASE2_PEAP_ADAPTER = new ArrayAdapter<String>(
+        mPhase2PeapAdapter = new ArrayAdapter<String>(
             mContext, android.R.layout.simple_spinner_item,
             res.getStringArray(R.array.wifi_peap_phase2_entries));
-        PHASE2_PEAP_ADAPTER.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mPhase2PeapAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
-        PHASE2_FULL_ADAPTER = new ArrayAdapter<String>(
+        mPhase2FullAdapter = new ArrayAdapter<String>(
                 mContext, android.R.layout.simple_spinner_item,
                 res.getStringArray(R.array.wifi_phase2_entries));
-        PHASE2_FULL_ADAPTER.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        mPhase2FullAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
-        unspecifiedCert = mContext.getString(R.string.wifi_unspecified);
+        mUnspecifiedCertString = mContext.getString(R.string.wifi_unspecified);
+        mMultipleCertSetString = mContext.getString(R.string.wifi_multiple_cert_added);
+        mDoNotProvideEapUserCertString =
+            mContext.getString(R.string.wifi_do_not_provide_eap_user_cert);
+        mDoNotValidateEapServerString =
+            mContext.getString(R.string.wifi_do_not_validate_eap_server);
+
         mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings);
         mIpSettingsSpinner.setOnItemSelectedListener(this);
         mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings);
@@ -192,10 +207,9 @@
             showIpConfigFields();
             showProxyFields();
             mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE);
-            ((CheckBox)mView.findViewById(R.id.wifi_advanced_togglebox))
+            ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox))
                     .setOnCheckedChangeListener(this);
 
-
             mConfigUi.setSubmitButton(res.getString(R.string.wifi_save));
         } else {
             mConfigUi.setTitle(mAccessPoint.getSsid());
@@ -212,7 +226,7 @@
                     StaticIpConfiguration staticConfig = config.getStaticIpConfiguration();
                     if (staticConfig != null && staticConfig.ipAddress != null) {
                         addRow(group, R.string.wifi_ip_address,
-                           staticConfig.ipAddress.getAddress().getHostAddress());
+                                staticConfig.ipAddress.getAddress().getHostAddress());
                     }
                 } else {
                     mIpSettingsSpinner.setSelection(DHCP);
@@ -229,8 +243,9 @@
                     mProxySettingsSpinner.setSelection(PROXY_NONE);
                 }
                 if (config != null && config.isPasspoint()) {
-                    addRow(group, R.string.passpoint_label, String.format(
-                        mContext.getString(R.string.passpoint_content), config.providerFriendlyName));
+                    addRow(group, R.string.passpoint_label,
+                            String.format(mContext.getString(R.string.passpoint_content),
+                            config.providerFriendlyName));
                 }
             }
 
@@ -240,10 +255,10 @@
                 showIpConfigFields();
                 showProxyFields();
                 mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE);
-                ((CheckBox)mView.findViewById(R.id.wifi_advanced_togglebox))
-                    .setOnCheckedChangeListener(this);
+                ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox))
+                        .setOnCheckedChangeListener(this);
                 if (showAdvancedFields) {
-                    ((CheckBox)mView.findViewById(R.id.wifi_advanced_togglebox)).setChecked(true);
+                    ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox)).setChecked(true);
                     mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.VISIBLE);
                 }
             }
@@ -319,7 +334,7 @@
         group.addView(row);
     }
 
-    private String getSignalString(){
+    private String getSignalString() {
         final int level = mAccessPoint.getLevel();
 
         return (level > -1 && level < mLevels.length) ? mLevels[level] : null;
@@ -347,15 +362,16 @@
         boolean enabled = false;
         boolean passwordInvalid = false;
 
-        if (mPasswordView != null &&
-            ((mAccessPointSecurity == AccessPoint.SECURITY_WEP && mPasswordView.length() == 0) ||
-            (mAccessPointSecurity == AccessPoint.SECURITY_PSK && mPasswordView.length() < 8))) {
+        if (mPasswordView != null
+                && ((mAccessPointSecurity == AccessPoint.SECURITY_WEP
+                        && mPasswordView.length() == 0)
+                    || (mAccessPointSecurity == AccessPoint.SECURITY_PSK
+                           && mPasswordView.length() < 8))) {
             passwordInvalid = true;
         }
 
-        if ((mSsidView != null && mSsidView.length() == 0) ||
-            ((mAccessPoint == null || !mAccessPoint.isSaved()) &&
-            passwordInvalid)) {
+        if ((mSsidView != null && mSsidView.length() == 0)
+                || ((mAccessPoint == null || !mAccessPoint.isSaved()) && passwordInvalid)) {
             enabled = false;
         } else {
             if (ipAndProxyFieldsAreValid()) {
@@ -364,9 +380,32 @@
                 enabled = false;
             }
         }
+        if (mEapCaCertSpinner != null
+                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE
+                && ((String) mEapCaCertSpinner.getSelectedItem()).equals(mUnspecifiedCertString)) {
+            enabled = false;
+        }
+        if (mEapUserCertSpinner != null
+                && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE
+                && ((String) mEapUserCertSpinner.getSelectedItem())
+                       .equals(mUnspecifiedCertString)) {
+            enabled = false;
+        }
         submit.setEnabled(enabled);
     }
 
+    void showWarningMessageIfAppropriate() {
+        mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.GONE);
+        if (mEapCaCertSpinner != null
+                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE
+                && ((String) mEapCaCertSpinner.getSelectedItem())
+                        .equals(mDoNotValidateEapServerString)) {
+            // Display warning if user chooses not to validate the EAP server with a user-supplied
+            // CA certificate in an EAP network configuration.
+            mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.VISIBLE);
+        }
+    }
+
     /* package */ WifiConfiguration getConfig() {
         if (!mEdit) {
             return null;
@@ -399,8 +438,8 @@
                     int length = mPasswordView.length();
                     String password = mPasswordView.getText().toString();
                     // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
-                    if ((length == 10 || length == 26 || length == 58) &&
-                            password.matches("[0-9A-Fa-f]*")) {
+                    if ((length == 10 || length == 26 || length == 58)
+                            && password.matches("[0-9A-Fa-f]*")) {
                         config.wepKeys[0] = password;
                     } else {
                         config.wepKeys[0] = '"' + password + '"';
@@ -430,7 +469,7 @@
                 switch (eapMethod) {
                     case Eap.PEAP:
                         // PEAP supports limited phase2 values
-                        // Map the index from the PHASE2_PEAP_ADAPTER to the one used
+                        // Map the index from the mPhase2PeapAdapter to the one used
                         // by the API which has the full list of PEAP methods.
                         switch(phase2Method) {
                             case WIFI_PEAP_PHASE2_NONE:
@@ -448,15 +487,41 @@
                         }
                         break;
                     default:
-                        // The default index from PHASE2_FULL_ADAPTER maps to the API
+                        // The default index from mPhase2FullAdapter maps to the API
                         config.enterpriseConfig.setPhase2Method(phase2Method);
                         break;
                 }
                 String caCert = (String) mEapCaCertSpinner.getSelectedItem();
-                if (caCert.equals(unspecifiedCert)) caCert = "";
-                config.enterpriseConfig.setCaCertificateAlias(caCert);
+                if (caCert.equals(mUnspecifiedCertString)
+                        || caCert.equals(mDoNotValidateEapServerString)) {
+                    // Note: |caCert| should not be able to take the value |unspecifiedCert|,
+                    // since we prevent such configurations from being saved.
+                    config.enterpriseConfig.setCaCertificateAliases(null);
+                } else {
+                    config.enterpriseConfig.setDomainSuffixMatch(
+                            mEapDomainView.getText().toString());
+                    if (caCert.equals(mMultipleCertSetString)) {
+                        if (mAccessPoint != null) {
+                            if (!mAccessPoint.isSaved()) {
+                                Log.e(TAG, "Multiple certs can only be set "
+                                        + "when editing saved network");
+                            }
+                            config.enterpriseConfig.setCaCertificateAliases(
+                                    mAccessPoint.getConfig().enterpriseConfig
+                                            .getCaCertificateAliases());
+                        }
+                    } else {
+                        config.enterpriseConfig.setCaCertificateAliases(new String[] {caCert});
+                    }
+                }
+
                 String clientCert = (String) mEapUserCertSpinner.getSelectedItem();
-                if (clientCert.equals(unspecifiedCert)) clientCert = "";
+                if (clientCert.equals(mUnspecifiedCertString)
+                        || clientCert.equals(mDoNotProvideEapUserCertString)) {
+                    // Note: |clientCert| should not be able to take the value |unspecifiedCert|,
+                    // since we prevent such configurations from being saved.
+                    clientCert = "";
+                }
                 config.enterpriseConfig.setClientCertificateAlias(clientCert);
                 if (eapMethod == Eap.SIM || eapMethod == Eap.AKA || eapMethod == Eap.AKA_PRIME) {
                     config.enterpriseConfig.setIdentity("");
@@ -493,9 +558,11 @@
     }
 
     private boolean ipAndProxyFieldsAreValid() {
-        mIpAssignment = (mIpSettingsSpinner != null &&
-                mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
-                IpAssignment.STATIC : IpAssignment.DHCP;
+        mIpAssignment =
+                (mIpSettingsSpinner != null
+                    && mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP)
+                ? IpAssignment.STATIC
+                : IpAssignment.DHCP;
 
         if (mIpAssignment == IpAssignment.STATIC) {
             mStaticIpConfiguration = new StaticIpConfiguration();
@@ -544,7 +611,7 @@
     private Inet4Address getIPv4Address(String text) {
         try {
             return (Inet4Address) NetworkUtils.numericToInetAddress(text);
-        } catch (IllegalArgumentException|ClassCastException e) {
+        } catch (IllegalArgumentException | ClassCastException e) {
             return null;
         }
     }
@@ -579,7 +646,7 @@
                 //Extract a default gateway from IP address
                 InetAddress netPart = NetworkUtils.getNetworkPart(inetAddr, networkPrefixLength);
                 byte[] addr = netPart.getAddress();
-                addr[addr.length-1] = 1;
+                addr[addr.length - 1] = 1;
                 mGatewayView.setText(InetAddress.getByAddress(addr).getHostAddress());
             } catch (RuntimeException ee) {
             } catch (java.net.UnknownHostException u) {
@@ -656,12 +723,17 @@
             }
             mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2);
             mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert);
+            mEapCaCertSpinner.setOnItemSelectedListener(this);
+            mEapDomainView = (TextView) mView.findViewById(R.id.domain);
             mEapUserCertSpinner = (Spinner) mView.findViewById(R.id.user_cert);
+            mEapUserCertSpinner.setOnItemSelectedListener(this);
             mEapIdentityView = (TextView) mView.findViewById(R.id.identity);
             mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous);
 
-            loadCertificates(mEapCaCertSpinner, Credentials.CA_CERTIFICATE);
-            loadCertificates(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY);
+            loadCertificates(mEapCaCertSpinner, Credentials.CA_CERTIFICATE, false,
+                    mDoNotValidateEapServerString);
+            loadCertificates(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, false,
+                    mDoNotProvideEapUserCertString);
 
             // Modifying an existing network
             if (mAccessPoint != null && mAccessPoint.isSaved()) {
@@ -691,7 +763,18 @@
                         mPhase2Spinner.setSelection(phase2Method);
                         break;
                 }
-                setSelection(mEapCaCertSpinner, enterpriseConfig.getCaCertificateAlias());
+                String[] caCerts = enterpriseConfig.getCaCertificateAliases();
+                if (caCerts == null) {
+                    setSelection(mEapCaCertSpinner, mUnspecifiedCertString);
+                } else if (caCerts.length == 1) {
+                    setSelection(mEapCaCertSpinner, caCerts[0]);
+                } else {
+                    // Reload the cert spinner with an extra "multiple certificates added" item
+                    loadCertificates(mEapCaCertSpinner,
+                            Credentials.CA_CERTIFICATE, true, mDoNotValidateEapServerString);
+                    mEapCaCertSpinner.setSelection(MULTIPLE_CERT_SET_INDEX);
+                }
+                mEapDomainView.setText(enterpriseConfig.getDomainSuffixMatch());
                 setSelection(mEapUserCertSpinner, enterpriseConfig.getClientCertificateAlias());
                 mEapIdentityView.setText(enterpriseConfig.getIdentity());
                 mEapAnonymousView.setText(enterpriseConfig.getAnonymousIdentity());
@@ -716,6 +799,7 @@
      * EAP-TLS valid fields include
      *   user_cert
      *   ca_cert
+     *   domain
      *   identity
      * EAP-TTLS valid fields include
      *   phase2: PAP, MSCHAP, MSCHAPV2, GTC
@@ -728,6 +812,7 @@
         // Common defaults
         mView.findViewById(R.id.l_method).setVisibility(View.VISIBLE);
         mView.findViewById(R.id.l_identity).setVisibility(View.VISIBLE);
+        mView.findViewById(R.id.l_domain).setVisibility(View.VISIBLE);
 
         // Defaults for most of the EAP methods and over-riden by
         // by certain EAP methods
@@ -740,6 +825,7 @@
             case WIFI_EAP_METHOD_PWD:
                 setPhase2Invisible();
                 setCaCertInvisible();
+                setDomainInvisible();
                 setAnonymousIdentInvisible();
                 setUserCertInvisible();
                 break;
@@ -751,8 +837,8 @@
                 break;
             case WIFI_EAP_METHOD_PEAP:
                 // Reset adapter if needed
-                if (mPhase2Adapter != PHASE2_PEAP_ADAPTER) {
-                    mPhase2Adapter = PHASE2_PEAP_ADAPTER;
+                if (mPhase2Adapter != mPhase2PeapAdapter) {
+                    mPhase2Adapter = mPhase2PeapAdapter;
                     mPhase2Spinner.setAdapter(mPhase2Adapter);
                 }
                 mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE);
@@ -761,8 +847,8 @@
                 break;
             case WIFI_EAP_METHOD_TTLS:
                 // Reset adapter if needed
-                if (mPhase2Adapter != PHASE2_FULL_ADAPTER) {
-                    mPhase2Adapter = PHASE2_FULL_ADAPTER;
+                if (mPhase2Adapter != mPhase2FullAdapter) {
+                    mPhase2Adapter = mPhase2FullAdapter;
                     mPhase2Spinner.setAdapter(mPhase2Adapter);
                 }
                 mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE);
@@ -775,11 +861,22 @@
                 setPhase2Invisible();
                 setAnonymousIdentInvisible();
                 setCaCertInvisible();
+                setDomainInvisible();
                 setUserCertInvisible();
                 setPasswordInvisible();
                 setIdentityInvisible();
                 break;
         }
+
+        if (mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) {
+            String eapCertSelection = (String) mEapCaCertSpinner.getSelectedItem();
+            if (eapCertSelection.equals(mDoNotValidateEapServerString)
+                    || eapCertSelection.equals(mUnspecifiedCertString)) {
+                // Domain suffix matching is not relevant if the user hasn't chosen a CA
+                // certificate yet, or chooses not to validate the EAP server.
+                setDomainInvisible();
+            }
+        }
     }
 
     private void setIdentityInvisible() {
@@ -794,12 +891,17 @@
 
     private void setCaCertInvisible() {
         mView.findViewById(R.id.l_ca_cert).setVisibility(View.GONE);
-        mEapCaCertSpinner.setSelection(unspecifiedCertIndex);
+        mEapCaCertSpinner.setSelection(UNSPECIFIED_CERT_INDEX);
+    }
+
+    private void setDomainInvisible() {
+        mView.findViewById(R.id.l_domain).setVisibility(View.GONE);
+        mEapDomainView.setText("");
     }
 
     private void setUserCertInvisible() {
         mView.findViewById(R.id.l_user_cert).setVisibility(View.GONE);
-        mEapUserCertSpinner.setSelection(unspecifiedCertIndex);
+        mEapUserCertSpinner.setSelection(UNSPECIFIED_CERT_INDEX);
     }
 
     private void setAnonymousIdentInvisible() {
@@ -923,21 +1025,22 @@
         }
     }
 
-    private void loadCertificates(Spinner spinner, String prefix) {
+    private void loadCertificates(
+            Spinner spinner, String prefix, boolean showMultipleCerts, String noCertificateString) {
         final Context context = mConfigUi.getContext();
 
-        String[] certs = KeyStore.getInstance().list(prefix, android.os.Process.WIFI_UID);
-        if (certs == null || certs.length == 0) {
-            certs = new String[] {unspecifiedCert};
-        } else {
-            final String[] array = new String[certs.length + 1];
-            array[0] = unspecifiedCert;
-            System.arraycopy(certs, 0, array, 1, certs.length);
-            certs = array;
+        ArrayList<String> certs = new ArrayList<String>();
+        certs.add(UNSPECIFIED_CERT_INDEX, mUnspecifiedCertString);
+        certs.add(NO_CERT_INDEX, noCertificateString);
+        if (showMultipleCerts) {
+            certs.add(MULTIPLE_CERT_SET_INDEX, mMultipleCertSetString);
         }
+        certs.addAll(
+                Arrays.asList(KeyStore.getInstance().list(prefix, android.os.Process.WIFI_UID)));
 
         final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
-                context, android.R.layout.simple_spinner_item, certs);
+                context, android.R.layout.simple_spinner_item,
+                certs.toArray(new String[certs.size()]));
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         spinner.setAdapter(adapter);
     }
@@ -986,12 +1089,11 @@
     public void onCheckedChanged(CompoundButton view, boolean isChecked) {
         if (view.getId() == R.id.show_password) {
             int pos = mPasswordView.getSelectionEnd();
-            mPasswordView.setInputType(
-                    InputType.TYPE_CLASS_TEXT | (isChecked ?
-                            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
-                                InputType.TYPE_TEXT_VARIATION_PASSWORD));
+            mPasswordView.setInputType(InputType.TYPE_CLASS_TEXT
+                    | (isChecked ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+                                 : InputType.TYPE_TEXT_VARIATION_PASSWORD));
             if (pos >= 0) {
-                ((EditText)mPasswordView).setSelection(pos);
+                ((EditText) mPasswordView).setSelection(pos);
             }
         } else if (view.getId() == R.id.wifi_advanced_togglebox) {
             if (isChecked) {
@@ -1007,13 +1109,14 @@
         if (parent == mSecuritySpinner) {
             mAccessPointSecurity = position;
             showSecurityFields();
-        } else if (parent == mEapMethodSpinner) {
+        } else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) {
             showSecurityFields();
         } else if (parent == mProxySettingsSpinner) {
             showProxyFields();
         } else {
             showIpConfigFields();
         }
+        showWarningMessageIfAppropriate();
         enableSubmitIfAppropriate();
     }
 
@@ -1027,10 +1130,9 @@
      */
     public void updatePassword() {
         TextView passwdView = (TextView) mView.findViewById(R.id.password);
-        passwdView.setInputType(
-                InputType.TYPE_CLASS_TEXT |
-                (((CheckBox) mView.findViewById(R.id.show_password)).isChecked() ?
-                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
-                InputType.TYPE_TEXT_VARIATION_PASSWORD));
+        passwdView.setInputType(InputType.TYPE_CLASS_TEXT
+                | (((CheckBox) mView.findViewById(R.id.show_password)).isChecked()
+                   ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+                   : InputType.TYPE_TEXT_VARIATION_PASSWORD));
     }
 }