Merge changes from topic "connectivity-cts-cherrypicks" into sc-dev
* changes: Use assertEquals instead of assertTrue to compare the vpn type Add CTS for systemReady() & getIpSecNetIdRange() Call ConnectivitySettingsUtils to set/get private DNS related settings Add CTS for isUidNetworkingBlocked & isUidRestrictedOnMeteredNetworks Add test for CSM#[get|set]MobileDataPreferredUids Add test for setHttpProxyConfiguration CTS test for PacProxyManager Add test for CM#setAcceptUnvalidated Add test for CM#setAcceptPartialConnectivity Skip CaptivePortalTest for wearables Improve handling of invalid private DNS settings
This commit is contained in:
committed by
Android (Google) Code Review
commit
77fb999ed0
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -975,4 +975,15 @@ public abstract class AbstractRestrictBackgroundNetworkTestCase {
|
|||||||
*/
|
*/
|
||||||
String getExpected();
|
String getExpected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setRestrictedNetworkingMode(boolean enabled) throws Exception {
|
||||||
|
executeSilentShellCommand(
|
||||||
|
"settings put global restricted_networking_mode " + (enabled ? 1 : 0));
|
||||||
|
assertRestrictedNetworkingModeState(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertRestrictedNetworkingModeState(boolean enabled) throws Exception {
|
||||||
|
assertDelayedShellCommand("cmd netpolicy get restricted-mode",
|
||||||
|
"Restricted mode status: " + (enabled ? "enabled" : "disabled"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,241 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.cts.net.hostside;
|
||||||
|
|
||||||
|
import static android.os.Process.SYSTEM_UID;
|
||||||
|
|
||||||
|
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.assertNetworkingBlockedStatusForUid;
|
||||||
|
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.canChangeActiveNetworkMeteredness;
|
||||||
|
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isUidNetworkingBlocked;
|
||||||
|
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.isUidRestrictedOnMeteredNetworks;
|
||||||
|
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.setRestrictBackground;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class NetworkPolicyManagerTest extends AbstractRestrictBackgroundNetworkTestCase {
|
||||||
|
private static final boolean METERED = true;
|
||||||
|
private static final boolean NON_METERED = false;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final MeterednessConfigurationRule mMeterednessConfiguration =
|
||||||
|
new MeterednessConfigurationRule();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
assumeTrue(canChangeActiveNetworkMeteredness());
|
||||||
|
|
||||||
|
registerBroadcastReceiver();
|
||||||
|
|
||||||
|
removeRestrictBackgroundWhitelist(mUid);
|
||||||
|
removeRestrictBackgroundBlacklist(mUid);
|
||||||
|
assertRestrictBackgroundChangedReceived(0);
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
setBatterySaverMode(false);
|
||||||
|
setRestrictBackground(false);
|
||||||
|
setRestrictedNetworkingMode(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
|
||||||
|
setBatterySaverMode(false);
|
||||||
|
setRestrictBackground(false);
|
||||||
|
setRestrictedNetworkingMode(false);
|
||||||
|
unregisterNetworkCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidNetworkingBlocked_withUidNotBlocked() throws Exception {
|
||||||
|
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
|
||||||
|
// test the cases of non-metered network and uid not matched by any rule.
|
||||||
|
// If mUid is not blocked by data saver mode or power saver mode, no matter the network is
|
||||||
|
// metered or non-metered, mUid shouldn't be blocked.
|
||||||
|
assertFalse(isUidNetworkingBlocked(mUid, METERED)); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
assertFalse(isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidNetworkingBlocked_withSystemUid() throws Exception {
|
||||||
|
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
|
||||||
|
// test the case of uid is system uid.
|
||||||
|
// SYSTEM_UID will never be blocked.
|
||||||
|
assertFalse(isUidNetworkingBlocked(SYSTEM_UID, METERED)); // Match NTWK_ALLOWED_SYSTEM
|
||||||
|
assertFalse(isUidNetworkingBlocked(SYSTEM_UID, NON_METERED)); // Match NTWK_ALLOWED_SYSTEM
|
||||||
|
try {
|
||||||
|
setRestrictBackground(true);
|
||||||
|
setBatterySaverMode(true);
|
||||||
|
setRestrictedNetworkingMode(true);
|
||||||
|
assertNetworkingBlockedStatusForUid(SYSTEM_UID, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_SYSTEM
|
||||||
|
assertFalse(
|
||||||
|
isUidNetworkingBlocked(SYSTEM_UID, NON_METERED)); // Match NTWK_ALLOWED_SYSTEM
|
||||||
|
} finally {
|
||||||
|
setRestrictBackground(false);
|
||||||
|
setBatterySaverMode(false);
|
||||||
|
setRestrictedNetworkingMode(false);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidNetworkingBlocked_withDataSaverMode() throws Exception {
|
||||||
|
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
|
||||||
|
// test the cases of non-metered network, uid is matched by restrict background blacklist,
|
||||||
|
// uid is matched by restrict background whitelist, app is in the foreground with restrict
|
||||||
|
// background enabled and the app is in the background with restrict background enabled.
|
||||||
|
try {
|
||||||
|
// Enable restrict background and mUid will be blocked because it's not in the
|
||||||
|
// foreground.
|
||||||
|
setRestrictBackground(true);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
true /* expectedResult */); // Match NTWK_BLOCKED_BG_RESTRICT
|
||||||
|
|
||||||
|
// Although restrict background is enabled and mUid is in the background, but mUid will
|
||||||
|
// not be blocked if network is non-metered.
|
||||||
|
assertFalse(
|
||||||
|
isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
|
||||||
|
|
||||||
|
// Add mUid into the restrict background blacklist.
|
||||||
|
addRestrictBackgroundBlacklist(mUid);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
true /* expectedResult */); // Match NTWK_BLOCKED_DENYLIST
|
||||||
|
|
||||||
|
// Although mUid is in the restrict background blacklist, but mUid won't be blocked if
|
||||||
|
// the network is non-metered.
|
||||||
|
assertFalse(
|
||||||
|
isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
|
||||||
|
removeRestrictBackgroundBlacklist(mUid);
|
||||||
|
|
||||||
|
// Add mUid into the restrict background whitelist.
|
||||||
|
addRestrictBackgroundWhitelist(mUid);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_ALLOWLIST
|
||||||
|
assertFalse(
|
||||||
|
isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
|
||||||
|
removeRestrictBackgroundWhitelist(mUid);
|
||||||
|
|
||||||
|
// Make TEST_APP2_PKG go to foreground and mUid will be allowed temporarily.
|
||||||
|
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
||||||
|
assertForegroundState();
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_TMP_ALLOWLIST
|
||||||
|
|
||||||
|
// Back to background.
|
||||||
|
finishActivity();
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
true /* expectedResult */); // Match NTWK_BLOCKED_BG_RESTRICT
|
||||||
|
} finally {
|
||||||
|
setRestrictBackground(false);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidNetworkingBlocked_withRestrictedNetworkingMode() throws Exception {
|
||||||
|
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
|
||||||
|
// test the cases of restricted networking mode enabled.
|
||||||
|
try {
|
||||||
|
// All apps should be blocked if restricted networking mode is enabled except for those
|
||||||
|
// apps who have CONNECTIVITY_USE_RESTRICTED_NETWORKS permission.
|
||||||
|
// This test won't test if an app who has CONNECTIVITY_USE_RESTRICTED_NETWORKS will not
|
||||||
|
// be blocked because CONNECTIVITY_USE_RESTRICTED_NETWORKS is a signature/privileged
|
||||||
|
// permission that CTS cannot acquire. Also it's not good for this test to use those
|
||||||
|
// privileged apps which have CONNECTIVITY_USE_RESTRICTED_NETWORKS to test because there
|
||||||
|
// is no guarantee that those apps won't remove this permission someday, and if it
|
||||||
|
// happens, then this test will fail.
|
||||||
|
setRestrictedNetworkingMode(true);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
true /* expectedResult */); // Match NTWK_BLOCKED_RESTRICTED_MODE
|
||||||
|
assertTrue(isUidNetworkingBlocked(mUid,
|
||||||
|
NON_METERED)); // Match NTWK_BLOCKED_RESTRICTED_MODE
|
||||||
|
} finally {
|
||||||
|
setRestrictedNetworkingMode(false);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidNetworkingBlocked_withPowerSaverMode() throws Exception {
|
||||||
|
// Refer to NetworkPolicyManagerService#isUidNetworkingBlockedInternal(), this test is to
|
||||||
|
// test the cases of power saver mode enabled, uid in the power saver mode whitelist and
|
||||||
|
// uid in the power saver mode whitelist with non-metered network.
|
||||||
|
try {
|
||||||
|
// mUid should be blocked if power saver mode is enabled.
|
||||||
|
setBatterySaverMode(true);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
true /* expectedResult */); // Match NTWK_BLOCKED_POWER
|
||||||
|
assertTrue(isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_BLOCKED_POWER
|
||||||
|
|
||||||
|
// Add TEST_APP2_PKG into power saver mode whitelist, its uid rule is RULE_ALLOW_ALL and
|
||||||
|
// it shouldn't be blocked.
|
||||||
|
addPowerSaveModeWhitelist(TEST_APP2_PKG);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
assertFalse(
|
||||||
|
isUidNetworkingBlocked(mUid, NON_METERED)); // Match NTWK_ALLOWED_NON_METERED
|
||||||
|
removePowerSaveModeWhitelist(TEST_APP2_PKG);
|
||||||
|
} finally {
|
||||||
|
setBatterySaverMode(false);
|
||||||
|
assertNetworkingBlockedStatusForUid(mUid, METERED,
|
||||||
|
false /* expectedResult */); // Match NTWK_ALLOWED_DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsUidRestrictedOnMeteredNetworks() throws Exception {
|
||||||
|
try {
|
||||||
|
// isUidRestrictedOnMeteredNetworks() will only return true when restrict background is
|
||||||
|
// enabled and mUid is not in the restrict background whitelist and TEST_APP2_PKG is not
|
||||||
|
// in the foreground. For other cases, it will return false.
|
||||||
|
setRestrictBackground(true);
|
||||||
|
assertTrue(isUidRestrictedOnMeteredNetworks(mUid));
|
||||||
|
|
||||||
|
// Make TEST_APP2_PKG go to foreground and isUidRestrictedOnMeteredNetworks() will
|
||||||
|
// return false.
|
||||||
|
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
||||||
|
assertForegroundState();
|
||||||
|
assertFalse(isUidRestrictedOnMeteredNetworks(mUid));
|
||||||
|
// Back to background.
|
||||||
|
finishActivity();
|
||||||
|
|
||||||
|
// Add mUid into restrict background whitelist and isUidRestrictedOnMeteredNetworks()
|
||||||
|
// will return false.
|
||||||
|
addRestrictBackgroundWhitelist(mUid);
|
||||||
|
assertFalse(isUidRestrictedOnMeteredNetworks(mUid));
|
||||||
|
removeRestrictBackgroundWhitelist(mUid);
|
||||||
|
} finally {
|
||||||
|
// Restrict background is disabled and isUidRestrictedOnMeteredNetworks() will return
|
||||||
|
// false.
|
||||||
|
setRestrictBackground(false);
|
||||||
|
assertFalse(isUidRestrictedOnMeteredNetworks(mUid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ import android.net.ConnectivityManager;
|
|||||||
import android.net.ConnectivityManager.NetworkCallback;
|
import android.net.ConnectivityManager.NetworkCallback;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkPolicyManager;
|
||||||
import android.net.wifi.WifiConfiguration;
|
import android.net.wifi.WifiConfiguration;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.net.wifi.WifiManager.ActionListener;
|
import android.net.wifi.WifiManager.ActionListener;
|
||||||
@@ -58,6 +59,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
|
|||||||
|
|
||||||
import com.android.compatibility.common.util.AppStandbyUtils;
|
import com.android.compatibility.common.util.AppStandbyUtils;
|
||||||
import com.android.compatibility.common.util.BatteryUtils;
|
import com.android.compatibility.common.util.BatteryUtils;
|
||||||
|
import com.android.compatibility.common.util.PollingCheck;
|
||||||
import com.android.compatibility.common.util.ShellIdentityUtils;
|
import com.android.compatibility.common.util.ShellIdentityUtils;
|
||||||
import com.android.compatibility.common.util.ThrowingRunnable;
|
import com.android.compatibility.common.util.ThrowingRunnable;
|
||||||
|
|
||||||
@@ -81,6 +83,7 @@ public class NetworkPolicyTestUtils {
|
|||||||
private static ConnectivityManager mCm;
|
private static ConnectivityManager mCm;
|
||||||
private static WifiManager mWm;
|
private static WifiManager mWm;
|
||||||
private static CarrierConfigManager mCarrierConfigManager;
|
private static CarrierConfigManager mCarrierConfigManager;
|
||||||
|
private static NetworkPolicyManager sNpm;
|
||||||
|
|
||||||
private static Boolean mBatterySaverSupported;
|
private static Boolean mBatterySaverSupported;
|
||||||
private static Boolean mDataSaverSupported;
|
private static Boolean mDataSaverSupported;
|
||||||
@@ -408,6 +411,13 @@ public class NetworkPolicyTestUtils {
|
|||||||
return mCarrierConfigManager;
|
return mCarrierConfigManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static NetworkPolicyManager getNetworkPolicyManager() {
|
||||||
|
if (sNpm == null) {
|
||||||
|
sNpm = getContext().getSystemService(NetworkPolicyManager.class);
|
||||||
|
}
|
||||||
|
return sNpm;
|
||||||
|
}
|
||||||
|
|
||||||
public static Context getContext() {
|
public static Context getContext() {
|
||||||
return getInstrumentation().getContext();
|
return getInstrumentation().getContext();
|
||||||
}
|
}
|
||||||
@@ -415,4 +425,33 @@ public class NetworkPolicyTestUtils {
|
|||||||
public static Instrumentation getInstrumentation() {
|
public static Instrumentation getInstrumentation() {
|
||||||
return InstrumentationRegistry.getInstrumentation();
|
return InstrumentationRegistry.getInstrumentation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When power saver mode or restrict background enabled or adding any white/black list into
|
||||||
|
// those modes, NetworkPolicy may need to take some time to update the rules of uids. So having
|
||||||
|
// this function and using PollingCheck to try to make sure the uid has updated and reduce the
|
||||||
|
// flaky rate.
|
||||||
|
public static void assertNetworkingBlockedStatusForUid(int uid, boolean metered,
|
||||||
|
boolean expectedResult) throws Exception {
|
||||||
|
PollingCheck.waitFor(() -> (expectedResult == isUidNetworkingBlocked(uid, metered)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUidNetworkingBlocked(int uid, boolean meteredNetwork) {
|
||||||
|
final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
|
||||||
|
try {
|
||||||
|
uiAutomation.adoptShellPermissionIdentity();
|
||||||
|
return getNetworkPolicyManager().isUidNetworkingBlocked(uid, meteredNetwork);
|
||||||
|
} finally {
|
||||||
|
uiAutomation.dropShellPermissionIdentity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUidRestrictedOnMeteredNetworks(int uid) {
|
||||||
|
final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
|
||||||
|
try {
|
||||||
|
uiAutomation.adoptShellPermissionIdentity();
|
||||||
|
return getNetworkPolicyManager().isUidRestrictedOnMeteredNetworks(uid);
|
||||||
|
} finally {
|
||||||
|
uiAutomation.dropShellPermissionIdentity();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,28 +28,17 @@ public final class RestrictedModeTest extends AbstractRestrictBackgroundNetworkT
|
|||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
setRestrictedMode(false);
|
setRestrictedNetworkingMode(false);
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRestrictedMode(boolean enabled) throws Exception {
|
|
||||||
executeSilentShellCommand(
|
|
||||||
"settings put global restricted_networking_mode " + (enabled ? 1 : 0));
|
|
||||||
assertRestrictedModeState(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertRestrictedModeState(boolean enabled) throws Exception {
|
|
||||||
assertDelayedShellCommand("cmd netpolicy get restricted-mode",
|
|
||||||
"Restricted mode status: " + (enabled ? "enabled" : "disabled"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNetworkAccess() throws Exception {
|
public void testNetworkAccess() throws Exception {
|
||||||
setRestrictedMode(false);
|
setRestrictedNetworkingMode(false);
|
||||||
|
|
||||||
// go to foreground state and enable restricted mode
|
// go to foreground state and enable restricted mode
|
||||||
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
||||||
setRestrictedMode(true);
|
setRestrictedNetworkingMode(true);
|
||||||
assertForegroundNetworkAccess(false);
|
assertForegroundNetworkAccess(false);
|
||||||
|
|
||||||
// go to background state
|
// go to background state
|
||||||
@@ -57,7 +46,7 @@ public final class RestrictedModeTest extends AbstractRestrictBackgroundNetworkT
|
|||||||
assertBackgroundNetworkAccess(false);
|
assertBackgroundNetworkAccess(false);
|
||||||
|
|
||||||
// disable restricted mode and assert network access in foreground and background states
|
// disable restricted mode and assert network access in foreground and background states
|
||||||
setRestrictedMode(false);
|
setRestrictedNetworkingMode(false);
|
||||||
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
launchComponentAndAssertNetworkAccess(TYPE_COMPONENT_ACTIVTIY);
|
||||||
assertForegroundNetworkAccess(true);
|
assertForegroundNetworkAccess(true);
|
||||||
|
|
||||||
|
|||||||
@@ -760,7 +760,7 @@ public class VpnTest extends InstrumentationTestCase {
|
|||||||
assertEquals(vpnNetwork, mCM.getActiveNetwork());
|
assertEquals(vpnNetwork, mCM.getActiveNetwork());
|
||||||
assertNotEqual(defaultNetwork, vpnNetwork);
|
assertNotEqual(defaultNetwork, vpnNetwork);
|
||||||
maybeExpectVpnTransportInfo(vpnNetwork);
|
maybeExpectVpnTransportInfo(vpnNetwork);
|
||||||
assertTrue(mCM.getNetworkInfo(vpnNetwork).getType() == TYPE_VPN);
|
assertEquals(TYPE_VPN, mCM.getNetworkInfo(vpnNetwork).getType());
|
||||||
|
|
||||||
if (SdkLevel.isAtLeastS()) {
|
if (SdkLevel.isAtLeastS()) {
|
||||||
// Check that system default network callback has not seen any network changes, even
|
// Check that system default network callback has not seen any network changes, even
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.cts.net;
|
||||||
|
|
||||||
|
public class HostsideNetworkPolicyManagerTests extends HostsideNetworkTestCase {
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
uninstallPackage(TEST_APP2_PKG, false);
|
||||||
|
installPackage(TEST_APP2_APK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
uninstallPackage(TEST_APP2_PKG, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidNetworkingBlocked_withUidNotBlocked() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest",
|
||||||
|
"testIsUidNetworkingBlocked_withUidNotBlocked");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidNetworkingBlocked_withSystemUid() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest", "testIsUidNetworkingBlocked_withSystemUid");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidNetworkingBlocked_withDataSaverMode() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest",
|
||||||
|
"testIsUidNetworkingBlocked_withDataSaverMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidNetworkingBlocked_withRestrictedNetworkingMode() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest",
|
||||||
|
"testIsUidNetworkingBlocked_withRestrictedNetworkingMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidNetworkingBlocked_withPowerSaverMode() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest",
|
||||||
|
"testIsUidNetworkingBlocked_withPowerSaverMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsUidRestrictedOnMeteredNetworks() throws Exception {
|
||||||
|
runDeviceTests(TEST_PKG,
|
||||||
|
TEST_PKG + ".NetworkPolicyManagerTest", "testIsUidRestrictedOnMeteredNetworks");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import android.Manifest.permission.CONNECTIVITY_INTERNAL
|
|||||||
import android.Manifest.permission.NETWORK_SETTINGS
|
import android.Manifest.permission.NETWORK_SETTINGS
|
||||||
import android.Manifest.permission.READ_DEVICE_CONFIG
|
import android.Manifest.permission.READ_DEVICE_CONFIG
|
||||||
import android.content.pm.PackageManager.FEATURE_TELEPHONY
|
import android.content.pm.PackageManager.FEATURE_TELEPHONY
|
||||||
|
import android.content.pm.PackageManager.FEATURE_WATCH
|
||||||
import android.content.pm.PackageManager.FEATURE_WIFI
|
import android.content.pm.PackageManager.FEATURE_WIFI
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.ConnectivityManager.NetworkCallback
|
import android.net.ConnectivityManager.NetworkCallback
|
||||||
@@ -57,6 +58,7 @@ import fi.iki.elonen.NanoHTTPD.Response.Status
|
|||||||
import junit.framework.AssertionFailedError
|
import junit.framework.AssertionFailedError
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assume.assumeTrue
|
import org.junit.Assume.assumeTrue
|
||||||
|
import org.junit.Assume.assumeFalse
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
@@ -128,6 +130,7 @@ class CaptivePortalTest {
|
|||||||
fun testCaptivePortalIsNotDefaultNetwork() {
|
fun testCaptivePortalIsNotDefaultNetwork() {
|
||||||
assumeTrue(pm.hasSystemFeature(FEATURE_TELEPHONY))
|
assumeTrue(pm.hasSystemFeature(FEATURE_TELEPHONY))
|
||||||
assumeTrue(pm.hasSystemFeature(FEATURE_WIFI))
|
assumeTrue(pm.hasSystemFeature(FEATURE_WIFI))
|
||||||
|
assumeFalse(pm.hasSystemFeature(FEATURE_WATCH))
|
||||||
utils.ensureWifiConnected()
|
utils.ensureWifiConnected()
|
||||||
val cellNetwork = utils.connectToCell()
|
val cellNetwork = utils.connectToCell()
|
||||||
|
|
||||||
@@ -148,8 +151,8 @@ class CaptivePortalTest {
|
|||||||
server.addResponse(Request(TEST_PORTAL_URL_PATH), Status.OK,
|
server.addResponse(Request(TEST_PORTAL_URL_PATH), Status.OK,
|
||||||
content = "Test captive portal content")
|
content = "Test captive portal content")
|
||||||
server.addResponse(Request(TEST_HTTPS_URL_PATH), Status.INTERNAL_ERROR)
|
server.addResponse(Request(TEST_HTTPS_URL_PATH), Status.INTERNAL_ERROR)
|
||||||
server.addResponse(Request(TEST_HTTP_URL_PATH), Status.REDIRECT,
|
val headers = mapOf("Location" to makeUrl(TEST_PORTAL_URL_PATH))
|
||||||
locationHeader = makeUrl(TEST_PORTAL_URL_PATH))
|
server.addResponse(Request(TEST_HTTP_URL_PATH), Status.REDIRECT, headers)
|
||||||
setHttpsUrlDeviceConfig(makeUrl(TEST_HTTPS_URL_PATH))
|
setHttpsUrlDeviceConfig(makeUrl(TEST_HTTPS_URL_PATH))
|
||||||
setHttpUrlDeviceConfig(makeUrl(TEST_HTTP_URL_PATH))
|
setHttpUrlDeviceConfig(makeUrl(TEST_HTTP_URL_PATH))
|
||||||
// URL expiration needs to be in the next 10 minutes
|
// URL expiration needs to be in the next 10 minutes
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.net.cts;
|
|||||||
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
||||||
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
||||||
import static android.Manifest.permission.NETWORK_SETTINGS;
|
import static android.Manifest.permission.NETWORK_SETTINGS;
|
||||||
|
import static android.Manifest.permission.READ_DEVICE_CONFIG;
|
||||||
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
|
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
|
||||||
import static android.content.pm.PackageManager.FEATURE_ETHERNET;
|
import static android.content.pm.PackageManager.FEATURE_ETHERNET;
|
||||||
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
|
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
|
||||||
@@ -48,6 +49,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.TetheringManager.TETHERING_WIFI;
|
import static android.net.TetheringManager.TETHERING_WIFI;
|
||||||
@@ -60,6 +63,8 @@ import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
|
|||||||
import static android.net.cts.util.CtsTetheringUtils.StartTetheringCallback;
|
import static android.net.cts.util.CtsTetheringUtils.StartTetheringCallback;
|
||||||
import static android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
|
import static android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
|
||||||
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
|
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
|
||||||
|
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL;
|
||||||
|
import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL;
|
||||||
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
|
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
|
||||||
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
|
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
|
||||||
import static android.system.OsConstants.AF_INET;
|
import static android.system.OsConstants.AF_INET;
|
||||||
@@ -81,7 +86,6 @@ import static org.junit.Assert.assertNotEquals;
|
|||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNotSame;
|
import static org.junit.Assert.assertNotSame;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertThrows;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
@@ -122,6 +126,7 @@ import android.net.TelephonyNetworkSpecifier;
|
|||||||
import android.net.TestNetworkInterface;
|
import android.net.TestNetworkInterface;
|
||||||
import android.net.TestNetworkManager;
|
import android.net.TestNetworkManager;
|
||||||
import android.net.TetheringManager;
|
import android.net.TetheringManager;
|
||||||
|
import android.net.Uri;
|
||||||
import android.net.cts.util.CtsNetUtils;
|
import android.net.cts.util.CtsNetUtils;
|
||||||
import android.net.util.KeepaliveUtils;
|
import android.net.util.KeepaliveUtils;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@@ -136,6 +141,7 @@ import android.os.SystemProperties;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.VintfRuntimeInfo;
|
import android.os.VintfRuntimeInfo;
|
||||||
import android.platform.test.annotations.AppModeFull;
|
import android.platform.test.annotations.AppModeFull;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
@@ -160,6 +166,7 @@ import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
|||||||
import com.android.testutils.DevSdkIgnoreRuleKt;
|
import com.android.testutils.DevSdkIgnoreRuleKt;
|
||||||
import com.android.testutils.RecorderCallback.CallbackEntry;
|
import com.android.testutils.RecorderCallback.CallbackEntry;
|
||||||
import com.android.testutils.SkipPresubmit;
|
import com.android.testutils.SkipPresubmit;
|
||||||
|
import com.android.testutils.TestHttpServer;
|
||||||
import com.android.testutils.TestNetworkTracker;
|
import com.android.testutils.TestNetworkTracker;
|
||||||
import com.android.testutils.TestableNetworkCallback;
|
import com.android.testutils.TestableNetworkCallback;
|
||||||
|
|
||||||
@@ -192,6 +199,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -202,6 +210,10 @@ import java.util.function.Supplier;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import fi.iki.elonen.NanoHTTPD.Method;
|
||||||
|
import fi.iki.elonen.NanoHTTPD.Response.IStatus;
|
||||||
|
import fi.iki.elonen.NanoHTTPD.Response.Status;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class ConnectivityManagerTest {
|
public class ConnectivityManagerTest {
|
||||||
@Rule
|
@Rule
|
||||||
@@ -245,6 +257,12 @@ public class ConnectivityManagerTest {
|
|||||||
private static final int AIRPLANE_MODE_OFF = 0;
|
private static final int AIRPLANE_MODE_OFF = 0;
|
||||||
private static final int AIRPLANE_MODE_ON = 1;
|
private static final int AIRPLANE_MODE_ON = 1;
|
||||||
|
|
||||||
|
private static final String TEST_HTTPS_URL_PATH = "/https_path";
|
||||||
|
private static final String TEST_HTTP_URL_PATH = "/http_path";
|
||||||
|
private static final String LOCALHOST_HOSTNAME = "localhost";
|
||||||
|
// Re-connecting to the AP, obtaining an IP address, revalidating can take a long time
|
||||||
|
private static final long WIFI_CONNECT_TIMEOUT_MS = 60_000L;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private Instrumentation mInstrumentation;
|
private Instrumentation mInstrumentation;
|
||||||
private ConnectivityManager mCm;
|
private ConnectivityManager mCm;
|
||||||
@@ -259,6 +277,8 @@ public class ConnectivityManagerTest {
|
|||||||
// Used for cleanup purposes.
|
// Used for cleanup purposes.
|
||||||
private final List<Range<Integer>> mVpnRequiredUidRanges = new ArrayList<>();
|
private final List<Range<Integer>> mVpnRequiredUidRanges = new ArrayList<>();
|
||||||
|
|
||||||
|
private final TestHttpServer mHttpServer = new TestHttpServer(LOCALHOST_HOSTNAME);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
@@ -667,12 +687,14 @@ public class ConnectivityManagerTest {
|
|||||||
private NetworkRequest makeWifiNetworkRequest() {
|
private NetworkRequest makeWifiNetworkRequest() {
|
||||||
return new NetworkRequest.Builder()
|
return new NetworkRequest.Builder()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
.addCapability(NET_CAPABILITY_INTERNET)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkRequest makeCellNetworkRequest() {
|
private NetworkRequest makeCellNetworkRequest() {
|
||||||
return new NetworkRequest.Builder()
|
return new NetworkRequest.Builder()
|
||||||
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||||
|
.addCapability(NET_CAPABILITY_INTERNET)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2134,6 +2156,24 @@ public class ConnectivityManagerTest {
|
|||||||
null /* listener */));
|
null /* listener */));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSystemReady() {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
assertThrows(SecurityException.class, () -> mCm.systemReady());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetIpSecNetIdRange() {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
// The lower refers to ConnectivityManager.TUN_INTF_NETID_START.
|
||||||
|
final long lower = 64512;
|
||||||
|
// The upper refers to ConnectivityManager.TUN_INTF_NETID_START
|
||||||
|
// + ConnectivityManager.TUN_INTF_NETID_RANGE - 1
|
||||||
|
final long upper = 65535;
|
||||||
|
assertEquals(lower, (long) ConnectivityManager.getIpSecNetIdRange().getLower());
|
||||||
|
assertEquals(upper, (long) ConnectivityManager.getIpSecNetIdRange().getUpper());
|
||||||
|
}
|
||||||
|
|
||||||
private void verifySettings(int expectedAirplaneMode, int expectedPrivateDnsMode,
|
private void verifySettings(int expectedAirplaneMode, int expectedPrivateDnsMode,
|
||||||
int expectedAvoidBadWifi) throws Exception {
|
int expectedAvoidBadWifi) throws Exception {
|
||||||
assertEquals(expectedAirplaneMode, Settings.Global.getInt(
|
assertEquals(expectedAirplaneMode, Settings.Global.getInt(
|
||||||
@@ -2327,4 +2367,268 @@ public class ConnectivityManagerTest {
|
|||||||
}
|
}
|
||||||
oemPrefListener.expectOnComplete();
|
oemPrefListener.expectOnComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetAcceptPartialConnectivity_NoPermission_GetException() {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
assertThrows(SecurityException.class, () -> mCm.setAcceptPartialConnectivity(
|
||||||
|
mCm.getActiveNetwork(), false /* accept */ , false /* always */));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps")
|
||||||
|
@Test
|
||||||
|
public void testAcceptPartialConnectivity_validatedNetwork() throws Exception {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute"
|
||||||
|
+ " unless device supports WiFi",
|
||||||
|
mPackageManager.hasSystemFeature(FEATURE_WIFI));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wait for partial connectivity to be detected on the network
|
||||||
|
final Network network = preparePartialConnectivity();
|
||||||
|
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
// The always bit is verified in NetworkAgentTest
|
||||||
|
mCm.setAcceptPartialConnectivity(network, true /* accept */, false /* always */);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Accept partial connectivity network should result in a validated network
|
||||||
|
expectNetworkHasCapability(network, NET_CAPABILITY_VALIDATED, WIFI_CONNECT_TIMEOUT_MS);
|
||||||
|
} finally {
|
||||||
|
resetValidationConfig();
|
||||||
|
// Reconnect wifi to reset the wifi status
|
||||||
|
mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
|
||||||
|
mCtsNetUtils.ensureWifiConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps")
|
||||||
|
@Test
|
||||||
|
public void testRejectPartialConnectivity_TearDownNetwork() throws Exception {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute"
|
||||||
|
+ " unless device supports WiFi",
|
||||||
|
mPackageManager.hasSystemFeature(FEATURE_WIFI));
|
||||||
|
|
||||||
|
final TestNetworkCallback cb = new TestNetworkCallback();
|
||||||
|
try {
|
||||||
|
// Wait for partial connectivity to be detected on the network
|
||||||
|
final Network network = preparePartialConnectivity();
|
||||||
|
|
||||||
|
mCm.requestNetwork(makeWifiNetworkRequest(), cb);
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
// The always bit is verified in NetworkAgentTest
|
||||||
|
mCm.setAcceptPartialConnectivity(network, false /* accept */, false /* always */);
|
||||||
|
});
|
||||||
|
// Reject partial connectivity network should cause the network being torn down
|
||||||
|
assertEquals(network, cb.waitForLost());
|
||||||
|
} finally {
|
||||||
|
mCm.unregisterNetworkCallback(cb);
|
||||||
|
resetValidationConfig();
|
||||||
|
// Wifi will not automatically reconnect to the network. ensureWifiDisconnected cannot
|
||||||
|
// apply here. Thus, turn off wifi first and restart to restore.
|
||||||
|
runShellCommand("svc wifi disable");
|
||||||
|
mCtsNetUtils.ensureWifiConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetAcceptUnvalidated_NoPermission_GetException() {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
assertThrows(SecurityException.class, () -> mCm.setAcceptUnvalidated(
|
||||||
|
mCm.getActiveNetwork(), false /* accept */ , false /* always */));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AppModeFull(reason = "WRITE_DEVICE_CONFIG permission can't be granted to instant apps")
|
||||||
|
@Test
|
||||||
|
public void testRejectUnvalidated_TearDownNetwork() throws Exception {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
|
||||||
|
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
|
||||||
|
assumeTrue("testAcceptPartialConnectivity_validatedNetwork cannot execute"
|
||||||
|
+ " unless device supports WiFi and telephony", canRunTest);
|
||||||
|
|
||||||
|
final TestableNetworkCallback wifiCb = new TestableNetworkCallback();
|
||||||
|
try {
|
||||||
|
// Ensure at least one default network candidate connected.
|
||||||
|
mCtsNetUtils.connectToCell();
|
||||||
|
|
||||||
|
final Network wifiNetwork = prepareUnvalidatedNetwork();
|
||||||
|
// Default network should not be wifi ,but checking that wifi is not the default doesn't
|
||||||
|
// guarantee that it won't become the default in the future.
|
||||||
|
assertNotEquals(wifiNetwork, mCm.getActiveNetwork());
|
||||||
|
|
||||||
|
mCm.registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
mCm.setAcceptUnvalidated(wifiNetwork, false /* accept */, false /* always */);
|
||||||
|
});
|
||||||
|
waitForLost(wifiCb);
|
||||||
|
} finally {
|
||||||
|
mCm.unregisterNetworkCallback(wifiCb);
|
||||||
|
resetValidationConfig();
|
||||||
|
/// Wifi will not automatically reconnect to the network. ensureWifiDisconnected cannot
|
||||||
|
// apply here. Thus, turn off wifi first and restart to restore.
|
||||||
|
runShellCommand("svc wifi disable");
|
||||||
|
mCtsNetUtils.ensureWifiConnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Network expectNetworkHasCapability(Network network, int expectedNetCap, long timeout)
|
||||||
|
throws Exception {
|
||||||
|
final CompletableFuture<Network> future = new CompletableFuture();
|
||||||
|
final NetworkCallback cb = new NetworkCallback() {
|
||||||
|
@Override
|
||||||
|
public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) {
|
||||||
|
if (n.equals(network) && nc.hasCapability(expectedNetCap)) {
|
||||||
|
future.complete(network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), cb);
|
||||||
|
return future.get(timeout, TimeUnit.MILLISECONDS);
|
||||||
|
} finally {
|
||||||
|
mCm.unregisterNetworkCallback(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetValidationConfig() {
|
||||||
|
NetworkValidationTestUtil.clearValidationTestUrlsDeviceConfig();
|
||||||
|
mHttpServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareHttpServer() throws Exception {
|
||||||
|
runAsShell(READ_DEVICE_CONFIG, () -> {
|
||||||
|
// Verify that the test URLs are not normally set on the device, but do not fail if the
|
||||||
|
// test URLs are set to what this test uses (URLs on localhost), in case the test was
|
||||||
|
// interrupted manually and rerun.
|
||||||
|
assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL);
|
||||||
|
assertEmptyOrLocalhostUrl(TEST_CAPTIVE_PORTAL_HTTP_URL);
|
||||||
|
});
|
||||||
|
|
||||||
|
NetworkValidationTestUtil.clearValidationTestUrlsDeviceConfig();
|
||||||
|
|
||||||
|
mHttpServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Network preparePartialConnectivity() throws Exception {
|
||||||
|
prepareHttpServer();
|
||||||
|
// Configure response code for partial connectivity
|
||||||
|
configTestServer(Status.INTERNAL_ERROR /* httpsStatusCode */,
|
||||||
|
Status.NO_CONTENT /* httpStatusCode */);
|
||||||
|
// Disconnect wifi first then start wifi network with configuration.
|
||||||
|
mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
|
||||||
|
final Network network = mCtsNetUtils.ensureWifiConnected();
|
||||||
|
|
||||||
|
return expectNetworkHasCapability(network, NET_CAPABILITY_PARTIAL_CONNECTIVITY,
|
||||||
|
WIFI_CONNECT_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Network prepareUnvalidatedNetwork() throws Exception {
|
||||||
|
prepareHttpServer();
|
||||||
|
// Configure response code for unvalidated network
|
||||||
|
configTestServer(Status.INTERNAL_ERROR /* httpsStatusCode */,
|
||||||
|
Status.INTERNAL_ERROR /* httpStatusCode */);
|
||||||
|
|
||||||
|
// Disconnect wifi first then start wifi network with configuration.
|
||||||
|
mCtsNetUtils.ensureWifiDisconnected(null /* wifiNetworkToCheck */);
|
||||||
|
final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
|
||||||
|
return expectNetworkHasCapability(wifiNetwork, NET_CAPABILITY_INTERNET,
|
||||||
|
WIFI_CONNECT_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String makeUrl(String path) {
|
||||||
|
return "http://localhost:" + mHttpServer.getListeningPort() + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEmptyOrLocalhostUrl(String urlKey) {
|
||||||
|
final String url = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, urlKey);
|
||||||
|
assertTrue(urlKey + " must not be set in production scenarios, current value= " + url,
|
||||||
|
TextUtils.isEmpty(url) || LOCALHOST_HOSTNAME.equals(Uri.parse(url).getHost()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configTestServer(IStatus httpsStatusCode, IStatus httpStatusCode) {
|
||||||
|
mHttpServer.addResponse(new TestHttpServer.Request(
|
||||||
|
TEST_HTTPS_URL_PATH, Method.GET, "" /* queryParameters */),
|
||||||
|
httpsStatusCode, null /* locationHeader */, "" /* content */);
|
||||||
|
mHttpServer.addResponse(new TestHttpServer.Request(
|
||||||
|
TEST_HTTP_URL_PATH, Method.GET, "" /* queryParameters */),
|
||||||
|
httpStatusCode, null /* locationHeader */, "" /* content */);
|
||||||
|
NetworkValidationTestUtil.setHttpsUrlDeviceConfig(makeUrl(TEST_HTTPS_URL_PATH));
|
||||||
|
NetworkValidationTestUtil.setHttpUrlDeviceConfig(makeUrl(TEST_HTTP_URL_PATH));
|
||||||
|
NetworkValidationTestUtil.setUrlExpirationDeviceConfig(
|
||||||
|
System.currentTimeMillis() + WIFI_CONNECT_TIMEOUT_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
|
||||||
|
@Test
|
||||||
|
public void testMobileDataPreferredUids() throws Exception {
|
||||||
|
assumeTrue(TestUtils.shouldTestSApis());
|
||||||
|
final boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
|
||||||
|
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
|
||||||
|
assumeTrue("testMobileDataPreferredUidsWithCallback cannot execute"
|
||||||
|
+ " unless device supports both WiFi and telephony", canRunTest);
|
||||||
|
|
||||||
|
final int uid = mPackageManager.getPackageUid(mContext.getPackageName(), 0 /* flag */);
|
||||||
|
final Set<Integer> mobileDataPreferredUids =
|
||||||
|
ConnectivitySettingsManager.getMobileDataPreferredUids(mContext);
|
||||||
|
// CtsNetTestCases uid should not list in MOBILE_DATA_PREFERRED_UIDS setting because it just
|
||||||
|
// installs to device. In case the uid is existed in setting mistakenly, try to remove the
|
||||||
|
// uid and set correct uids to setting.
|
||||||
|
mobileDataPreferredUids.remove(uid);
|
||||||
|
ConnectivitySettingsManager.setMobileDataPreferredUids(mContext, mobileDataPreferredUids);
|
||||||
|
|
||||||
|
// For testing mobile data preferred uids feature, it needs both wifi and cell network.
|
||||||
|
final Network wifiNetwork = mCtsNetUtils.ensureWifiConnected();
|
||||||
|
final Network cellNetwork = mCtsNetUtils.connectToCell();
|
||||||
|
final TestableNetworkCallback defaultTrackingCb = new TestableNetworkCallback();
|
||||||
|
final TestableNetworkCallback systemDefaultCb = new TestableNetworkCallback();
|
||||||
|
final Handler h = new Handler(Looper.getMainLooper());
|
||||||
|
runWithShellPermissionIdentity(() -> mCm.registerSystemDefaultNetworkCallback(
|
||||||
|
systemDefaultCb, h), NETWORK_SETTINGS);
|
||||||
|
mCm.registerDefaultNetworkCallback(defaultTrackingCb);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// CtsNetTestCases uid is not listed in MOBILE_DATA_PREFERRED_UIDS setting, so the
|
||||||
|
// per-app default network should be same as system default network.
|
||||||
|
waitForAvailable(systemDefaultCb, wifiNetwork);
|
||||||
|
defaultTrackingCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
|
||||||
|
entry -> wifiNetwork.equals(entry.getNetwork()));
|
||||||
|
// Active network for CtsNetTestCases uid should be wifi now.
|
||||||
|
assertEquals(wifiNetwork, mCm.getActiveNetwork());
|
||||||
|
|
||||||
|
// Add CtsNetTestCases uid to MOBILE_DATA_PREFERRED_UIDS setting, then available per-app
|
||||||
|
// default network callback should be received with cell network.
|
||||||
|
final Set<Integer> newMobileDataPreferredUids = new ArraySet<>(mobileDataPreferredUids);
|
||||||
|
newMobileDataPreferredUids.add(uid);
|
||||||
|
ConnectivitySettingsManager.setMobileDataPreferredUids(
|
||||||
|
mContext, newMobileDataPreferredUids);
|
||||||
|
defaultTrackingCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
|
||||||
|
entry -> cellNetwork.equals(entry.getNetwork()));
|
||||||
|
// System default network doesn't change.
|
||||||
|
systemDefaultCb.assertNoCallback();
|
||||||
|
// Active network for CtsNetTestCases uid should change to cell, too.
|
||||||
|
assertEquals(cellNetwork, mCm.getActiveNetwork());
|
||||||
|
|
||||||
|
// Remove CtsNetTestCases uid from MOBILE_DATA_PREFERRED_UIDS setting, then available
|
||||||
|
// per-app default network callback should be received again with system default network
|
||||||
|
newMobileDataPreferredUids.remove(uid);
|
||||||
|
ConnectivitySettingsManager.setMobileDataPreferredUids(
|
||||||
|
mContext, newMobileDataPreferredUids);
|
||||||
|
defaultTrackingCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
|
||||||
|
entry -> wifiNetwork.equals(entry.getNetwork()));
|
||||||
|
// System default network still doesn't change.
|
||||||
|
systemDefaultCb.assertNoCallback();
|
||||||
|
// Active network for CtsNetTestCases uid should change back to wifi.
|
||||||
|
assertEquals(wifiNetwork, mCm.getActiveNetwork());
|
||||||
|
} finally {
|
||||||
|
mCm.unregisterNetworkCallback(systemDefaultCb);
|
||||||
|
mCm.unregisterNetworkCallback(defaultTrackingCb);
|
||||||
|
|
||||||
|
// Restore setting.
|
||||||
|
ConnectivitySettingsManager.setMobileDataPreferredUids(
|
||||||
|
mContext, mobileDataPreferredUids);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ internal object NetworkValidationTestUtil {
|
|||||||
/**
|
/**
|
||||||
* Clear the test network validation URLs.
|
* Clear the test network validation URLs.
|
||||||
*/
|
*/
|
||||||
fun clearValidationTestUrlsDeviceConfig() {
|
@JvmStatic fun clearValidationTestUrlsDeviceConfig() {
|
||||||
setHttpsUrlDeviceConfig(null)
|
setHttpsUrlDeviceConfig(null)
|
||||||
setHttpUrlDeviceConfig(null)
|
setHttpUrlDeviceConfig(null)
|
||||||
setUrlExpirationDeviceConfig(null)
|
setUrlExpirationDeviceConfig(null)
|
||||||
@@ -40,7 +40,7 @@ internal object NetworkValidationTestUtil {
|
|||||||
*
|
*
|
||||||
* @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
|
* @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
|
||||||
*/
|
*/
|
||||||
fun setHttpsUrlDeviceConfig(url: String?) =
|
@JvmStatic fun setHttpsUrlDeviceConfig(url: String?) =
|
||||||
setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
|
setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +48,7 @@ internal object NetworkValidationTestUtil {
|
|||||||
*
|
*
|
||||||
* @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
|
* @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
|
||||||
*/
|
*/
|
||||||
fun setHttpUrlDeviceConfig(url: String?) =
|
@JvmStatic fun setHttpUrlDeviceConfig(url: String?) =
|
||||||
setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
|
setConfig(NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +56,7 @@ internal object NetworkValidationTestUtil {
|
|||||||
*
|
*
|
||||||
* @see NetworkStackUtils.TEST_URL_EXPIRATION_TIME
|
* @see NetworkStackUtils.TEST_URL_EXPIRATION_TIME
|
||||||
*/
|
*/
|
||||||
fun setUrlExpirationDeviceConfig(timestamp: Long?) =
|
@JvmStatic fun setUrlExpirationDeviceConfig(timestamp: Long?) =
|
||||||
setConfig(NetworkStackUtils.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
|
setConfig(NetworkStackUtils.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
|
||||||
|
|
||||||
private fun setConfig(configKey: String, value: String?) {
|
private fun setConfig(configKey: String, value: String?) {
|
||||||
|
|||||||
192
tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
Normal file
192
tests/cts/net/src/android/net/cts/PacProxyManagerTest.java
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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 android.net.cts;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.NETWORK_SETTINGS;
|
||||||
|
|
||||||
|
import static com.android.testutils.TestPermissionUtil.runAsShell;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.Network;
|
||||||
|
import android.net.PacProxyManager;
|
||||||
|
import android.net.Proxy;
|
||||||
|
import android.net.ProxyInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Range;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
|
||||||
|
import com.android.testutils.DevSdkIgnoreRunner;
|
||||||
|
import com.android.testutils.TestHttpServer;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import fi.iki.elonen.NanoHTTPD.Response.Status;
|
||||||
|
|
||||||
|
@IgnoreUpTo(Build.VERSION_CODES.R)
|
||||||
|
@RunWith(DevSdkIgnoreRunner.class)
|
||||||
|
public final class PacProxyManagerTest {
|
||||||
|
private static final String TAG = PacProxyManagerTest.class.getSimpleName();
|
||||||
|
private static final int PROXY_CHANGED_BROADCAST_TIMEOUT_MS = 5000;
|
||||||
|
private static final int CALLBACK_TIMEOUT_MS = 3 * 1000;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private TestHttpServer mServer;
|
||||||
|
private ConnectivityManager mCm;
|
||||||
|
private PacProxyManager mPacProxyManager;
|
||||||
|
private ServerSocket mServerSocket;
|
||||||
|
private Instrumentation mInstrumentation;
|
||||||
|
|
||||||
|
private static final String PAC_FILE = "function FindProxyForURL(url, host)"
|
||||||
|
+ "{"
|
||||||
|
+ " return \"PROXY 192.168.0.1:9091\";"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
mContext = mInstrumentation.getContext();
|
||||||
|
|
||||||
|
mCm = mContext.getSystemService(ConnectivityManager.class);
|
||||||
|
mPacProxyManager = (PacProxyManager) mContext.getSystemService(PacProxyManager.class);
|
||||||
|
mServer = new TestHttpServer();
|
||||||
|
mServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
if (mServer != null) {
|
||||||
|
mServer.stop();
|
||||||
|
mServer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestPacProxyInstalledListener implements
|
||||||
|
PacProxyManager.PacProxyInstalledListener {
|
||||||
|
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
|
public void onPacProxyInstalled(Network network, ProxyInfo proxy) {
|
||||||
|
Log.e(TAG, "onPacProxyInstalled is called.");
|
||||||
|
mLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean waitForCallback() throws Exception {
|
||||||
|
final boolean result = mLatch.await(CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProxyBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||||
|
private final ProxyInfo mProxy;
|
||||||
|
|
||||||
|
ProxyBroadcastReceiver(ProxyInfo proxy) {
|
||||||
|
mProxy = proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
final ProxyInfo proxy = (ProxyInfo) intent.getExtra(Proxy.EXTRA_PROXY_INFO,
|
||||||
|
ProxyInfo.buildPacProxy(Uri.EMPTY));
|
||||||
|
// ProxyTracker sends sticky broadcast which will receive the last broadcast while
|
||||||
|
// register the intent receiver. That is, if system never receives the intent then
|
||||||
|
// it won't receive an intent when register the receiver. How many intents will be
|
||||||
|
// received in the test is unpredictable so here counts down the latch when the PAC
|
||||||
|
// file in the intent is the same as the one at registration.
|
||||||
|
if (mProxy.getPacFileUrl().equals(proxy.getPacFileUrl())) {
|
||||||
|
// Host/Port represent a local proxy server that redirects to the PAC-configured
|
||||||
|
// server. Host should be "localhost" and the port should be a value which is
|
||||||
|
// between 0 and 65535.
|
||||||
|
assertEquals(proxy.getHost(), "localhost");
|
||||||
|
assertInRange(proxy.getPort(), 0 /* lower */, 65535 /* upper */);
|
||||||
|
mLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean waitForProxyChanged() throws Exception {
|
||||||
|
final boolean result = mLatch.await(PROXY_CHANGED_BROADCAST_TIMEOUT_MS,
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetCurrentProxyScriptUrl() throws Exception {
|
||||||
|
// Register a PacProxyInstalledListener
|
||||||
|
final TestPacProxyInstalledListener listener = new TestPacProxyInstalledListener();
|
||||||
|
final Executor executor = (Runnable r) -> r.run();
|
||||||
|
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
mPacProxyManager.addPacProxyInstalledListener(executor, listener);
|
||||||
|
});
|
||||||
|
|
||||||
|
final Map<String, String> headers = new HashMap<String, String>();
|
||||||
|
headers.put("Content-Type", "application/x-ns-proxy-autoconfig");
|
||||||
|
final Uri pacProxyUrl = Uri.parse("http://localhost:"
|
||||||
|
+ mServer.getListeningPort() + "/proxy.pac");
|
||||||
|
mServer.addResponse(pacProxyUrl, Status.OK, headers, PAC_FILE);
|
||||||
|
|
||||||
|
final ProxyInfo proxy = ProxyInfo.buildPacProxy(pacProxyUrl);
|
||||||
|
final ProxyBroadcastReceiver receiver = new ProxyBroadcastReceiver(proxy);
|
||||||
|
mContext.registerReceiver(receiver, new IntentFilter(Proxy.PROXY_CHANGE_ACTION));
|
||||||
|
|
||||||
|
// Call setCurrentProxyScriptUrl with the URL of the pac file.
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
mPacProxyManager.setCurrentProxyScriptUrl(proxy);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure the listener was called and testing the intent is received.
|
||||||
|
try {
|
||||||
|
assertTrue("Didn't receive PROXY_CHANGE_ACTION broadcast.",
|
||||||
|
receiver.waitForProxyChanged());
|
||||||
|
assertTrue("Did not receive onPacProxyInstalled callback.",
|
||||||
|
listener.waitForCallback());
|
||||||
|
} finally {
|
||||||
|
runAsShell(NETWORK_SETTINGS, () -> {
|
||||||
|
mPacProxyManager.removePacProxyInstalledListener(listener);
|
||||||
|
});
|
||||||
|
mContext.unregisterReceiver(receiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertInRange(int value, int lower, int upper) {
|
||||||
|
final Range range = new Range(lower, upper);
|
||||||
|
assertTrue(value + "is not within range [" + lower + ", " + upper + "]",
|
||||||
|
range.contains(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2009 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 android.net.cts;
|
|
||||||
|
|
||||||
|
|
||||||
import android.net.Proxy;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
|
|
||||||
public class ProxyTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
public void testConstructor() {
|
|
||||||
new Proxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAccessProperties() {
|
|
||||||
final int minValidPort = 0;
|
|
||||||
final int maxValidPort = 65535;
|
|
||||||
int defaultPort = Proxy.getDefaultPort();
|
|
||||||
if(null == Proxy.getDefaultHost()) {
|
|
||||||
assertEquals(-1, defaultPort);
|
|
||||||
} else {
|
|
||||||
assertTrue(defaultPort >= minValidPort && defaultPort <= maxValidPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
103
tests/cts/net/src/android/net/cts/ProxyTest.kt
Normal file
103
tests/cts/net/src/android/net/cts/ProxyTest.kt
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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 android.net.cts
|
||||||
|
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.Proxy
|
||||||
|
import android.net.ProxyInfo
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.text.TextUtils
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import com.android.testutils.DevSdkIgnoreRule
|
||||||
|
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ProxyTest {
|
||||||
|
@get:Rule
|
||||||
|
val ignoreRule = DevSdkIgnoreRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testConstructor() {
|
||||||
|
Proxy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAccessProperties() {
|
||||||
|
val minValidPort = 0
|
||||||
|
val maxValidPort = 65535
|
||||||
|
val defaultPort = Proxy.getDefaultPort()
|
||||||
|
if (null == Proxy.getDefaultHost()) {
|
||||||
|
assertEquals(-1, defaultPort.toLong())
|
||||||
|
} else {
|
||||||
|
Assert.assertTrue(defaultPort in minValidPort..maxValidPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun verifyProxySystemProperties(info: ProxyInfo) {
|
||||||
|
assertEquals(info.host, System.getProperty("http.proxyHost"))
|
||||||
|
assertEquals(info.host, System.getProperty("https.proxyHost"))
|
||||||
|
|
||||||
|
assertEquals(info.port.toString(), System.getProperty("http.proxyPort"))
|
||||||
|
assertEquals(info.port.toString(), System.getProperty("https.proxyPort"))
|
||||||
|
|
||||||
|
val strExcludes = if (info.exclusionList.isEmpty()) null
|
||||||
|
else TextUtils.join("|", info.exclusionList)
|
||||||
|
assertEquals(strExcludes, System.getProperty("https.nonProxyHosts"))
|
||||||
|
assertEquals(strExcludes, System.getProperty("http.nonProxyHosts"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getDefaultProxy(): ProxyInfo? {
|
||||||
|
return InstrumentationRegistry.getInstrumentation().context
|
||||||
|
.getSystemService(ConnectivityManager::class.java)
|
||||||
|
.getDefaultProxy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test @IgnoreUpTo(Build.VERSION_CODES.R) // setHttpProxyConfiguration was added in S
|
||||||
|
fun testSetHttpProxyConfiguration_DirectProxy() {
|
||||||
|
val info = ProxyInfo.buildDirectProxy(
|
||||||
|
"testproxy.android.com",
|
||||||
|
12345 /* port */,
|
||||||
|
listOf("testexclude1.android.com", "testexclude2.android.com"))
|
||||||
|
val original = getDefaultProxy()
|
||||||
|
try {
|
||||||
|
Proxy.setHttpProxyConfiguration(info)
|
||||||
|
verifyProxySystemProperties(info)
|
||||||
|
} finally {
|
||||||
|
Proxy.setHttpProxyConfiguration(original)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test @IgnoreUpTo(Build.VERSION_CODES.R) // setHttpProxyConfiguration was added in S
|
||||||
|
fun testSetHttpProxyConfiguration_PacProxy() {
|
||||||
|
val pacInfo = ProxyInfo.buildPacProxy(Uri.parse("http://testpac.android.com/pac.pac"))
|
||||||
|
val original = getDefaultProxy()
|
||||||
|
try {
|
||||||
|
Proxy.setHttpProxyConfiguration(pacInfo)
|
||||||
|
verifyProxySystemProperties(pacInfo)
|
||||||
|
} finally {
|
||||||
|
Proxy.setHttpProxyConfiguration(original)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,5 +27,6 @@ java_library {
|
|||||||
"junit",
|
"junit",
|
||||||
"net-tests-utils",
|
"net-tests-utils",
|
||||||
"modules-utils-build",
|
"modules-utils-build",
|
||||||
|
"net-utils-framework-common",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,62 +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)) {
|
|
||||||
setPrivateDnsStrictMode(mOldPrivateDnsSpecifier);
|
|
||||||
|
|
||||||
// In case of invalid setting, still restore it but fail the test
|
if (mOldPrivateDnsMode != ConnectivitySettingsUtils.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
|
||||||
if (mOldPrivateDnsSpecifier == null) {
|
ConnectivitySettingsUtils.setPrivateDnsMode(mContext, mOldPrivateDnsMode);
|
||||||
fail("Invalid private DNS setting: no hostname specified in strict mode");
|
return;
|
||||||
}
|
|
||||||
awaitPrivateDnsSetting("restorePrivateDnsSetting timeout",
|
|
||||||
mCm.getActiveNetwork(),
|
|
||||||
mOldPrivateDnsSpecifier, true);
|
|
||||||
} 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())) {
|
||||||
@@ -583,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user