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 33 import android.app.UiAutomation; 34 import android.content.Context; 35 import android.net.IpPrefix; 36 import android.net.LinkAddress; 37 import android.net.TetheringInterface; 38 import android.net.TetheringManager; 39 import android.net.cts.util.CtsTetheringUtils; 40 import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; 41 import android.provider.DeviceConfig; 42 43 import androidx.annotation.NonNull; 44 import androidx.test.InstrumentationRegistry; 45 import androidx.test.runner.AndroidJUnit4; 46 47 import com.android.testutils.TestNetworkTracker; 48 49 import org.junit.After; 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 import java.net.InterfaceAddress; 55 import java.net.NetworkInterface; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.List; 59 60 @RunWith(AndroidJUnit4.class) 61 public class TetheringModuleTest { 62 private Context mContext; 63 private TetheringManager mTm; 64 private CtsTetheringUtils mCtsTetheringUtils; 65 66 private UiAutomation mUiAutomation = 67 InstrumentationRegistry.getInstrumentation().getUiAutomation(); 68 69 @Before setUp()70 public void setUp() throws Exception { 71 mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS, 72 WRITE_SETTINGS, READ_DEVICE_CONFIG, TETHER_PRIVILEGED, ACCESS_WIFI_STATE); 73 mContext = InstrumentationRegistry.getContext(); 74 mTm = mContext.getSystemService(TetheringManager.class); 75 mCtsTetheringUtils = new CtsTetheringUtils(mContext); 76 } 77 78 @After tearDown()79 public void tearDown() throws Exception { 80 mUiAutomation.dropShellPermissionIdentity(); 81 } 82 83 @Test testSwitchBasePrefixRangeWhenConflict()84 public void testSwitchBasePrefixRangeWhenConflict() throws Exception { 85 addressConflictTest(true); 86 } 87 88 @Test testSwitchPrefixRangeWhenConflict()89 public void testSwitchPrefixRangeWhenConflict() throws Exception { 90 addressConflictTest(false); 91 } 92 addressConflictTest(final boolean wholeRangeConflict)93 private void addressConflictTest(final boolean wholeRangeConflict) throws Exception { 94 final TestTetheringEventCallback tetherEventCallback = 95 mCtsTetheringUtils.registerTetheringEventCallback(); 96 97 TestNetworkTracker tnt = null; 98 try { 99 tetherEventCallback.assumeWifiTetheringSupported(mContext); 100 tetherEventCallback.expectNoTetheringActive(); 101 102 final TetheringInterface tetheredIface = 103 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 104 105 assertNotNull(tetheredIface); 106 final String wifiTetheringIface = tetheredIface.getInterface(); 107 108 NetworkInterface nif = NetworkInterface.getByName(wifiTetheringIface); 109 // Tethering downstream only have one ipv4 address. 110 final LinkAddress hotspotAddr = getFirstIpv4Address(nif); 111 assertNotNull(hotspotAddr); 112 113 final IpPrefix testPrefix = getConflictingPrefix(hotspotAddr, wholeRangeConflict); 114 assertNotNull(testPrefix); 115 116 tnt = setUpTestNetwork( 117 new LinkAddress(testPrefix.getAddress(), testPrefix.getPrefixLength())); 118 119 tetherEventCallback.expectNoTetheringActive(); 120 final List<String> wifiRegexs = 121 tetherEventCallback.getTetheringInterfaceRegexps().getTetherableWifiRegexs(); 122 123 tetherEventCallback.expectTetheredInterfacesChanged(wifiRegexs, TETHERING_WIFI); 124 nif = NetworkInterface.getByName(wifiTetheringIface); 125 final LinkAddress newHotspotAddr = getFirstIpv4Address(nif); 126 assertNotNull(newHotspotAddr); 127 128 assertFalse(testPrefix.containsPrefix( 129 new IpPrefix(newHotspotAddr.getAddress(), newHotspotAddr.getPrefixLength()))); 130 131 mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); 132 } finally { 133 if (tnt != null) { 134 tnt.teardown(); 135 } 136 mTm.stopAllTethering(); 137 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 138 } 139 } 140 getFirstIpv4Address(final NetworkInterface nif)141 private LinkAddress getFirstIpv4Address(final NetworkInterface nif) { 142 for (InterfaceAddress ia : nif.getInterfaceAddresses()) { 143 final LinkAddress addr = new LinkAddress(ia.getAddress(), ia.getNetworkPrefixLength()); 144 if (addr.isIpv4()) return addr; 145 } 146 return null; 147 } 148 149 @NonNull getConflictingPrefix(final LinkAddress address, final boolean wholeRangeConflict)150 private IpPrefix getConflictingPrefix(final LinkAddress address, 151 final boolean wholeRangeConflict) { 152 if (!wholeRangeConflict) { 153 return new IpPrefix(address.getAddress(), address.getPrefixLength()); 154 } 155 156 final ArrayList<IpPrefix> prefixPool = new ArrayList<>(Arrays.asList( 157 new IpPrefix("192.168.0.0/16"), 158 new IpPrefix("172.16.0.0/12"), 159 new IpPrefix("10.0.0.0/8"))); 160 161 for (IpPrefix prefix : prefixPool) { 162 if (prefix.contains(address.getAddress())) return prefix; 163 } 164 165 fail("Could not find sutiable conflict prefix"); 166 167 // Never go here. 168 return null; 169 } 170 setUpTestNetwork(final LinkAddress address)171 private TestNetworkTracker setUpTestNetwork(final LinkAddress address) throws Exception { 172 return initTestNetwork(mContext, address, 10_000L /* test timeout ms*/); 173 174 } 175 isFeatureEnabled(final String name, final boolean defaultValue)176 public static boolean isFeatureEnabled(final String name, final boolean defaultValue) { 177 return DeviceConfig.getBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue); 178 } 179 } 180