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:entries="@array/bluetooth_a2dp_codec_ldac_playback_quality_titles"
|
||||||
android:entryValues="@array/bluetooth_a2dp_codec_ldac_playback_quality_values" />
|
android:entryValues="@array/bluetooth_a2dp_codec_ldac_playback_quality_values" />
|
||||||
|
|
||||||
<SwitchPreference
|
<com.android.settings.development.PrivateDnsModeDialogPreference
|
||||||
android:key="dns_tls"
|
android:key="select_private_dns_configuration"
|
||||||
android:title="@string/dns_tls"
|
android:title="@string/select_private_dns_configuration_title"
|
||||||
android:summary="@string/dns_tls_summary" />
|
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>
|
</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_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 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";
|
private static final String INACTIVE_APPS_KEY = "inactive_apps";
|
||||||
|
|
||||||
@@ -302,8 +302,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
private ListPreference mBluetoothSelectA2dpChannelMode;
|
private ListPreference mBluetoothSelectA2dpChannelMode;
|
||||||
private ListPreference mBluetoothSelectA2dpLdacPlaybackQuality;
|
private ListPreference mBluetoothSelectA2dpLdacPlaybackQuality;
|
||||||
|
|
||||||
private SwitchPreference mDnsTls;
|
|
||||||
|
|
||||||
private SwitchPreference mOtaDisableAutomaticUpdate;
|
private SwitchPreference mOtaDisableAutomaticUpdate;
|
||||||
private SwitchPreference mWifiAllowScansWithTraffic;
|
private SwitchPreference mWifiAllowScansWithTraffic;
|
||||||
private SwitchPreference mStrictMode;
|
private SwitchPreference mStrictMode;
|
||||||
@@ -529,7 +527,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
mBluetoothSelectA2dpLdacPlaybackQuality = addListPreference(BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY);
|
mBluetoothSelectA2dpLdacPlaybackQuality = addListPreference(BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY);
|
||||||
initBluetoothConfigurationValues();
|
initBluetoothConfigurationValues();
|
||||||
|
|
||||||
mDnsTls = findAndInitSwitchPref(DNS_TLS_KEY);
|
updatePrivateDnsSummary();
|
||||||
|
|
||||||
mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
|
mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
|
||||||
mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
|
mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
|
||||||
@@ -862,8 +860,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
updateBluetoothDisableAbsVolumeOptions();
|
updateBluetoothDisableAbsVolumeOptions();
|
||||||
updateBluetoothEnableInbandRingingOptions();
|
updateBluetoothEnableInbandRingingOptions();
|
||||||
updateBluetoothA2dpConfigurationValues();
|
updateBluetoothA2dpConfigurationValues();
|
||||||
updateSwitchPreference(mDnsTls, Settings.Global.getInt(cr,
|
updatePrivateDnsSummary();
|
||||||
Settings.Global.DNS_TLS_DISABLED, 0) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetDangerousOptions() {
|
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() {
|
private void writeImmediatelyDestroyActivitiesOptions() {
|
||||||
try {
|
try {
|
||||||
ActivityManager.getService().setAlwaysFinish(
|
ActivityManager.getService().setAlwaysFinish(
|
||||||
@@ -2590,10 +2594,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
writeBluetoothDisableAbsVolumeOptions();
|
writeBluetoothDisableAbsVolumeOptions();
|
||||||
} else if (preference == mBluetoothEnableInbandRinging) {
|
} else if (preference == mBluetoothEnableInbandRinging) {
|
||||||
writeBluetoothEnableInbandRingingOptions();
|
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())) {
|
} else if (SHORTCUT_MANAGER_RESET_KEY.equals(preference.getKey())) {
|
||||||
resetShortcutManagerThrottling();
|
resetShortcutManagerThrottling();
|
||||||
} else {
|
} 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