Add the flag and default enable selectAllPrefixRange

Also add MtsTetheringTest which only run if tethering mainline
module is installed.

Bug: 166057846
Bug: 170265597
Test: atest TetheringTests
Change-Id: I434dda81eb5fab700d873a8ff3429b4222f0c7e6
This commit is contained in:
markchien
2020-10-15 09:42:31 +08:00
parent 8565b0244a
commit 4607c5535b
9 changed files with 365 additions and 14 deletions

View File

@@ -80,11 +80,6 @@ public class PrivateAddressCoordinator {
private final SparseArray<LinkAddress> mCachedAddresses;
public PrivateAddressCoordinator(Context context, TetheringConfiguration config) {
this(context, config, new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16"))));
}
public PrivateAddressCoordinator(Context context, TetheringConfiguration config,
List<IpPrefix> prefixPools) {
mDownstreams = new ArraySet<>();
mUpstreamPrefixMap = new ArrayMap<>();
mConnectivityMgr = (ConnectivityManager) context.getSystemService(
@@ -95,7 +90,11 @@ public class PrivateAddressCoordinator {
mCachedAddresses.put(TETHERING_BLUETOOTH, new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS));
mCachedAddresses.put(TETHERING_WIFI_P2P, new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));
mTetheringPrefixes = prefixPools;
mTetheringPrefixes = new ArrayList<>(Arrays.asList(new IpPrefix("192.168.0.0/16")));
if (config.isSelectAllPrefixRangeEnabled()) {
mTetheringPrefixes.add(new IpPrefix("172.16.0.0/12"));
mTetheringPrefixes.add(new IpPrefix("10.0.0.0/8"));
}
}
/**

View File

@@ -40,7 +40,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.StringJoiner;
/**
* A utility class to encapsulate the various tethering configuration elements.
*
@@ -87,6 +86,13 @@ public class TetheringConfiguration {
public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP =
"use_legacy_wifi_p2p_dedicated_ip";
/**
* Flag use to enable select all prefix ranges feature.
* TODO: Remove this flag if there are no problems after M-2020-12 rolls out.
*/
public static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
"tether_enable_select_all_prefix_ranges";
/**
* Default value that used to periodic polls tether offload stats from tethering offload HAL
* to make the data warnings work.
@@ -118,6 +124,8 @@ public class TetheringConfiguration {
private final boolean mEnableBpfOffload;
private final boolean mEnableWifiP2pDedicatedIp;
private final boolean mEnableSelectAllPrefixRange;
public TetheringConfiguration(Context ctx, SharedLog log, int id) {
final SharedLog configLog = log.forSubComponent("config");
@@ -164,6 +172,11 @@ public class TetheringConfiguration {
R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip,
false /* defaultValue */);
// Flags should normally not be booleans, but this is a kill-switch flag that is only used
// to turn off the feature, so binary rollback problems do not apply.
mEnableSelectAllPrefixRange = getDeviceConfigBoolean(
TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true /* defaultValue */);
configLog.log(toString());
}
@@ -249,6 +262,9 @@ public class TetheringConfiguration {
pw.print("enableWifiP2pDedicatedIp: ");
pw.println(mEnableWifiP2pDedicatedIp);
pw.print("mEnableSelectAllPrefixRange: ");
pw.println(mEnableSelectAllPrefixRange);
}
/** Returns the string representation of this object.*/
@@ -310,6 +326,10 @@ public class TetheringConfiguration {
return mEnableBpfOffload;
}
public boolean isSelectAllPrefixRangeEnabled() {
return mEnableSelectAllPrefixRange;
}
private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) {
final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types);
final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length);

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2020 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.
android_test {
// This tests for functionality that is not required for devices that
// don't use Tethering mainline module.
name: "MtsTetheringTest",
libs: [
"android.test.base",
],
srcs: [
"src/**/*.java",
],
static_libs: [
"androidx.test.rules",
// mockito-target-extended-minus-junit4 used in this lib have dependency with
// jni_libs libdexmakerjvmtiagent and libstaticjvmtiagent.
"cts-net-utils",
// This is needed for androidx.test.runner.AndroidJUnitRunner.
"ctstestrunner-axt",
"junit",
"junit-params",
],
jni_libs: [
// For mockito extended which is pulled in from -net-utils -> net-tests-utils
// (mockito-target-extended-minus-junit4).
"libdexmakerjvmtiagent",
"libstaticjvmtiagent",
],
platform_apis: true,
// Tag this module as a mts test artifact
test_suites: [
"general-tests",
"mts",
],
// Include both the 32 and 64 bit versions
compile_multilib: "both",
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (C) 2020 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.tethering.mts">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.tethering.mts"
android:label="MTS tests of android.tethering">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 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.
-->
<configuration description="Config for MTS Tethering test cases">
<option name="test-suite-tag" value="mts" />
<option name="config-descriptor:metadata" key="component" value="networking" />
<!-- Instant app do not have INTERNET permission. -->
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<!-- Feature is not backed by native code. -->
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<!-- Allow running this against a secondary user. -->
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="MtsTetheringTest.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.tethering.mts" />
</test>
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
<option name="mainline-module-package-name" value="com.google.android.tethering" />
</object>
</configuration>

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2020 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.tethering.mts;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.READ_DEVICE_CONFIG;
import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.Manifest.permission.WRITE_SETTINGS;
import static android.net.cts.util.CtsTetheringUtils.isWifiTetheringSupported;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.app.UiAutomation;
import android.content.Context;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.TetheringManager;
import android.net.cts.util.CtsTetheringUtils;
import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
import android.provider.DeviceConfig;
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.testutils.TestNetworkTracker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class TetheringModuleTest {
private Context mContext;
private TetheringManager mTm;
private CtsTetheringUtils mCtsTetheringUtils;
private UiAutomation mUiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
@Before
public void setUp() throws Exception {
mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS,
WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED);
mContext = InstrumentationRegistry.getContext();
mTm = mContext.getSystemService(TetheringManager.class);
mCtsTetheringUtils = new CtsTetheringUtils(mContext);
}
@After
public void tearDown() throws Exception {
mUiAutomation.dropShellPermissionIdentity();
}
private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES =
"tether_enable_select_all_prefix_ranges";
@Test
public void testSwitchBasePrefixRangeWhenConflict() throws Exception {
assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true));
addressConflictTest(true);
}
@Test
public void testSwitchPrefixRangeWhenConflict() throws Exception {
addressConflictTest(false);
}
private void addressConflictTest(final boolean wholeRangeConflict) throws Exception {
final TestTetheringEventCallback tetherEventCallback =
mCtsTetheringUtils.registerTetheringEventCallback();
TestNetworkTracker tnt = null;
try {
tetherEventCallback.assumeTetheringSupported();
assumeTrue(isWifiTetheringSupported(tetherEventCallback));
mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
final List<String> tetheredIfaces = tetherEventCallback.getTetheredInterfaces();
assertEquals(1, tetheredIfaces.size());
final String wifiTetheringIface = tetheredIfaces.get(0);
NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface);
// Tethering downstream only have one ipv4 address.
final LinkAddress hotspotAddr = getFirstIpv4Address(nif);
assertNotNull(hotspotAddr);
final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict);
assertNotNull(testPrefix);
tnt = setUpTestNetwork(
new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength()));
tetherEventCallback.expectTetheredInterfacesChanged(null);
final List<String> wifiRegexs =
tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs();
tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs);
nif = NetworkInterface.getByName(wifiTetheringIface);
final LinkAddress newHotspotAddr = getFirstIpv4Address(nif);
assertNotNull(newHotspotAddr);
assertFalse(testPrefix.containsPrefix(
new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength())));
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
} finally {
if (tnt != null) {
tnt.teardown();
}
mTm.stopAllTethering();
mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
}
}
private LinkAddress getFirstIpv4Address(final NetworkInterface nif) {
for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength());
if (addr.isIpv4()) return addr;
}
return null;
}
@NonNull
private IpPrefix getConflictingPrefix(final LinkAddress address,
final boolean wholeRangeConflict) {
if (!wholeRangeConflict) {
return new IpPrefix(address.getAddress(), address.getPrefixLength());
}
final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
new IpPrefix("192.168.0.0/16"),
new IpPrefix("172.16.0.0/12"),
new IpPrefix("10.0.0.0/8")));
for (IpPrefix prefix : prefixPool) {
if (prefix.contains(address.getAddress())) return prefix;
}
fail("Could not find sutiable conflict prefix");
// Never go here.
return null;
}
private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception {
return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/);
}
public static boolean isFeatureEnabled(final String name, final boolean defaultValue) {
return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue);
}
}

