1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.tethering.mts; 17 18 import static android.Manifest.permission.ACCESS_WIFI_STATE; 19 import static android.Manifest.permission.MANAGE_TEST_NETWORKS; 20 import static android.Manifest.permission.NETWORK_SETTINGS; 21 import static android.Manifest.permission.READ_DEVICE_CONFIG; 22 import static android.Manifest.permission.TETHER_PRIVILEGED; 23 import static android.Manifest.permission.WRITE_SETTINGS; 24 import static android.net.TetheringManager.TETHERING_WIFI; 25 import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; 26 27 import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork; 28 29 import static org.junit.Assert.assertFalse; 30 import static org.junit.Assert.assertNotNull; 31 import static org.junit.Assert.fail; 32 import static org.junit.Assume.assumeTrue; 33 34 import android.app.UiAutomation; 35 import android.content.Context; 36 import android.net.IpPrefix; 37 import android.net.LinkAddress; 38 import android.net.TetheringInterface; 39 import android.net.TetheringManager; 40 import android.net.cts.util.CtsTetheringUtils; 41 import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; 42 import android.provider.DeviceConfig; 43 44 import androidx.annotation.NonNull; 45 import androidx.test.InstrumentationRegistry; 46 import androidx.test.runner.AndroidJUnit4; 47 48 import com.android.testutils.TestNetworkTracker; 49 50 import org.junit.After; 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 55 import java.net.InterfaceAddress; 56 import java.net.NetworkInterface; 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.List; 60 61 @RunWith(AndroidJUnit4.class) 62 public class TetheringModuleTest { 63 private Context mContext; 64 private TetheringManager mTm; 65 private CtsTetheringUtils mCtsTetheringUtils; 66 67 private UiAutomation mUiAutomation = 68 InstrumentationRegistry.getInstrumentation().getUiAutomation(); 69 70 @Before setUp()71 public void setUp() throws Exception { 72 mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, 73 WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED, ACCESS_WIFI_STATE); 74 mContext = InstrumentationRegistry.getContext(); 75 mTm = mContext.getSystemService(TetheringManager.class); 76 mCtsTetheringUtils = new CtsTetheringUtils(mContext); 77 } 78 79 @After tearDown()80 public void tearDown() throws Exception { 81 mUiAutomation.dropShellPermissionIdentity(); 82 } 83 84 private static final String TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES = 85 "tether_enable_select_all_prefix_ranges"; 86 @Test testSwitchBasePrefixRangeWhenConflict()87 public void testSwitchBasePrefixRangeWhenConflict() throws Exception { 88 assumeTrue(isFeatureEnabled(TETHER_ENABLE_SELECT_ALL_PREFIX_RANGES, true)); 89 90 addressConflictTest(true); 91 } 92 93 @Test testSwitchPrefixRangeWhenConflict()94 public void testSwitchPrefixRangeWhenConflict() throws Exception { 95 addressConflictTest(false); 96 } 97 addressConflictTest(final boolean wholeRangeConflict)98 private void addressConflictTest(final boolean wholeRangeConflict) throws Exception { 99 final TestTetheringEventCallback tetherEventCallback = 100 mCtsTetheringUtils.registerTetheringEventCallback(); 101 102 TestNetworkTracker tnt = null; 103 try { 104 tetherEventCallback.assumeWifiTetheringSupported(mContext); 105 tetherEventCallback.expectNoTetheringActive(); 106 107 final TetheringInterface tetheredIface = 108 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 109 110 assertNotNull(tetheredIface); 111 final String wifiTetheringIface = tetheredIface.getInterface(); 112 113 NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface); 114 // Tethering downstream only have one ipv4 address. 115 final LinkAddress hotspotAddr = getFirstIpv4Address(nif); 116 assertNotNull(hotspotAddr); 117 118 final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict); 119 assertNotNull(testPrefix); 120 121 tnt = setUpTestNetwork( 122 new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength())); 123 124 tetherEventCallback.expectNoTetheringActive(); 125 final List<String> wifiRegexs = 126 tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs(); 127 128 tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI); 129 nif = NetworkInterface.getByName(wifiTetheringIface); 130 final LinkAddress newHotspotAddr = getFirstIpv4Address(nif); 131 assertNotNull(newHotspotAddr); 132 133 assertFalse(testPrefix.containsPrefix( 134 new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength()))); 135 136 mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); 137 } finally { 138 if (tnt != null) { 139 tnt.teardown(); 140 } 141 mTm.stopAllTethering(); 142 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 143 } 144 } 145 getFirstIpv4Address(final NetworkInterface nif)146 private LinkAddress getFirstIpv4Address(final NetworkInterface nif) { 147 for (InterfaceAddress ia : nif.getInterfaceAddresses()) { 148 final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength()); 149 if (addr.isIpv4()) return addr; 150 } 151 return null; 152 } 153 154 @NonNull getConflictingPrefix(final LinkAddress address, final boolean wholeRangeConflict)155 private IpPrefix getConflictingPrefix(final LinkAddress address, 156 final boolean wholeRangeConflict) { 157 if (!wholeRangeConflict) { 158 return new IpPrefix(address.getAddress(), address.getPrefixLength()); 159 } 160 161 final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList( 162 new IpPrefix("192.168.0.0/16"), 163 new IpPrefix("172.16.0.0/12"), 164 new IpPrefix("10.0.0.0/8"))); 165 166 for (IpPrefix prefix : prefixPool) { 167 if (prefix.contains(address.getAddress())) return prefix; 168 } 169 170 fail("Could not find sutiable conflict prefix"); 171 172 // Never go here. 173 return null; 174 } 175 setUpTestNetwork(final LinkAddress address)176 private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception { 177 return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/); 178 179 } 180 isFeatureEnabled(final String name, final boolean defaultValue)181 public static boolean isFeatureEnabled(final String name, final boolean defaultValue) { 182 return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue); 183 } 184 } 185