Merge "Update Settings UI for IKEv2/IPsec VPNs"

This commit is contained in:
Benedict Wong
2020-02-19 07:39:41 +00:00
committed by Gerrit Code Review
2 changed files with 133 additions and 47 deletions

View File

@@ -65,7 +65,7 @@
android:hint="@string/vpn_not_used"/> android:hint="@string/vpn_not_used"/>
</LinearLayout> </LinearLayout>
<LinearLayout android:id="@+id/ipsec_psk" <LinearLayout android:id="@+id/options_ipsec_identity"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
@@ -75,7 +75,13 @@
android:labelFor="@+id/ipsec_identifier"/> android:labelFor="@+id/ipsec_identifier"/>
<EditText style="@style/vpn_value" android:id="@+id/ipsec_identifier" <EditText style="@style/vpn_value" android:id="@+id/ipsec_identifier"
android:hint="@string/vpn_not_used"/> android:hint="@string/vpn_not_used"/>
</LinearLayout>
<LinearLayout android:id="@+id/ipsec_psk"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<TextView style="@style/vpn_label" <TextView style="@style/vpn_label"
android:text="@string/vpn_ipsec_secret" android:text="@string/vpn_ipsec_secret"
android:labelFor="@+id/ipsec_secret"/> android:labelFor="@+id/ipsec_secret"/>
@@ -123,23 +129,28 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
<TextView style="@style/vpn_label" <LinearLayout android:id="@+id/network_options"
android:text="@string/vpn_search_domains" android:layout_width="match_parent"
android:labelFor="@+id/search_domains"/> android:layout_height="wrap_content"
<EditText style="@style/vpn_value" android:id="@+id/search_domains" android:orientation="vertical">
android:hint="@string/vpn_not_used"/> <TextView style="@style/vpn_label"
android:text="@string/vpn_search_domains"
android:labelFor="@+id/search_domains"/>
<EditText style="@style/vpn_value" android:id="@+id/search_domains"
android:hint="@string/vpn_not_used"/>
<TextView style="@style/vpn_label" <TextView style="@style/vpn_label"
android:text="@string/vpn_dns_servers" android:text="@string/vpn_dns_servers"
android:labelFor="@+id/dns_servers"/> android:labelFor="@+id/dns_servers"/>
<EditText style="@style/vpn_value" android:id="@+id/dns_servers" <EditText style="@style/vpn_value" android:id="@+id/dns_servers"
android:hint="@string/vpn_not_used"/> android:hint="@string/vpn_not_used"/>
<TextView style="@style/vpn_label" <TextView style="@style/vpn_label"
android:text="@string/vpn_routes" android:text="@string/vpn_routes"
android:labelFor="@+id/routes"/> android:labelFor="@+id/routes"/>
<EditText style="@style/vpn_value" android:id="@+id/routes" <EditText style="@style/vpn_value" android:id="@+id/routes"
android:hint="@string/vpn_not_used"/> android:hint="@string/vpn_not_used"/>
</LinearLayout>
<TextView android:id="@+id/vpn_proxy_settings_title" <TextView android:id="@+id/vpn_proxy_settings_title"
style="@style/vpn_label" style="@style/vpn_label"
@@ -182,11 +193,10 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout android:id="@+id/login" <LinearLayout android:id="@+id/userpass"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical">
android:animateLayoutChanges="true">
<TextView style="@style/vpn_label" <TextView style="@style/vpn_label"
android:text="@string/vpn_username" android:text="@string/vpn_username"
@@ -202,6 +212,13 @@
<CheckBox style="@style/vpn_value" android:id="@+id/save_login" <CheckBox style="@style/vpn_value" android:id="@+id/save_login"
android:singleLine="false" android:singleLine="false"
android:text="@string/vpn_save_login"/> android:text="@string/vpn_save_login"/>
</LinearLayout>
<LinearLayout android:id="@+id/connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true">
<CheckBox style="@style/vpn_value" android:id="@+id/always_on_vpn" <CheckBox style="@style/vpn_value" android:id="@+id/always_on_vpn"
android:singleLine="false" android:singleLine="false"
android:text="@string/vpn_menu_lockdown"/> android:text="@string/vpn_menu_lockdown"/>

