Merge "Replace dns_tls with private_dns_mode setting" am: ca92fb5e2b
am: 768f467089
Change-Id: I70b86f3e2ebf823fea8a1516031f9137b2813bb3
This commit is contained in:
59
res/layout/private_dns_mode_dialog.xml
Normal file
59
res/layout/private_dns_mode_dialog.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
|
||||
<RadioGroup
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dip">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/private_dns_mode_off"
|
||||
android:text="@string/private_dns_mode_off"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dip"
|
||||
/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/private_dns_mode_opportunistic"
|
||||
android:text="@string/private_dns_mode_opportunistic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dip"
|
||||
/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/private_dns_mode_provider"
|
||||
android:text="@string/private_dns_mode_provider"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dip"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/private_dns_mode_provider_hostname"
|
||||
android:hint="@string/private_dns_mode_provider_hostname_hint"
|
||||
style="@android:style/Widget.CompoundButton.RadioButton"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textFilter|textUri"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dip"
|
||||
android:layout_marginEnd="8dip"
|
||||
/>
|
||||
|
||||
</RadioGroup>
|
@@ -270,10 +270,13 @@
|
||||
android:entries="@array/bluetooth_a2dp_codec_ldac_playback_quality_titles"
|
||||
android:entryValues="@array/bluetooth_a2dp_codec_ldac_playback_quality_values" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="dns_tls"
|
||||
android:title="@string/dns_tls"
|
||||
android:summary="@string/dns_tls_summary" />
|
||||
<com.android.settings.development.PrivateDnsModeDialogPreference
|
||||
android:key="select_private_dns_configuration"
|
||||
android:title="@string/select_private_dns_configuration_title"
|
||||
android:dialogTitle="@string/select_private_dns_configuration_dialog_title"
|
||||
android:dialogLayout="@layout/private_dns_mode_dialog"
|
||||
android:positiveButtonText="@string/save"
|
||||
android:negativeButtonText="@string/cancel" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
@@ -223,7 +223,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
private static final String BLUETOOTH_SELECT_A2DP_CHANNEL_MODE_KEY = "bluetooth_select_a2dp_channel_mode";
|
||||
private static final String BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY = "bluetooth_select_a2dp_ldac_playback_quality";
|
||||
|
||||
private static final String DNS_TLS_KEY = "dns_tls";
|
||||
private static final String PRIVATE_DNS_PREF_KEY = "select_private_dns_configuration";
|
||||
|
||||
private static final String INACTIVE_APPS_KEY = "inactive_apps";
|
||||
|
||||
@@ -302,8 +302,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
private ListPreference mBluetoothSelectA2dpChannelMode;
|
||||
private ListPreference mBluetoothSelectA2dpLdacPlaybackQuality;
|
||||
|
||||
private SwitchPreference mDnsTls;
|
||||
|
||||
private SwitchPreference mOtaDisableAutomaticUpdate;
|
||||
private SwitchPreference mWifiAllowScansWithTraffic;
|
||||
private SwitchPreference mStrictMode;
|
||||
@@ -529,7 +527,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
mBluetoothSelectA2dpLdacPlaybackQuality = addListPreference(BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY);
|
||||
initBluetoothConfigurationValues();
|
||||
|
||||
mDnsTls = findAndInitSwitchPref(DNS_TLS_KEY);
|
||||
updatePrivateDnsSummary();
|
||||
|
||||
mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
|
||||
mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
|
||||
@@ -862,8 +860,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
updateBluetoothDisableAbsVolumeOptions();
|
||||
updateBluetoothEnableInbandRingingOptions();
|
||||
updateBluetoothA2dpConfigurationValues();
|
||||
updateSwitchPreference(mDnsTls, Settings.Global.getInt(cr,
|
||||
Settings.Global.DNS_TLS_DISABLED, 0) == 0);
|
||||
updatePrivateDnsSummary();
|
||||
}
|
||||
|
||||
private void resetDangerousOptions() {
|
||||
@@ -2242,6 +2239,13 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePrivateDnsSummary() {
|
||||
final String summary = PrivateDnsModeDialogPreference.getSummaryStringForModeFromSettings(
|
||||
getActivity().getContentResolver(), getActivity().getResources());
|
||||
final Preference pref = findPreference(PRIVATE_DNS_PREF_KEY);
|
||||
pref.setSummary(summary);
|
||||
}
|
||||
|
||||
private void writeImmediatelyDestroyActivitiesOptions() {
|
||||
try {
|
||||
ActivityManager.getService().setAlwaysFinish(
|
||||
@@ -2590,10 +2594,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
||||
writeBluetoothDisableAbsVolumeOptions();
|
||||
} else if (preference == mBluetoothEnableInbandRinging) {
|
||||
writeBluetoothEnableInbandRingingOptions();
|
||||
} else if (preference == mDnsTls) {
|
||||
Settings.Global.putInt(getActivity().getContentResolver(),
|
||||
Settings.Global.DNS_TLS_DISABLED,
|
||||
mDnsTls.isChecked() ? 0 : 1);
|
||||
} else if (SHORTCUT_MANAGER_RESET_KEY.equals(preference.getKey())) {
|
||||
resetShortcutManagerThrottling();
|
||||
} else {
|
||||
|
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.settings.development;
|
||||
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
|
||||
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.PreferenceDialogFragment;
|
||||
import android.support.v7.preference.DialogPreference;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.CustomDialogPreference;
|
||||
|
||||
|
||||
public class PrivateDnsModeDialogPreference extends CustomDialogPreference
|
||||
implements OnCheckedChangeListener, TextWatcher, OnEditorActionListener {
|
||||
private static final String TAG = PrivateDnsModeDialogPreference.class.getSimpleName();
|
||||
|
||||
private static final String MODE_KEY = Settings.Global.PRIVATE_DNS_MODE;
|
||||
private static final String HOSTNAME_KEY = Settings.Global.PRIVATE_DNS_SPECIFIER;
|
||||
private String mMode;
|
||||
private EditText mEditText;
|
||||
|
||||
public static String getSummaryStringForModeFromSettings(ContentResolver cr, Resources res) {
|
||||
final String mode = getModeFromSettings(cr);
|
||||
switch (mode) {
|
||||
case PRIVATE_DNS_MODE_OFF:
|
||||
return res.getString(R.string.private_dns_mode_off);
|
||||
case PRIVATE_DNS_MODE_OPPORTUNISTIC:
|
||||
return res.getString(R.string.private_dns_mode_opportunistic);
|
||||
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
|
||||
return getHostnameFromSettings(cr);
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public PrivateDnsModeDialogPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public PrivateDnsModeDialogPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
// This is called first when the dialog is launched.
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
final String mode = getModeFromSettings();
|
||||
|
||||
RadioButton rb = (RadioButton) view.findViewById(R.id.private_dns_mode_off);
|
||||
if (mode.equals(PRIVATE_DNS_MODE_OFF)) rb.setChecked(true);
|
||||
rb.setOnCheckedChangeListener(this);
|
||||
|
||||
rb = (RadioButton) view.findViewById(R.id.private_dns_mode_opportunistic);
|
||||
if (mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC)) rb.setChecked(true);
|
||||
rb.setOnCheckedChangeListener(this);
|
||||
|
||||
rb = (RadioButton) view.findViewById(R.id.private_dns_mode_provider);
|
||||
if (mode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) rb.setChecked(true);
|
||||
rb.setOnCheckedChangeListener(this);
|
||||
|
||||
mEditText = (EditText) view.findViewById(R.id.private_dns_mode_provider_hostname);
|
||||
mEditText.setOnEditorActionListener(this);
|
||||
mEditText.addTextChangedListener(this);
|
||||
|
||||
// (Mostly) Fix the EditText field's indentation to align underneath the
|
||||
// displayed radio button text, and not under the radio button itself.
|
||||
final int padding = rb.isLayoutRtl()
|
||||
? rb.getCompoundPaddingRight()
|
||||
: rb.getCompoundPaddingLeft();
|
||||
final MarginLayoutParams marginParams = (MarginLayoutParams) mEditText.getLayoutParams();
|
||||
marginParams.setMarginStart(marginParams.getMarginStart() + padding);
|
||||
mEditText.setLayoutParams(marginParams);
|
||||
mEditText.setText(getHostnameFromSettings());
|
||||
|
||||
setDialogValue(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
if (!positiveResult) return;
|
||||
|
||||
saveDialogValue();
|
||||
setSummary(getSummaryStringForModeFromSettings(
|
||||
getContext().getContentResolver(), getContext().getResources()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (!isChecked) return;
|
||||
|
||||
switch (buttonView.getId()) {
|
||||
case R.id.private_dns_mode_off:
|
||||
setDialogValue(PRIVATE_DNS_MODE_OFF);
|
||||
break;
|
||||
case R.id.private_dns_mode_opportunistic:
|
||||
setDialogValue(PRIVATE_DNS_MODE_OPPORTUNISTIC);
|
||||
break;
|
||||
case R.id.private_dns_mode_provider:
|
||||
setDialogValue(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
|
||||
break;
|
||||
default:
|
||||
// Unknown button; ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView tv, int actionId, KeyEvent k) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
saveDialogValue();
|
||||
getDialog().dismiss();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { return; }
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) { return; }
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
final String hostname = s.toString();
|
||||
final boolean appearsValid = isWeaklyValidatedHostname(hostname);
|
||||
// TODO: Disable the "positive button" ("Save") when appearsValid is false.
|
||||
}
|
||||
|
||||
private void setDialogValue(String mode) {
|
||||
mMode = mode;
|
||||
final boolean txtEnabled = mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
|
||||
mEditText.setEnabled(txtEnabled);
|
||||
}
|
||||
|
||||
private void saveDialogValue() {
|
||||
if (!isValidMode(mMode)) {
|
||||
mMode = PRIVATE_DNS_DEFAULT_MODE;
|
||||
}
|
||||
|
||||
if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
|
||||
final String hostname = mEditText.getText().toString();
|
||||
if (isWeaklyValidatedHostname(hostname)) {
|
||||
saveHostnameToSettings(hostname);
|
||||
} else {
|
||||
// TODO: Once quasi-validation of hostnames works and acceptable
|
||||
// user signaling is working, this can be deleted.
|
||||
mMode = PRIVATE_DNS_MODE_OPPORTUNISTIC;
|
||||
if (TextUtils.isEmpty(hostname)) saveHostnameToSettings("");
|
||||
}
|
||||
}
|
||||
|
||||
saveModeToSettings(mMode);
|
||||
}
|
||||
|
||||
private String getModeFromSettings() {
|
||||
return getModeFromSettings(getContext().getContentResolver());
|
||||
}
|
||||
|
||||
private void saveModeToSettings(String value) {
|
||||
Settings.Global.putString(getContext().getContentResolver(), MODE_KEY, value);
|
||||
}
|
||||
|
||||
private String getHostnameFromSettings() {
|
||||
return getHostnameFromSettings(getContext().getContentResolver());
|
||||
}
|
||||
|
||||
private void saveHostnameToSettings(String hostname) {
|
||||
Settings.Global.putString(getContext().getContentResolver(), HOSTNAME_KEY, hostname);
|
||||
}
|
||||
|
||||
private static String getModeFromSettings(ContentResolver cr) {
|
||||
final String mode = Settings.Global.getString(cr, MODE_KEY);
|
||||
return isValidMode(mode) ? mode : PRIVATE_DNS_DEFAULT_MODE;
|
||||
}
|
||||
|
||||
private static boolean isValidMode(String mode) {
|
||||
return !TextUtils.isEmpty(mode) && (
|
||||
mode.equals(PRIVATE_DNS_MODE_OFF) ||
|
||||
mode.equals(PRIVATE_DNS_MODE_OPPORTUNISTIC) ||
|
||||
mode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME));
|
||||
}
|
||||
|
||||
private static String getHostnameFromSettings(ContentResolver cr) {
|
||||
return Settings.Global.getString(cr, HOSTNAME_KEY);
|
||||
}
|
||||
|
||||
private static boolean isWeaklyValidatedHostname(String hostname) {
|
||||
// TODO: Find and use a better validation method. Specifically:
|
||||
// [1] this should reject IP string literals, and
|
||||
// [2] do the best, simplest, future-proof verification that
|
||||
// the input approximates a DNS hostname.
|
||||
final String WEAK_HOSTNAME_REGEX = "^[a-zA-Z0-9_.-]+$";
|
||||
return hostname.matches(WEAK_HOSTNAME_REGEX);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user