Allow domain suffix match to be set in UI for EAP configurations

Add a "domain" field that allows the user to specify a domain
suffix match for an EAP network configuration. This field
will only be available when the user specifies a CA certificate for
an EAP-PEAP, EAP-TLS, or EAP-TTLS network. Under the hood, the
value entered into this field will be passed to WPA supplicant
as the |domain_suffix_match| configuration variable.

BUG: 25180141
Change-Id: Ib69b9519f475e90e40441ddff61c80be43cf624b
TEST: On angler, domain field appears for the EAP-PEAP, EAP-TLS
TEST: and EAP-TTLS networks.
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 28ceee0..5233e5e 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -157,6 +157,24 @@
                             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"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ebad62b..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 -->
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index ffa4afe..d108af4 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -123,6 +123,7 @@
     private Spinner mSecuritySpinner;
     private Spinner mEapMethodSpinner;
     private Spinner mEapCaCertSpinner;
+    private TextView mEapDomainView;
     private Spinner mPhase2Spinner;
     // Associated with mPhase2Spinner, one of mPhase2FullAdapter or mPhase2PeapAdapter
     private ArrayAdapter<String> mPhase2Adapter;
@@ -398,7 +399,7 @@
         if (mEapCaCertSpinner != null
                 && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE
                 && ((String) mEapCaCertSpinner.getSelectedItem())
-                       .equals(mDoNotValidateEapServerString)) {
+                        .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);
@@ -496,17 +497,22 @@
                     // Note: |caCert| should not be able to take the value |unspecifiedCert|,
                     // since we prevent such configurations from being saved.
                     config.enterpriseConfig.setCaCertificateAliases(null);
-                } else 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});
+                    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();
@@ -718,6 +724,7 @@
             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);
@@ -767,6 +774,7 @@
                             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());
@@ -791,6 +799,7 @@
      * EAP-TLS valid fields include
      *   user_cert
      *   ca_cert
+     *   domain
      *   identity
      * EAP-TTLS valid fields include
      *   phase2: PAP, MSCHAP, MSCHAPV2, GTC
@@ -803,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
@@ -815,6 +825,7 @@
             case WIFI_EAP_METHOD_PWD:
                 setPhase2Invisible();
                 setCaCertInvisible();
+                setDomainInvisible();
                 setAnonymousIdentInvisible();
                 setUserCertInvisible();
                 break;
@@ -850,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() {
@@ -872,6 +894,11 @@
         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(UNSPECIFIED_CERT_INDEX);
@@ -1082,7 +1109,7 @@
         if (parent == mSecuritySpinner) {
             mAccessPointSecurity = position;
             showSecurityFields();
-        } else if (parent == mEapMethodSpinner) {
+        } else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) {
             showSecurityFields();
         } else if (parent == mProxySettingsSpinner) {
             showProxyFields();