View File

@@ -16,6 +16,8 @@
package com.android.settings.vpn2; package com.android.settings.vpn2;
import static com.android.internal.net.VpnProfile.isLegacyType;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.net.Proxy; import android.net.Proxy;
@@ -191,12 +193,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// Hide 'save login' when we are editing. // Hide 'save login' when we are editing.
mSaveLogin.setVisibility(View.GONE); mSaveLogin.setVisibility(View.GONE);
// Switch to advanced view immediately if any advanced options are on configureAdvancedOptionsVisibility();
if (!mProfile.searchDomains.isEmpty() || !mProfile.dnsServers.isEmpty() ||
!mProfile.routes.isEmpty() || (mProfile.proxy != null &&
(!mProfile.proxy.getHost().isEmpty() || mProfile.proxy.getPort() != 0))) {
showAdvancedOptions();
}
// Create a button to forget the profile if it has already been saved.. // Create a button to forget the profile if it has already been saved..
if (mExists) { if (mExists) {
@@ -210,6 +207,8 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} else { } else {
setTitle(context.getString(R.string.vpn_connect_to, mProfile.name)); setTitle(context.getString(R.string.vpn_connect_to, mProfile.name));
setUsernamePasswordVisibility(mProfile.type);
// Create a button to connect the network. // Create a button to connect the network.
setButton(DialogInterface.BUTTON_POSITIVE, setButton(DialogInterface.BUTTON_POSITIVE,
context.getString(R.string.vpn_connect), mListener); context.getString(R.string.vpn_connect), mListener);
@@ -236,9 +235,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// Visibility isn't restored by super.onRestoreInstanceState, so re-show the advanced // Visibility isn't restored by super.onRestoreInstanceState, so re-show the advanced
// options here if they were already revealed or set. // options here if they were already revealed or set.
if (mShowOptions.isChecked()) { configureAdvancedOptionsVisibility();
showAdvancedOptions();
}
} }
@Override @Override
@@ -257,7 +254,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (view == mShowOptions) { if (view == mShowOptions) {
showAdvancedOptions(); configureAdvancedOptionsVisibility();
} }
} }
@@ -308,11 +305,11 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mAlwaysOnVpn.setEnabled(false); mAlwaysOnVpn.setEnabled(false);
if (!profile.isTypeValidForLockdown()) { if (!profile.isTypeValidForLockdown()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_type); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_type);
} else if (!profile.isServerAddressNumeric()) { } else if (isLegacyType(profile.type) && !profile.isServerAddressNumeric()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_server); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_server);
} else if (!profile.hasDns()) { } else if (isLegacyType(profile.type) && !profile.hasDns()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_no_dns); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_no_dns);
} else if (!profile.areDnsAddressesNumeric()) { } else if (isLegacyType(profile.type) && !profile.areDnsAddressesNumeric()) {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_dns); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_dns);
} else { } else {
mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_other); mAlwaysOnInvalidReason.setText(R.string.vpn_always_on_invalid_reason_other);
@@ -345,9 +342,26 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible); mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible);
} }
private void showAdvancedOptions() { private boolean hasAdvancedOptionsEnabled() {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE); return mSearchDomains.getText().length() > 0 || mDnsServers.getText().length() > 0 ||
mShowOptions.setVisibility(View.GONE); mRoutes.getText().length() > 0 || mProxyHost.getText().length() > 0
|| mProxyPort.getText().length() > 0;
}
private void configureAdvancedOptionsVisibility() {
if (mShowOptions.isChecked() || hasAdvancedOptionsEnabled()) {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
mShowOptions.setVisibility(View.GONE);
// Configure networking option visibility
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
final int visibility =
isLegacyType(mType.getSelectedItemPosition()) ? View.VISIBLE : View.GONE;
mView.findViewById(R.id.network_options).setVisibility(visibility);
} else {
mView.findViewById(R.id.options).setVisibility(View.GONE);
mShowOptions.setVisibility(View.VISIBLE);
}
} }
private void changeType(int type) { private void changeType(int type) {
@@ -357,6 +371,14 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
mView.findViewById(R.id.ipsec_psk).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_psk).setVisibility(View.GONE);
mView.findViewById(R.id.ipsec_user).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_user).setVisibility(View.GONE);
mView.findViewById(R.id.ipsec_peer).setVisibility(View.GONE); mView.findViewById(R.id.ipsec_peer).setVisibility(View.GONE);
mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.GONE);
setUsernamePasswordVisibility(type);
// Always enable identity for IKEv2/IPsec profiles.
if (!isLegacyType(type)) {
mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE);
}
// Then, unhide type-specific fields. // Then, unhide type-specific fields.
switch (type) { switch (type) {
@@ -367,32 +389,50 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
case VpnProfile.TYPE_L2TP_IPSEC_PSK: case VpnProfile.TYPE_L2TP_IPSEC_PSK:
mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE); mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE);
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK: case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
mView.findViewById(R.id.ipsec_psk).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_psk).setVisibility(View.VISIBLE);
mView.findViewById(R.id.options_ipsec_identity).setVisibility(View.VISIBLE);
break; break;
case VpnProfile.TYPE_L2TP_IPSEC_RSA: case VpnProfile.TYPE_L2TP_IPSEC_RSA:
mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE); mView.findViewById(R.id.l2tp).setVisibility(View.VISIBLE);
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA: case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
mView.findViewById(R.id.ipsec_user).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_user).setVisibility(View.VISIBLE);
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through
case VpnProfile.TYPE_IPSEC_HYBRID_RSA: case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
mView.findViewById(R.id.ipsec_peer).setVisibility(View.VISIBLE); mView.findViewById(R.id.ipsec_peer).setVisibility(View.VISIBLE);
break; break;
} }
configureAdvancedOptionsVisibility();
} }
private boolean validate(boolean editing) { private boolean validate(boolean editing) {
if (mAlwaysOnVpn.isChecked() && !getProfile().isValidLockdownProfile()) { if (mAlwaysOnVpn.isChecked() && !getProfile().isValidLockdownProfile()) {
return false; return false;
} }
if (!editing) {
final int type = mType.getSelectedItemPosition();
if (!editing && requiresUsernamePassword(type)) {
return mUsername.getText().length() != 0 && mPassword.getText().length() != 0; return mUsername.getText().length() != 0 && mPassword.getText().length() != 0;
} }
if (mName.getText().length() == 0 || mServer.getText().length() == 0 || if (mName.getText().length() == 0 || mServer.getText().length() == 0) {
!validateAddresses(mDnsServers.getText().toString(), false) || return false;
!validateAddresses(mRoutes.getText().toString(), true)) { }
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
if (isLegacyType(mProfile.type)
&& (!validateAddresses(mDnsServers.getText().toString(), false)
|| !validateAddresses(mRoutes.getText().toString(), true))) {
return false;
}
// All IKEv2 methods require an identifier
if (!isLegacyType(mProfile.type) && mIpsecIdentifier.getText().length() == 0) {
return false; return false;
} }
@@ -400,16 +440,19 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
return false; return false;
} }
switch (mType.getSelectedItemPosition()) { switch (type) {
case VpnProfile.TYPE_PPTP: case VpnProfile.TYPE_PPTP: // fall through
case VpnProfile.TYPE_IPSEC_HYBRID_RSA: case VpnProfile.TYPE_IPSEC_HYBRID_RSA: // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
return true; return true;
case VpnProfile.TYPE_L2TP_IPSEC_PSK: case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through
case VpnProfile.TYPE_L2TP_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK: case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
return mIpsecSecret.getText().length() != 0; return mIpsecSecret.getText().length() != 0;
case VpnProfile.TYPE_L2TP_IPSEC_RSA: case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
case VpnProfile.TYPE_L2TP_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA: case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
return mIpsecUserCert.getSelectedItemPosition() != 0; return mIpsecUserCert.getSelectedItemPosition() != 0;
} }
@@ -470,6 +513,21 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
} }
} }
private void setUsernamePasswordVisibility(int type) {
mView.findViewById(R.id.userpass).setVisibility(
requiresUsernamePassword(type) ? View.VISIBLE : View.GONE);
}
private boolean requiresUsernamePassword(int type) {
switch (type) {
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
return false;
default:
return true;
}
}
boolean isEditing() { boolean isEditing() {
return mEditing; return mEditing;
} }
@@ -486,9 +544,17 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
profile.server = mServer.getText().toString().trim(); profile.server = mServer.getText().toString().trim();
profile.username = mUsername.getText().toString(); profile.username = mUsername.getText().toString();
profile.password = mPassword.getText().toString(); profile.password = mPassword.getText().toString();
profile.searchDomains = mSearchDomains.getText().toString().trim();
profile.dnsServers = mDnsServers.getText().toString().trim(); // Save fields based on VPN type.
profile.routes = mRoutes.getText().toString().trim(); if (isLegacyType(profile.type)) {
// TODO(b/149070123): Add ability for platform VPNs to support DNS & routes
profile.searchDomains = mSearchDomains.getText().toString().trim();
profile.dnsServers = mDnsServers.getText().toString().trim();
profile.routes = mRoutes.getText().toString().trim();
} else {
profile.ipsecIdentifier = mIpsecIdentifier.getText().toString();
}
if (hasProxy()) { if (hasProxy()) {
String proxyHost = mProxyHost.getText().toString().trim(); String proxyHost = mProxyHost.getText().toString().trim();
String proxyPort = mProxyPort.getText().toString().trim(); String proxyPort = mProxyPort.getText().toString().trim();
@@ -508,6 +574,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
case VpnProfile.TYPE_L2TP_IPSEC_PSK: case VpnProfile.TYPE_L2TP_IPSEC_PSK:
profile.l2tpSecret = mL2tpSecret.getText().toString(); profile.l2tpSecret = mL2tpSecret.getText().toString();
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_PSK: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_PSK: case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
profile.ipsecIdentifier = mIpsecIdentifier.getText().toString(); profile.ipsecIdentifier = mIpsecIdentifier.getText().toString();
profile.ipsecSecret = mIpsecSecret.getText().toString(); profile.ipsecSecret = mIpsecSecret.getText().toString();
@@ -516,11 +583,13 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
case VpnProfile.TYPE_L2TP_IPSEC_RSA: case VpnProfile.TYPE_L2TP_IPSEC_RSA:
profile.l2tpSecret = mL2tpSecret.getText().toString(); profile.l2tpSecret = mL2tpSecret.getText().toString();
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
case VpnProfile.TYPE_IPSEC_XAUTH_RSA: case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
if (mIpsecUserCert.getSelectedItemPosition() != 0) { if (mIpsecUserCert.getSelectedItemPosition() != 0) {
profile.ipsecUserCert = (String) mIpsecUserCert.getSelectedItem(); profile.ipsecUserCert = (String) mIpsecUserCert.getSelectedItem();
} }
// fall through // fall through
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through
case VpnProfile.TYPE_IPSEC_HYBRID_RSA: case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
if (mIpsecCaCert.getSelectedItemPosition() != 0) { if (mIpsecCaCert.getSelectedItemPosition() != 0) {
profile.ipsecCaCert = (String) mIpsecCaCert.getSelectedItem(); profile.ipsecCaCert = (String) mIpsecCaCert.getSelectedItem();