diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java index 03c3600414..4644e4f483 100644 --- a/framework/src/android/net/ConnectivitySettingsManager.java +++ b/framework/src/android/net/ConnectivitySettingsManager.java @@ -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_RELIABILITY; +import static com.android.net.module.util.ConnectivitySettingsUtils.getPrivateDnsModeAsString; + import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; -import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager.MultipathPreference; import android.os.Process; @@ -35,6 +36,7 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Range; +import com.android.net.module.util.ConnectivitySettingsUtils; import com.android.net.module.util.ProxyUtils; 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. */ - 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 * 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 * {@link #PRIVATE_DNS_SPECIFIER} is required, which will try to use the value of * {@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 */ @Retention(RetentionPolicy.SOURCE) @@ -369,10 +373,6 @@ public class ConnectivitySettingsManager { }) 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. * @@ -730,32 +730,6 @@ public class ConnectivitySettingsManager { 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. * @@ -764,13 +738,7 @@ public class ConnectivitySettingsManager { */ @PrivateDnsMode public static int getPrivateDnsMode(@NonNull Context context) { - final ContentResolver cr = context.getContentResolver(); - 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); + return ConnectivitySettingsUtils.getPrivateDnsMode(context); } /** @@ -780,13 +748,7 @@ public class ConnectivitySettingsManager { * @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) { - if (!(mode == PRIVATE_DNS_MODE_OFF - || 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)); + ConnectivitySettingsUtils.setPrivateDnsMode(context, mode); } /** @@ -797,7 +759,7 @@ public class ConnectivitySettingsManager { */ @Nullable 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 specifier The specific private dns provider name. */ - public static void setPrivateDnsHostname(@NonNull Context context, - @Nullable String specifier) { - Settings.Global.putString(context.getContentResolver(), PRIVATE_DNS_SPECIFIER, specifier); + public static void setPrivateDnsHostname(@NonNull Context context, @Nullable String specifier) { + ConnectivitySettingsUtils.setPrivateDnsHostname(context, specifier); } /** diff --git a/tests/cts/net/util/Android.bp b/tests/cts/net/util/Android.bp index b5f1208a4d..fffd30f7e1 100644 --- a/tests/cts/net/util/Android.bp +++ b/tests/cts/net/util/Android.bp @@ -27,5 +27,6 @@ java_library { "junit", "net-tests-utils", "modules-utils-build", + "net-utils-framework-common", ], } diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java index 4abbecce2c..bce9880db8 100644 --- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java +++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java @@ -56,12 +56,13 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.IBinder; -import android.provider.Settings; import android.system.Os; import android.system.OsConstants; +import android.text.TextUtils; import android.util.Log; import com.android.compatibility.common.util.SystemUtil; +import com.android.net.module.util.ConnectivitySettingsUtils; import junit.framework.AssertionFailedError; @@ -80,7 +81,6 @@ import java.util.concurrent.TimeoutException; public final class CtsNetUtils { 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 PRIVATE_DNS_PROBE_MS = 1_000; @@ -104,7 +104,7 @@ public final class CtsNetUtils { private final ContentResolver mCR; private final WifiManager mWifiManager; private TestNetworkCallback mCellNetworkCallback; - private String mOldPrivateDnsMode; + private int mOldPrivateDnsMode = 0; private String mOldPrivateDnsSpecifier; public CtsNetUtils(Context context) { @@ -508,64 +508,69 @@ public final class CtsNetUtils { } public void storePrivateDnsSetting() { - // Store private DNS setting - mOldPrivateDnsMode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); - 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); - } + mOldPrivateDnsMode = ConnectivitySettingsUtils.getPrivateDnsMode(mContext); + mOldPrivateDnsSpecifier = ConnectivitySettingsUtils.getPrivateDnsHostname(mContext); } public void restorePrivateDnsSetting() throws InterruptedException { - if (mOldPrivateDnsMode == null) { + if (mOldPrivateDnsMode == 0) { 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", - mCm.getActiveNetwork(), - mOldPrivateDnsSpecifier, true); - } else { - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, mOldPrivateDnsMode); + if (mOldPrivateDnsMode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) { + ConnectivitySettingsUtils.setPrivateDnsMode(mContext, mOldPrivateDnsMode); + return; } + // 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) { // 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 // EVENT_PRIVATE_DNS_SETTINGS_CHANGED event instead of two. - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_SPECIFIER, server); - final String mode = Settings.Global.getString(mCR, Settings.Global.PRIVATE_DNS_MODE); + ConnectivitySettingsUtils.setPrivateDnsHostname(mContext, server); + final int mode = ConnectivitySettingsUtils.getPrivateDnsMode(mContext); // If current private DNS mode is strict, we only need to set PRIVATE_DNS_SPECIFIER. - if (!PRIVATE_DNS_MODE_STRICT.equals(mode)) { - Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, - PRIVATE_DNS_MODE_STRICT); + if (mode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) { + ConnectivitySettingsUtils.setPrivateDnsMode(mContext, + 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, - @NonNull String server, boolean requiresValidatedServers) throws InterruptedException { - CountDownLatch latch = new CountDownLatch(1); - NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); + @NonNull String server, boolean requiresValidatedServer) throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build(); NetworkCallback callback = new NetworkCallback() { @Override public void onLinkPropertiesChanged(Network n, LinkProperties lp) { - if (requiresValidatedServers && lp.getValidatedPrivateDnsServers().isEmpty()) { + if (requiresValidatedServer && lp.getValidatedPrivateDnsServers().isEmpty()) { return; } 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 // network is likely already validated, there is no callback that we can listen to, so // just sleep. - if (requiresValidatedServers) { + if (requiresValidatedServer) { Thread.sleep(PRIVATE_DNS_PROBE_MS); } }