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