diff --git a/src/com/android/settings/network/PrivateDnsModeDialogFragment.java b/src/com/android/settings/network/PrivateDnsModeDialogFragment.java index cb3079e6798..5704fb914b4 100644 --- a/src/com/android/settings/network/PrivateDnsModeDialogFragment.java +++ b/src/com/android/settings/network/PrivateDnsModeDialogFragment.java @@ -32,6 +32,7 @@ import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; +import android.widget.Button; import android.widget.EditText; import android.widget.RadioGroup; @@ -68,6 +69,8 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp @VisibleForTesting RadioGroup mRadioGroup; @VisibleForTesting + Button mSaveButton; + @VisibleForTesting String mMode; public static void show(FragmentManager fragmentManager) { @@ -81,17 +84,23 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getContext(); - return new AlertDialog.Builder(context) + final AlertDialog dialog = new AlertDialog.Builder(context) .setTitle(R.string.select_private_dns_configuration_title) .setView(buildPrivateDnsView(context)) .setPositiveButton(R.string.save, this) .setNegativeButton(R.string.dlg_cancel, null) .create(); + + dialog.setOnShowListener(dialogInterface -> { + mSaveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); + updateDialogInfo(); + }); + return dialog; } private View buildPrivateDnsView(final Context context) { final ContentResolver contentResolver = context.getContentResolver(); - final String mode = Settings.Global.getString(contentResolver, MODE_KEY); + mMode = Settings.Global.getString(contentResolver, MODE_KEY); final View view = LayoutInflater.from(context).inflate(R.layout.private_dns_mode_dialog, null); @@ -101,7 +110,7 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp mRadioGroup = view.findViewById(R.id.private_dns_radio_group); mRadioGroup.setOnCheckedChangeListener(this); - mRadioGroup.check(PRIVATE_DNS_MAP.getOrDefault(mode, R.id.private_dns_mode_opportunistic)); + mRadioGroup.check(PRIVATE_DNS_MAP.getOrDefault(mMode, R.id.private_dns_mode_opportunistic)); return view; } @@ -129,17 +138,15 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp switch (checkedId) { case R.id.private_dns_mode_off: mMode = PRIVATE_DNS_MODE_OFF; - mEditText.setEnabled(false); break; case R.id.private_dns_mode_opportunistic: mMode = PRIVATE_DNS_MODE_OPPORTUNISTIC; - mEditText.setEnabled(false); break; case R.id.private_dns_mode_provider: mMode = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; - mEditText.setEnabled(true); break; } + updateDialogInfo(); } @Override @@ -152,8 +159,9 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp @Override public void afterTextChanged(Editable s) { - // TODO(b/68030013): Disable the "positive button" ("Save") when appearsValid is false. - final boolean valid = isWeaklyValidatedHostname(s.toString()); + if (mSaveButton != null) { + mSaveButton.setEnabled(isWeaklyValidatedHostname(mEditText.getText().toString())); + } } private boolean isWeaklyValidatedHostname(String hostname) { @@ -165,4 +173,17 @@ public class PrivateDnsModeDialogFragment extends InstrumentedDialogFragment imp return hostname.matches(WEAK_HOSTNAME_REGEX); } + private void updateDialogInfo() { + final boolean modeProvider = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mMode); + if (mEditText != null) { + mEditText.setEnabled(modeProvider); + } + if (mSaveButton != null) { + mSaveButton.setEnabled( + modeProvider + ? isWeaklyValidatedHostname(mEditText.getText().toString()) + : true); + } + } + } diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogFragmentTest.java index 3468702f76e..f1d7a73c3e5 100644 --- a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogFragmentTest.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.spy; import android.content.Context; import android.provider.Settings; +import android.widget.Button; import com.android.settings.R; import com.android.settings.TestConfig; @@ -43,9 +44,11 @@ import org.robolectric.annotation.Config; @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class PrivateDnsModeDialogFragmentTest { private static final String HOST_NAME = "192.168.1.1"; + private static final String INVALID_HOST_NAME = "...,"; private Context mContext; private PrivateDnsModeDialogFragment mFragment; + private Button mSaveButton; @Before @@ -53,9 +56,12 @@ public class PrivateDnsModeDialogFragmentTest { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; + mSaveButton = new Button(mContext); + mFragment = spy(new PrivateDnsModeDialogFragment()); doReturn(mContext).when(mFragment).getContext(); mFragment.onCreateDialog(null); + mFragment.mSaveButton = mSaveButton; } @Test @@ -96,4 +102,19 @@ public class PrivateDnsModeDialogFragmentTest { R.id.private_dns_mode_opportunistic); } + @Test + public void testOnCheckedChanged_switchMode_saveButtonHasCorrectState() { + // Set invalid hostname + mFragment.mEditText.setText(INVALID_HOST_NAME); + + mFragment.onCheckedChanged(null, R.id.private_dns_mode_opportunistic); + assertThat(mSaveButton.isEnabled()).isTrue(); + + mFragment.onCheckedChanged(null, R.id.private_dns_mode_provider); + assertThat(mSaveButton.isEnabled()).isFalse(); + + mFragment.onCheckedChanged(null, R.id.private_dns_mode_off); + assertThat(mSaveButton.isEnabled()).isTrue(); + } + }