Merge "Call ConnectivitySettingsUtils to set/get private DNS related settings"

This commit is contained in:
Lucas Lin
2021-06-21 19:12:33 +00:00
committed by Gerrit Code Review
3 changed files with 60 additions and 93 deletions

View File

@@ -20,12 +20,13 @@ import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE; import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY; import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
import static com.android.net.module.util.ConnectivitySettingsUtils.getPrivateDnsModeAsString;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.annotation.IntRange; import android.annotation.IntRange;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager.MultipathPreference; import android.net.ConnectivityManager.MultipathPreference;
import android.os.Process; import android.os.Process;
@@ -35,6 +36,7 @@ import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Range; import android.util.Range;
import com.android.net.module.util.ConnectivitySettingsUtils;
import com.android.net.module.util.ProxyUtils; import com.android.net.module.util.ProxyUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@@ -345,20 +347,22 @@ public class ConnectivitySettingsManager {
/** /**
* One of the private DNS modes that indicates the private DNS mode is off. * One of the private DNS modes that indicates the private DNS mode is off.
*/ */
public static final int PRIVATE_DNS_MODE_OFF = 1; public static final int PRIVATE_DNS_MODE_OFF = ConnectivitySettingsUtils.PRIVATE_DNS_MODE_OFF;
/** /**
* One of the private DNS modes that indicates the private DNS mode is automatic, which * One of the private DNS modes that indicates the private DNS mode is automatic, which
* will try to use the current DNS as private DNS. * will try to use the current DNS as private DNS.
*/ */
public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC = 2; public static final int PRIVATE_DNS_MODE_OPPORTUNISTIC =
ConnectivitySettingsUtils.PRIVATE_DNS_MODE_OPPORTUNISTIC;
/** /**
* One of the private DNS modes that indicates the private DNS mode is strict and the * One of the private DNS modes that indicates the private DNS mode is strict and the
* {@link #PRIVATE_DNS_SPECIFIER} is required, which will try to use the value of * {@link #PRIVATE_DNS_SPECIFIER} is required, which will try to use the value of
* {@link #PRIVATE_DNS_SPECIFIER} as private DNS. * {@link #PRIVATE_DNS_SPECIFIER} as private DNS.
*/ */
public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = 3; public static final int PRIVATE_DNS_MODE_PROVIDER_HOSTNAME =
ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
/** @hide */ /** @hide */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@@ -369,10 +373,6 @@ public class ConnectivitySettingsManager {
}) })
public @interface PrivateDnsMode {} public @interface PrivateDnsMode {}
private static final String PRIVATE_DNS_MODE_OFF_STRING = "off";
private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING = "opportunistic";
private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING = "hostname";
/** /**
* A list of uids that is allowed to use restricted networks. * A list of uids that is allowed to use restricted networks.
* *
@@ -730,32 +730,6 @@ public class ConnectivitySettingsManager {
context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */); context.getContentResolver(), GLOBAL_HTTP_PROXY_PAC, "" /* value */);
} }
private static String getPrivateDnsModeAsString(@PrivateDnsMode int mode) {
switch (mode) {
case PRIVATE_DNS_MODE_OFF:
return PRIVATE_DNS_MODE_OFF_STRING;
case PRIVATE_DNS_MODE_OPPORTUNISTIC:
return PRIVATE_DNS_MODE_OPPORTUNISTIC_STRING;
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME_STRING;
default:
throw new IllegalArgumentException("Invalid private dns mode: " + mode);
}
}
private static int getPrivateDnsModeAsInt(String mode) {
switch (mode) {
case "off":
return PRIVATE_DNS_MODE_OFF;
case "hostname":
return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
case "opportunistic":
return PRIVATE_DNS_MODE_OPPORTUNISTIC;
default:
throw new IllegalArgumentException("Invalid private dns mode: " + mode);
}
}
/** /**
* Get private DNS mode from settings. * Get private DNS mode from settings.
* *
@@ -764,13 +738,7 @@ public class ConnectivitySettingsManager {
*/ */
@PrivateDnsMode @PrivateDnsMode
public static int getPrivateDnsMode(@NonNull Context context) { public static int getPrivateDnsMode(@NonNull Context context) {
final ContentResolver cr = context.getContentResolver(); return ConnectivitySettingsUtils.getPrivateDnsMode(context);
String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE);
if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE);
// If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose
// PRIVATE_DNS_MODE_OPPORTUNISTIC as default mode.
if (TextUtils.isEmpty(mode)) return PRIVATE_DNS_MODE_OPPORTUNISTIC;
return getPrivateDnsModeAsInt(mode);
} }
/** /**
@@ -780,13 +748,7 @@ public class ConnectivitySettingsManager {
* @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants. * @param mode The private dns mode. This should be one of the PRIVATE_DNS_MODE_* constants.
*/ */
public static void setPrivateDnsMode(@NonNull Context context, @PrivateDnsMode int mode) { public static void setPrivateDnsMode(@NonNull Context context, @PrivateDnsMode int mode) {
if (!(mode == PRIVATE_DNS_MODE_OFF ConnectivitySettingsUtils.setPrivateDnsMode(context, mode);
|| mode == PRIVATE_DNS_MODE_OPPORTUNISTIC
|| mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) {
throw new IllegalArgumentException("Invalid private dns mode: " + mode);
}
Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_MODE,
getPrivateDnsModeAsString(mode));
} }
/** /**
@@ -797,7 +759,7 @@ public class ConnectivitySettingsManager {
*/ */
@Nullable @Nullable
public static String getPrivateDnsHostname(@NonNull Context context) { public static String getPrivateDnsHostname(@NonNull Context context) {
return Settings.Global.getString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER); return ConnectivitySettingsUtils.getPrivateDnsHostname(context);
} }
/** /**
@@ -806,9 +768,8 @@ public class ConnectivitySettingsManager {
* @param context The {@link Context} to set the setting. * @param context The {@link Context} to set the setting.
* @param specifier The specific private dns provider name. * @param specifier The specific private dns provider name.
*/ */
public static void setPrivateDnsHostname(@NonNull Context context, public static void setPrivateDnsHostname(@NonNull Context context, @Nullable String specifier) {
@Nullable String specifier) { ConnectivitySettingsUtils.setPrivateDnsHostname(context, specifier);
Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier);
} }
/** /**

View File

@@ -27,5 +27,6 @@ java_library {
"junit", "junit",
"net-tests-utils", "net-tests-utils",
"modules-utils-build", "modules-utils-build",
"net-utils-framework-common",
], ],
} }

View File

@@ -56,12 +56,13 @@ import android.net.wifi.WifiManager;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.provider.Settings;
import android.system.Os; import android.system.Os;
import android.system.OsConstants; import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.compatibility.common.util.SystemUtil; import com.android.compatibility.common.util.SystemUtil;
import com.android.net.module.util.ConnectivitySettingsUtils;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
@@ -80,7 +81,6 @@ import java.util.concurrent.TimeoutException;
public final class CtsNetUtils { public final class CtsNetUtils {
private static final String TAG = CtsNetUtils.class.getSimpleName(); private static final String TAG = CtsNetUtils.class.getSimpleName();
private static final int DURATION = 10000;
private static final int SOCKET_TIMEOUT_MS = 2000; private static final int SOCKET_TIMEOUT_MS = 2000;
private static final int PRIVATE_DNS_PROBE_MS = 1_000; private static final int PRIVATE_DNS_PROBE_MS = 1_000;
@@ -104,7 +104,7 @@ public final class CtsNetUtils {
private final ContentResolver mCR; private final ContentResolver mCR;
private final WifiManager mWifiManager; private final WifiManager mWifiManager;
private TestNetworkCallback mCellNetworkCallback; private TestNetworkCallback mCellNetworkCallback;
private String mOldPrivateDnsMode; private int mOldPrivateDnsMode = 0;
private String mOldPrivateDnsSpecifier; private String mOldPrivateDnsSpecifier;
public CtsNetUtils(Context context) { public CtsNetUtils(Context context) {
@@ -508,64 +508,69 @@ public final class CtsNetUtils {
} }
public void storePrivateDnsSetting() { public void storePrivateDnsSetting() {
// Store private DNS setting mOldPrivateDnsMode = ConnectivitySettingsUtils.getPrivateDnsMode(mContext);
mOldPrivateDnsMode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); mOldPrivateDnsSpecifier = ConnectivitySettingsUtils.getPrivateDnsHostname(mContext);
mOldPrivateDnsSpecifier = Settings.Global.getString(mCR,
Settings.Global.PRIVATE_DNS_SPECIFIER);
// It's possible that there is no private DNS default value in Settings.
// Give it a proper default mode which is opportunistic mode.
if (mOldPrivateDnsMode == null) {
mOldPrivateDnsSpecifier = "";
mOldPrivateDnsMode = PRIVATE_DNS_MODE_OPPORTUNISTIC;
Settings.Global.putString(mCR,
Settings.Global.PRIVATE_DNS_SPECIFIER, mOldPrivateDnsSpecifier);
Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldPrivateDnsMode);
}
} }
public void restorePrivateDnsSetting() throws InterruptedException { public void restorePrivateDnsSetting() throws InterruptedException {
if (mOldPrivateDnsMode == null) { if (mOldPrivateDnsMode == 0) {
fail("restorePrivateDnsSetting without storing settings first"); fail("restorePrivateDnsSetting without storing settings first");
} }
// restore private DNS setting
if (PRIVATE_DNS_MODE_STRICT.equals(mOldPrivateDnsMode)) {
// In case of invalid setting, set to opportunistic to avoid a bad state and fail
if (mOldPrivateDnsSpecifier == null) {
Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE,
PRIVATE_DNS_MODE_OPPORTUNISTIC);
fail("Invalid private DNS setting: no hostname specified in strict mode");
}
setPrivateDnsStrictMode(mOldPrivateDnsSpecifier);
awaitPrivateDnsSetting("restorePrivateDnsSetting timeout", if (mOldPrivateDnsMode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
mCm.getActiveNetwork(), ConnectivitySettingsUtils.setPrivateDnsMode(mContext, mOldPrivateDnsMode);
mOldPrivateDnsSpecifier, true); return;
} else {
Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldPrivateDnsMode);
} }
// restore private DNS setting
// In case of invalid setting, set to opportunistic to avoid a bad state and fail
if (TextUtils.isEmpty(mOldPrivateDnsSpecifier)) {
ConnectivitySettingsUtils.setPrivateDnsMode(mContext,
ConnectivitySettingsUtils.PRIVATE_DNS_MODE_OPPORTUNISTIC);
fail("Invalid private DNS setting: no hostname specified in strict mode");
}
setPrivateDnsStrictMode(mOldPrivateDnsSpecifier);
// There might be a race before private DNS setting is applied and the next test is
// running. So waiting private DNS to be validated can reduce the flaky rate of test.
awaitPrivateDnsSetting("restorePrivateDnsSetting timeout",
mCm.getActiveNetwork(),
mOldPrivateDnsSpecifier, true /* requiresValidatedServer */);
} }
public void setPrivateDnsStrictMode(String server) { public void setPrivateDnsStrictMode(String server) {
// To reduce flake rate, set PRIVATE_DNS_SPECIFIER before PRIVATE_DNS_MODE. This ensures // To reduce flake rate, set PRIVATE_DNS_SPECIFIER before PRIVATE_DNS_MODE. This ensures
// that if the previous private DNS mode was not strict, the system only sees one // that if the previous private DNS mode was not strict, the system only sees one
// EVENT_PRIVATE_DNS_SETTINGS_CHANGED event instead of two. // EVENT_PRIVATE_DNS_SETTINGS_CHANGED event instead of two.
Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_SPECIFIER, server); ConnectivitySettingsUtils.setPrivateDnsHostname(mContext, server);
final String mode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); final int mode = ConnectivitySettingsUtils.getPrivateDnsMode(mContext);
// If current private DNS mode is strict, we only need to set PRIVATE_DNS_SPECIFIER. // If current private DNS mode is strict, we only need to set PRIVATE_DNS_SPECIFIER.
if (!PRIVATE_DNS_MODE_STRICT.equals(mode)) { if (mode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, ConnectivitySettingsUtils.setPrivateDnsMode(mContext,
PRIVATE_DNS_MODE_STRICT); ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
} }
} }
/**
* Waiting for the new private DNS setting to be validated.
* This method is helpful when the new private DNS setting is configured and ensure the new
* setting is applied and workable. It can also reduce the flaky rate when the next test is
* running.
*
* @param msg A message that will be printed when the validation of private DNS is timeout.
* @param network A network which will apply the new private DNS setting.
* @param server The hostname of private DNS.
* @param requiresValidatedServer A boolean to decide if it's needed to wait private DNS to be
* validated or not.
* @throws InterruptedException If the thread is interrupted.
*/
public void awaitPrivateDnsSetting(@NonNull String msg, @NonNull Network network, public void awaitPrivateDnsSetting(@NonNull String msg, @NonNull Network network,
@NonNull String server, boolean requiresValidatedServers) throws InterruptedException { @NonNull String server, boolean requiresValidatedServer) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
NetworkCallback callback = new NetworkCallback() { NetworkCallback callback = new NetworkCallback() {
@Override @Override
public void onLinkPropertiesChanged(Network n, LinkProperties lp) { public void onLinkPropertiesChanged(Network n, LinkProperties lp) {
if (requiresValidatedServers && lp.getValidatedPrivateDnsServers().isEmpty()) { if (requiresValidatedServer && lp.getValidatedPrivateDnsServers().isEmpty()) {
return; return;
} }
if (network.equals(n) && server.equals(lp.getPrivateDnsServerName())) { if (network.equals(n) && server.equals(lp.getPrivateDnsServerName())) {
@@ -585,7 +590,7 @@ public final class CtsNetUtils {
// private DNS probe. There is no way to know when the probe has completed: because the // private DNS probe. There is no way to know when the probe has completed: because the
// network is likely already validated, there is no callback that we can listen to, so // network is likely already validated, there is no callback that we can listen to, so
// just sleep. // just sleep.
if (requiresValidatedServers) { if (requiresValidatedServer) {
Thread.sleep(PRIVATE_DNS_PROBE_MS); Thread.sleep(PRIVATE_DNS_PROBE_MS);
} }
} }