View File

@@ -99,9 +99,9 @@ public final class PrivateAddressCoordinatorTest {
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mConnectivityMgr);
when(mConnectivityMgr.getAllNetworks()).thenReturn(mAllNetworks);
when(mConfig.shouldEnableWifiP2pDedicatedIp()).thenReturn(false);
when(mConfig.isSelectAllPrefixRangeEnabled()).thenReturn(true);
setUpIpServers();
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig,
mTetheringPrefixes));
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(mContext, mConfig));
}
private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) {

View File

@@ -131,6 +131,7 @@ public class TetheringConfigurationTest {
when(mResources.getBoolean(R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip))
.thenReturn(false);
initializeBpfOffloadConfiguration(true, null /* unset */);
initEnableSelectAllPrefixRangeFlag(null /* unset */);
mHasTelephonyManager = true;
mMockContext = new MockContext(mContext);
@@ -428,4 +429,30 @@ public class TetheringConfigurationTest {
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(testCfg.shouldEnableWifiP2pDedicatedIp());
}
private void initEnableSelectAllPrefixRangeFlag(final String value) {
doReturn(value).when(
() -> DeviceConfig.getProperty(eq(NAMESPACE_CONNECTIVITY),
eq(TetheringConfiguration.TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES)));
}
@Test
public void testSelectAllPrefixRangeFlag() throws Exception {
// Test default value.
final TetheringConfiguration defaultCfg = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(defaultCfg.isSelectAllPrefixRangeEnabled());
// Test disable flag.
initEnableSelectAllPrefixRangeFlag("false");
final TetheringConfiguration testDisable = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertFalse(testDisable.isSelectAllPrefixRangeEnabled());
// Test enable flag.
initEnableSelectAllPrefixRangeFlag("true");
final TetheringConfiguration testEnable = new TetheringConfiguration(
mMockContext, mLog, INVALID_SUBSCRIPTION_ID);
assertTrue(testEnable.isSelectAllPrefixRangeEnabled());
}
}

View File

@@ -456,11 +456,7 @@ public class TetheringTest {
@Override
public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
TetheringConfiguration cfg) {
final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList(
new IpPrefix("192.168.0.0/16"),
new IpPrefix("172.16.0.0/12"),
new IpPrefix("10.0.0.0/8")));
mPrivateAddressCoordinator = spy(new PrivateAddressCoordinator(ctx, cfg, prefixPool));
mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg);
return mPrivateAddressCoordinator;
}
}