1 /* 2 * Copyright (C) 2019 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.test; 17 18 import static android.Manifest.permission.MODIFY_PHONE_STATE; 19 import static android.Manifest.permission.TETHER_PRIVILEGED; 20 import static android.Manifest.permission.WRITE_SETTINGS; 21 import static android.content.pm.PackageManager.FEATURE_TELEPHONY; 22 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN; 23 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; 24 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 25 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 26 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; 27 import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; 28 import static android.net.TetheringManager.TETHERING_BLUETOOTH; 29 import static android.net.TetheringManager.TETHERING_ETHERNET; 30 import static android.net.TetheringManager.TETHERING_NCM; 31 import static android.net.TetheringManager.TETHERING_USB; 32 import static android.net.TetheringManager.TETHERING_VIRTUAL; 33 import static android.net.TetheringManager.TETHERING_WIFI; 34 import static android.net.TetheringManager.TETHERING_WIFI_P2P; 35 import static android.net.TetheringManager.TETHER_ERROR_DUPLICATE_REQUEST; 36 import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; 37 import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; 38 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; 39 import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST; 40 import static android.net.cts.util.CtsTetheringUtils.isAnyIfaceMatch; 41 import static android.os.Process.INVALID_UID; 42 43 import static com.android.testutils.TestPermissionUtil.runAsShell; 44 45 import static org.junit.Assert.assertEquals; 46 import static org.junit.Assert.assertFalse; 47 import static org.junit.Assert.assertNotEquals; 48 import static org.junit.Assert.assertNotNull; 49 import static org.junit.Assert.assertNull; 50 import static org.junit.Assert.assertThrows; 51 import static org.junit.Assert.assertTrue; 52 import static org.junit.Assert.fail; 53 import static org.junit.Assume.assumeFalse; 54 import static org.junit.Assume.assumeTrue; 55 56 import android.content.BroadcastReceiver; 57 import android.content.Context; 58 import android.content.Intent; 59 import android.content.IntentFilter; 60 import android.content.pm.PackageManager; 61 import android.net.ConnectivityManager; 62 import android.net.LinkAddress; 63 import android.net.Network; 64 import android.net.NetworkCapabilities; 65 import android.net.TetheringInterface; 66 import android.net.TetheringManager; 67 import android.net.TetheringManager.OnTetheringEntitlementResultListener; 68 import android.net.TetheringManager.TetheringInterfaceRegexps; 69 import android.net.TetheringManager.TetheringRequest; 70 import android.net.cts.util.CtsNetUtils; 71 import android.net.cts.util.CtsNetUtils.TestNetworkCallback; 72 import android.net.cts.util.CtsTetheringUtils; 73 import android.net.cts.util.CtsTetheringUtils.StartTetheringCallback; 74 import android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback; 75 import android.net.wifi.SoftApConfiguration; 76 import android.net.wifi.WifiManager; 77 import android.net.wifi.WifiSsid; 78 import android.os.Bundle; 79 import android.os.PersistableBundle; 80 import android.os.ResultReceiver; 81 import android.telephony.CarrierConfigManager; 82 import android.telephony.SubscriptionManager; 83 import android.telephony.TelephonyManager; 84 85 import androidx.annotation.NonNull; 86 import androidx.test.InstrumentationRegistry; 87 import androidx.test.runner.AndroidJUnit4; 88 89 import com.android.modules.utils.build.SdkLevel; 90 import com.android.testutils.ParcelUtils; 91 import com.android.testutils.com.android.testutils.CarrierConfigRule; 92 93 import org.junit.After; 94 import org.junit.Before; 95 import org.junit.Rule; 96 import org.junit.Test; 97 import org.junit.runner.RunWith; 98 99 import java.nio.charset.StandardCharsets; 100 import java.util.ArrayList; 101 import java.util.Arrays; 102 import java.util.List; 103 import java.util.concurrent.CompletableFuture; 104 import java.util.concurrent.LinkedBlockingQueue; 105 import java.util.concurrent.TimeUnit; 106 import java.util.function.Consumer; 107 108 @RunWith(AndroidJUnit4.class) 109 public class TetheringManagerTest { 110 @Rule 111 public final CarrierConfigRule mCarrierConfigRule = new CarrierConfigRule(); 112 113 private Context mContext; 114 115 private ConnectivityManager mCm; 116 private TetheringManager mTM; 117 private WifiManager mWm; 118 private PackageManager mPm; 119 120 private TetherChangeReceiver mTetherChangeReceiver; 121 private CtsNetUtils mCtsNetUtils; 122 private CtsTetheringUtils mCtsTetheringUtils; 123 124 private static final int DEFAULT_TIMEOUT_MS = 60_000; 125 126 @Before setUp()127 public void setUp() throws Exception { 128 mContext = InstrumentationRegistry.getContext(); 129 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 130 mTM = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); 131 mWm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 132 mPm = mContext.getPackageManager(); 133 mCtsNetUtils = new CtsNetUtils(mContext); 134 mCtsTetheringUtils = new CtsTetheringUtils(mContext); 135 mTetherChangeReceiver = new TetherChangeReceiver(); 136 final IntentFilter filter = new IntentFilter( 137 TetheringManager.ACTION_TETHER_STATE_CHANGED); 138 final Intent intent = mContext.registerReceiver(mTetherChangeReceiver, filter); 139 if (intent != null) mTetherChangeReceiver.onReceive(null, intent); 140 } 141 142 @After tearDown()143 public void tearDown() throws Exception { 144 mCtsTetheringUtils.stopAllTethering(); 145 mContext.unregisterReceiver(mTetherChangeReceiver); 146 } 147 148 private class TetherChangeReceiver extends BroadcastReceiver { 149 private class TetherState { 150 final ArrayList<String> mAvailable; 151 final ArrayList<String> mActive; 152 final ArrayList<String> mErrored; 153 TetherState(Intent intent)154 TetherState(Intent intent) { 155 mAvailable = intent.getStringArrayListExtra( 156 TetheringManager.EXTRA_AVAILABLE_TETHER); 157 mActive = intent.getStringArrayListExtra( 158 TetheringManager.EXTRA_ACTIVE_TETHER); 159 mErrored = intent.getStringArrayListExtra( 160 TetheringManager.EXTRA_ERRORED_TETHER); 161 } 162 } 163 164 @Override onReceive(Context content, Intent intent)165 public void onReceive(Context content, Intent intent) { 166 String action = intent.getAction(); 167 if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) { 168 mResult.add(new TetherState(intent)); 169 } 170 } 171 172 public final LinkedBlockingQueue<TetherState> mResult = new LinkedBlockingQueue<>(); 173 174 // Expects that tethering reaches the desired state. 175 // - If active is true, expects that tethering is enabled on at least one interface 176 // matching ifaceRegexs. 177 // - If active is false, expects that tethering is disabled on all the interfaces matching 178 // ifaceRegexs. 179 // Fails if any interface matching ifaceRegexs becomes errored. expectTethering(final boolean active, final String[] ifaceRegexs)180 public void expectTethering(final boolean active, final String[] ifaceRegexs) { 181 while (true) { 182 final TetherState state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS, ifaceRegexs); 183 assertNotNull("Did not receive expected state change, active: " + active, state); 184 185 if (isIfaceActive(ifaceRegexs, state) == active) return; 186 } 187 } 188 pollAndAssertNoError(final int timeout, final String[] ifaceRegexs)189 private TetherState pollAndAssertNoError(final int timeout, final String[] ifaceRegexs) { 190 final TetherState state = pollTetherState(timeout); 191 assertNoErroredIfaces(state, ifaceRegexs); 192 return state; 193 } 194 pollTetherState(final int timeout)195 private TetherState pollTetherState(final int timeout) { 196 try { 197 return mResult.poll(timeout, TimeUnit.MILLISECONDS); 198 } catch (InterruptedException e) { 199 fail("No result after " + timeout + " ms"); 200 return null; 201 } 202 } 203 isIfaceActive(final String[] ifaceRegexs, final TetherState state)204 private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) { 205 return isAnyIfaceMatch(ifaceRegexs, state.mActive); 206 } 207 assertNoErroredIfaces(final TetherState state, final String[] ifaceRegexs)208 private void assertNoErroredIfaces(final TetherState state, final String[] ifaceRegexs) { 209 if (state == null || state.mErrored == null) return; 210 211 if (isAnyIfaceMatch(ifaceRegexs, state.mErrored)) { 212 fail("Found failed tethering interfaces: " + Arrays.toString(state.mErrored.toArray())); 213 } 214 } 215 } 216 217 @Test testStartTetheringWithStateChangeBroadcast()218 public void testStartTetheringWithStateChangeBroadcast() throws Exception { 219 final TestTetheringEventCallback tetherEventCallback = 220 mCtsTetheringUtils.registerTetheringEventCallback(); 221 try { 222 tetherEventCallback.assumeWifiTetheringSupported(mContext); 223 tetherEventCallback.expectNoTetheringActive(); 224 225 final String[] wifiRegexs = mTM.getTetherableWifiRegexs(); 226 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 227 228 mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs); 229 230 mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); 231 mTetherChangeReceiver.expectTethering(false /* active */, wifiRegexs); 232 } finally { 233 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 234 } 235 236 } 237 238 @Test testStartTetheringDuplicateRequestRejected()239 public void testStartTetheringDuplicateRequestRejected() throws Exception { 240 assumeTrue(SdkLevel.isAtLeastB()); 241 final TestTetheringEventCallback tetherEventCallback = 242 mCtsTetheringUtils.registerTetheringEventCallback(); 243 try { 244 tetherEventCallback.assumeWifiTetheringSupported(mContext); 245 tetherEventCallback.expectNoTetheringActive(); 246 247 final String[] wifiRegexs = mTM.getTetherableWifiRegexs(); 248 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 249 mTetherChangeReceiver.expectTethering(true /* active */, wifiRegexs); 250 251 final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); 252 runAsShell(TETHER_PRIVILEGED, () -> { 253 mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), 254 c -> c.run() /* executor */, startTetheringCallback); 255 startTetheringCallback.expectTetheringFailed(TETHER_ERROR_DUPLICATE_REQUEST); 256 }); 257 } finally { 258 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 259 } 260 } 261 createSoftApConfiguration(@onNull String ssid)262 private SoftApConfiguration createSoftApConfiguration(@NonNull String ssid) { 263 SoftApConfiguration config; 264 if (SdkLevel.isAtLeastT()) { 265 config = new SoftApConfiguration.Builder() 266 .setWifiSsid(WifiSsid.fromBytes(ssid.getBytes(StandardCharsets.UTF_8))) 267 .build(); 268 } else { 269 config = new SoftApConfiguration.Builder() 270 .setSsid(ssid) 271 .build(); 272 } 273 return config; 274 } 275 276 @Test testTetheringRequest()277 public void testTetheringRequest() { 278 SoftApConfiguration softApConfiguration = createSoftApConfiguration("SSID"); 279 final TetheringRequest tr = new TetheringRequest.Builder(TETHERING_WIFI) 280 .setSoftApConfiguration(softApConfiguration) 281 .build(); 282 assertEquals(TETHERING_WIFI, tr.getTetheringType()); 283 assertNull(tr.getLocalIpv4Address()); 284 assertNull(tr.getClientStaticIpv4Address()); 285 assertFalse(tr.isExemptFromEntitlementCheck()); 286 assertTrue(tr.getShouldShowEntitlementUi()); 287 assertEquals(CONNECTIVITY_SCOPE_GLOBAL, tr.getConnectivityScope()); 288 assertEquals(softApConfiguration, tr.getSoftApConfiguration()); 289 assertEquals(INVALID_UID, tr.getUid()); 290 assertNull(tr.getPackageName()); 291 assertEquals(tr.toString(), "TetheringRequest[ " 292 + "TETHERING_WIFI, " 293 + "showProvisioningUi, " 294 + "CONNECTIVITY_SCOPE_GLOBAL, " 295 + "softApConfig=" + softApConfiguration.toString() 296 + " ]"); 297 298 final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); 299 final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); 300 final TetheringRequest tr2 = new TetheringRequest.Builder(TETHERING_USB) 301 .setStaticIpv4Addresses(localAddr, clientAddr) 302 .setExemptFromEntitlementCheck(true) 303 .setShouldShowEntitlementUi(false) 304 .setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL) 305 .build(); 306 int uid = 1000; 307 String packageName = "package"; 308 tr2.setUid(uid); 309 tr2.setPackageName(packageName); 310 311 assertEquals(localAddr, tr2.getLocalIpv4Address()); 312 assertEquals(clientAddr, tr2.getClientStaticIpv4Address()); 313 assertEquals(TETHERING_USB, tr2.getTetheringType()); 314 assertTrue(tr2.isExemptFromEntitlementCheck()); 315 assertFalse(tr2.getShouldShowEntitlementUi()); 316 assertEquals(CONNECTIVITY_SCOPE_LOCAL, tr2.getConnectivityScope()); 317 assertNull(tr2.getSoftApConfiguration()); 318 assertEquals(uid, tr2.getUid()); 319 assertEquals(packageName, tr2.getPackageName()); 320 assertEquals(tr2.toString(), "TetheringRequest[ " 321 + "TETHERING_USB, " 322 + "localIpv4Address=" + localAddr + ", " 323 + "staticClientAddress=" + clientAddr + ", " 324 + "exemptFromEntitlementCheck, " 325 + "CONNECTIVITY_SCOPE_LOCAL, " 326 + "uid=1000, " 327 + "packageName=package" 328 + " ]"); 329 330 final TetheringRequest tr3 = new TetheringRequest.Builder(TETHERING_USB) 331 .setStaticIpv4Addresses(localAddr, clientAddr) 332 .setExemptFromEntitlementCheck(true) 333 .setShouldShowEntitlementUi(false) 334 .setConnectivityScope(CONNECTIVITY_SCOPE_LOCAL) 335 .build(); 336 tr3.setUid(uid); 337 tr3.setPackageName(packageName); 338 assertEquals(tr2, tr3); 339 340 final String interfaceName = "test_iface"; 341 final TetheringRequest tr4 = new TetheringRequest.Builder(TETHERING_VIRTUAL) 342 .setInterfaceName(interfaceName) 343 .setConnectivityScope(CONNECTIVITY_SCOPE_GLOBAL).build(); 344 assertEquals(interfaceName, tr4.getInterfaceName()); 345 assertEquals(CONNECTIVITY_SCOPE_GLOBAL, tr4.getConnectivityScope()); 346 } 347 348 @Test testTetheringRequestSetSoftApConfigurationFailsWhenNotWifi()349 public void testTetheringRequestSetSoftApConfigurationFailsWhenNotWifi() { 350 final SoftApConfiguration softApConfiguration = createSoftApConfiguration("SSID"); 351 for (int type : List.of(TETHERING_USB, TETHERING_BLUETOOTH, TETHERING_WIFI_P2P, 352 TETHERING_NCM, TETHERING_ETHERNET)) { 353 try { 354 new TetheringRequest.Builder(type).setSoftApConfiguration(softApConfiguration); 355 fail("Was able to set SoftApConfiguration for tethering type " + type); 356 } catch (IllegalArgumentException e) { 357 // Success 358 } 359 } 360 } 361 362 @Test testTetheringRequestSetInterfaceNameFailsExceptTetheringVirtual()363 public void testTetheringRequestSetInterfaceNameFailsExceptTetheringVirtual() { 364 for (int type : List.of(TETHERING_USB, TETHERING_BLUETOOTH, TETHERING_NCM, 365 TETHERING_ETHERNET)) { 366 try { 367 new TetheringRequest.Builder(type).setInterfaceName("test_iface"); 368 fail("Was able to set interface name for tethering type " + type); 369 } catch (IllegalArgumentException e) { 370 // Success 371 } 372 } 373 } 374 375 @Test testTetheringRequestParcelable()376 public void testTetheringRequestParcelable() { 377 final SoftApConfiguration softApConfiguration = createSoftApConfiguration("SSID"); 378 final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); 379 final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); 380 final TetheringRequest withApConfig = new TetheringRequest.Builder(TETHERING_WIFI) 381 .setSoftApConfiguration(softApConfiguration) 382 .setStaticIpv4Addresses(localAddr, clientAddr) 383 .setExemptFromEntitlementCheck(true) 384 .setShouldShowEntitlementUi(false).build(); 385 final TetheringRequest withoutApConfig = new TetheringRequest.Builder(TETHERING_WIFI) 386 .setStaticIpv4Addresses(localAddr, clientAddr) 387 .setExemptFromEntitlementCheck(true) 388 .setShouldShowEntitlementUi(false).build(); 389 assertEquals(withApConfig, ParcelUtils.parcelingRoundTrip(withApConfig)); 390 assertEquals(withoutApConfig, ParcelUtils.parcelingRoundTrip(withoutApConfig)); 391 assertNotEquals(withApConfig, ParcelUtils.parcelingRoundTrip(withoutApConfig)); 392 assertNotEquals(withoutApConfig, ParcelUtils.parcelingRoundTrip(withApConfig)); 393 394 final TetheringRequest withIfaceName = new TetheringRequest.Builder(TETHERING_VIRTUAL) 395 .setInterfaceName("test_iface").build(); 396 assertEquals(withIfaceName, ParcelUtils.parcelingRoundTrip(withIfaceName)); 397 } 398 399 @Test testRegisterTetheringEventCallback()400 public void testRegisterTetheringEventCallback() throws Exception { 401 final TestTetheringEventCallback tetherEventCallback = 402 mCtsTetheringUtils.registerTetheringEventCallback(); 403 404 try { 405 tetherEventCallback.assumeWifiTetheringSupported(mContext); 406 tetherEventCallback.expectNoTetheringActive(); 407 408 SoftApConfiguration softApConfig = SdkLevel.isAtLeastB() 409 ? createSoftApConfiguration("SSID") : null; 410 final TetheringInterface tetheredIface = 411 mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig); 412 413 assertNotNull(tetheredIface); 414 if (SdkLevel.isAtLeastB()) { 415 assertEquals(softApConfig, tetheredIface.getSoftApConfiguration()); 416 } 417 418 mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); 419 420 if (!SdkLevel.isAtLeastB()) { 421 final String wifiTetheringIface = tetheredIface.getInterface(); 422 try { 423 final int ret = runAsShell(TETHER_PRIVILEGED, 424 () -> mTM.tether(wifiTetheringIface)); 425 // There is no guarantee that the wifi interface will be available after 426 // disabling the hotspot, so don't fail the test if the call to tether() fails. 427 if (ret == TETHER_ERROR_NO_ERROR) { 428 // If calling #tether successful, there is a callback to tell the result of 429 // tethering setup. 430 tetherEventCallback.expectErrorOrTethered( 431 new TetheringInterface(TETHERING_WIFI, wifiTetheringIface)); 432 } 433 } finally { 434 runAsShell(TETHER_PRIVILEGED, () -> mTM.untether(wifiTetheringIface)); 435 } 436 } 437 } finally { 438 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 439 } 440 } 441 442 @Test testGetTetherableInterfaceRegexps()443 public void testGetTetherableInterfaceRegexps() { 444 final TestTetheringEventCallback tetherEventCallback = 445 mCtsTetheringUtils.registerTetheringEventCallback(); 446 tetherEventCallback.assumeTetheringSupported(); 447 448 final TetheringInterfaceRegexps tetherableRegexs = 449 tetherEventCallback.getTetheringInterfaceRegexps(); 450 final List<String> wifiRegexs = tetherableRegexs.getTetherableWifiRegexs(); 451 final List<String> usbRegexs = tetherableRegexs.getTetherableUsbRegexs(); 452 final List<String> btRegexs = tetherableRegexs.getTetherableBluetoothRegexs(); 453 454 assertEquals(wifiRegexs, Arrays.asList(mTM.getTetherableWifiRegexs())); 455 assertEquals(usbRegexs, Arrays.asList(mTM.getTetherableUsbRegexs())); 456 assertEquals(btRegexs, Arrays.asList(mTM.getTetherableBluetoothRegexs())); 457 458 //Verify that any regex name should only contain in one array. 459 wifiRegexs.forEach(s -> assertFalse(usbRegexs.contains(s))); 460 wifiRegexs.forEach(s -> assertFalse(btRegexs.contains(s))); 461 usbRegexs.forEach(s -> assertFalse(btRegexs.contains(s))); 462 463 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 464 } 465 466 @Test testStopAllTethering()467 public void testStopAllTethering() throws Exception { 468 final TestTetheringEventCallback tetherEventCallback = 469 mCtsTetheringUtils.registerTetheringEventCallback(); 470 try { 471 tetherEventCallback.assumeWifiTetheringSupported(mContext); 472 473 // TODO: start ethernet tethering here when TetheringManagerTest is moved to 474 // TetheringIntegrationTest. 475 476 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 477 478 mCtsTetheringUtils.stopAllTethering(); 479 tetherEventCallback.expectNoTetheringActive(); 480 } finally { 481 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 482 } 483 } 484 485 @Test testStopTetheringRequestNoMatchFailure()486 public void testStopTetheringRequestNoMatchFailure() throws Exception { 487 assumeTrue(SdkLevel.isAtLeastB()); 488 final TestTetheringEventCallback tetherEventCallback = 489 mCtsTetheringUtils.registerTetheringEventCallback(); 490 try { 491 tetherEventCallback.assumeWifiTetheringSupported(mContext); 492 tetherEventCallback.expectNoTetheringActive(); 493 494 final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); 495 mTM.startTethering(new TetheringRequest.Builder(TETHERING_VIRTUAL).build(), 496 c -> c.run(), startTetheringCallback); 497 498 // Stopping a non-matching request should have no effect 499 TetheringRequest nonMatchingRequest = new TetheringRequest.Builder(TETHERING_VIRTUAL) 500 .setInterfaceName("iface") 501 .build(); 502 mCtsTetheringUtils.stopTethering(nonMatchingRequest, false /* success */); 503 } finally { 504 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 505 } 506 } 507 508 @Test testStopTetheringRequestMatchSuccess()509 public void testStopTetheringRequestMatchSuccess() throws Exception { 510 assumeTrue(SdkLevel.isAtLeastB()); 511 final TestTetheringEventCallback tetherEventCallback = 512 mCtsTetheringUtils.registerTetheringEventCallback(); 513 try { 514 tetherEventCallback.assumeWifiTetheringSupported(mContext); 515 tetherEventCallback.expectNoTetheringActive(); 516 517 SoftApConfiguration softApConfig = new SoftApConfiguration.Builder() 518 .setWifiSsid(WifiSsid.fromBytes("This is one config" 519 .getBytes(StandardCharsets.UTF_8))).build(); 520 mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig); 521 522 // Stopping the active request should stop tethering. 523 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) 524 .setSoftApConfiguration(softApConfig) 525 .build(); 526 mCtsTetheringUtils.stopTethering(request, true /* success */); 527 tetherEventCallback.expectNoTetheringActive(); 528 } finally { 529 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 530 } 531 } 532 533 @Test testStopTetheringRequestFuzzyMatchSuccess()534 public void testStopTetheringRequestFuzzyMatchSuccess() throws Exception { 535 assumeTrue(SdkLevel.isAtLeastB()); 536 final TestTetheringEventCallback tetherEventCallback = 537 mCtsTetheringUtils.registerTetheringEventCallback(); 538 try { 539 tetherEventCallback.assumeWifiTetheringSupported(mContext); 540 tetherEventCallback.expectNoTetheringActive(); 541 542 SoftApConfiguration softApConfig = new SoftApConfiguration.Builder() 543 .setWifiSsid(WifiSsid.fromBytes("This is one config" 544 .getBytes(StandardCharsets.UTF_8))).build(); 545 mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig); 546 547 // Stopping with a fuzzy matching request should stop tethering. 548 final LinkAddress localAddr = new LinkAddress("192.168.24.5/24"); 549 final LinkAddress clientAddr = new LinkAddress("192.168.24.100/24"); 550 TetheringRequest fuzzyMatchingRequest = new TetheringRequest.Builder(TETHERING_WIFI) 551 .setSoftApConfiguration(softApConfig) 552 .setShouldShowEntitlementUi(true) 553 .setStaticIpv4Addresses(localAddr, clientAddr) 554 .build(); 555 mCtsTetheringUtils.stopTethering(fuzzyMatchingRequest, true /* success */); 556 tetherEventCallback.expectNoTetheringActive(); 557 } finally { 558 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 559 } 560 } 561 562 @Test testStartTetheringNoPermission()563 public void testStartTetheringNoPermission() throws Exception { 564 final StartTetheringCallback startTetheringCallback = new StartTetheringCallback(); 565 566 // No permission 567 mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), 568 c -> c.run() /* executor */, startTetheringCallback); 569 startTetheringCallback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 570 571 // WRITE_SETTINGS not sufficient 572 if (SdkLevel.isAtLeastB()) { 573 runAsShell(WRITE_SETTINGS, () -> { 574 mTM.startTethering(new TetheringRequest.Builder(TETHERING_WIFI).build(), 575 c -> c.run() /* executor */, startTetheringCallback); 576 startTetheringCallback.expectTetheringFailed( 577 TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 578 }); 579 } 580 } 581 582 private class EntitlementResultListener implements OnTetheringEntitlementResultListener { 583 private final CompletableFuture<Integer> future = new CompletableFuture<>(); 584 585 @Override onTetheringEntitlementResult(int result)586 public void onTetheringEntitlementResult(int result) { 587 future.complete(result); 588 } 589 get(long timeout, TimeUnit unit)590 public int get(long timeout, TimeUnit unit) throws Exception { 591 return future.get(timeout, unit); 592 } 593 594 } 595 assertEntitlementResult(final Consumer<EntitlementResultListener> functor, final int expect)596 private void assertEntitlementResult(final Consumer<EntitlementResultListener> functor, 597 final int expect) throws Exception { 598 runAsShell(TETHER_PRIVILEGED, () -> { 599 final EntitlementResultListener listener = new EntitlementResultListener(); 600 functor.accept(listener); 601 602 assertEquals(expect, listener.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); 603 }); 604 } 605 isTetheringSupported()606 private boolean isTetheringSupported() { 607 return runAsShell(TETHER_PRIVILEGED, () -> mTM.isTetheringSupported()); 608 } 609 610 @Test testRequestLatestEntitlementResult()611 public void testRequestLatestEntitlementResult() throws Exception { 612 assumeTrue(isTetheringSupported()); 613 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 614 // Verify that requestLatestTetheringEntitlementResult() can get entitlement 615 // result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via listener. 616 assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( 617 TETHERING_WIFI_P2P, false, c -> c.run(), listener), 618 TETHER_ERROR_ENTITLEMENT_UNKNOWN); 619 620 // Verify that requestLatestTetheringEntitlementResult() can get entitlement 621 // result(TETHER_ERROR_ENTITLEMENT_UNKNOWN due to invalid downstream type) via receiver. 622 assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( 623 TETHERING_WIFI_P2P, 624 new ResultReceiver(null /* handler */) { 625 @Override 626 public void onReceiveResult(int resultCode, Bundle resultData) { 627 listener.onTetheringEntitlementResult(resultCode); 628 } 629 }, false), 630 TETHER_ERROR_ENTITLEMENT_UNKNOWN); 631 632 // Do not request TETHERING_WIFI entitlement result if TETHERING_WIFI is not available. 633 assumeTrue(mTM.getTetherableWifiRegexs().length > 0); 634 635 // Verify that null listener will cause IllegalArgumentException. 636 try { 637 mTM.requestLatestTetheringEntitlementResult( 638 TETHERING_WIFI, false, c -> c.run(), null); 639 } catch (IllegalArgumentException expect) { } 640 641 // Override carrier config to ignore entitlement check. 642 final PersistableBundle bundle = new PersistableBundle(); 643 bundle.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, false); 644 mCarrierConfigRule.addConfigOverrides( 645 SubscriptionManager.getDefaultSubscriptionId(), bundle); 646 647 // Verify that requestLatestTetheringEntitlementResult() can get entitlement 648 // result TETHER_ERROR_NO_ERROR due to provisioning bypassed. 649 assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult( 650 TETHERING_WIFI, false, c -> c.run(), listener), TETHER_ERROR_NO_ERROR); 651 } 652 isTetheringApnRequired()653 private boolean isTetheringApnRequired() { 654 final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); 655 return runAsShell(MODIFY_PHONE_STATE, () -> tm.isTetheringApnRequired()); 656 657 } 658 659 @Test testTetheringUpstream()660 public void testTetheringUpstream() throws Exception { 661 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 662 final TestTetheringEventCallback tetherEventCallback = 663 mCtsTetheringUtils.registerTetheringEventCallback(); 664 665 boolean previousWifiEnabledState = false; 666 667 try { 668 tetherEventCallback.assumeWifiTetheringSupported(mContext); 669 tetherEventCallback.expectNoTetheringActive(); 670 671 previousWifiEnabledState = mWm.isWifiEnabled(); 672 if (previousWifiEnabledState) { 673 mCtsNetUtils.ensureWifiDisconnected(null); 674 } 675 676 final TestNetworkCallback networkCallback = new TestNetworkCallback(); 677 Network activeNetwork = null; 678 try { 679 mCm.registerDefaultNetworkCallback(networkCallback); 680 activeNetwork = networkCallback.waitForAvailable(); 681 } finally { 682 mCm.unregisterNetworkCallback(networkCallback); 683 } 684 685 assertNotNull("No active network. Please ensure the device has working mobile data.", 686 activeNetwork); 687 final NetworkCapabilities activeNetCap = mCm.getNetworkCapabilities(activeNetwork); 688 689 // If active nework is ETHERNET, tethering may not use cell network as upstream. 690 assumeFalse(activeNetCap.hasTransport(TRANSPORT_ETHERNET)); 691 692 assertTrue(activeNetCap.hasTransport(TRANSPORT_CELLULAR)); 693 694 mCtsTetheringUtils.startWifiTethering(tetherEventCallback); 695 696 final int expectedCap = isTetheringApnRequired() 697 ? NET_CAPABILITY_DUN : NET_CAPABILITY_INTERNET; 698 final Network network = tetherEventCallback.getCurrentValidUpstream(); 699 final NetworkCapabilities netCap = mCm.getNetworkCapabilities(network); 700 assertTrue(netCap.hasTransport(TRANSPORT_CELLULAR)); 701 assertTrue(netCap.hasCapability(expectedCap)); 702 703 mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); 704 } finally { 705 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 706 if (previousWifiEnabledState) { 707 mCtsNetUtils.connectToWifi(); 708 } 709 } 710 } 711 712 @Test testLegacyTetherApisThrowUnsupportedOperationExceptionAfterV()713 public void testLegacyTetherApisThrowUnsupportedOperationExceptionAfterV() { 714 assumeTrue(SdkLevel.isAtLeastB()); 715 assertThrows(UnsupportedOperationException.class, () -> mTM.tether("iface")); 716 assertThrows(UnsupportedOperationException.class, () -> mTM.untether("iface")); 717 } 718 719 @Test testCarrierPrivilegedIsTetheringSupported()720 public void testCarrierPrivilegedIsTetheringSupported() throws Exception { 721 assumeTrue(SdkLevel.isAtLeastB()); 722 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 723 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 724 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 725 final TestTetheringEventCallback tetherEventCallback = 726 mCtsTetheringUtils.registerTetheringEventCallback(); 727 try { 728 tetherEventCallback.assumeWifiTetheringSupported(mContext); 729 tetherEventCallback.expectNoTetheringActive(); 730 731 assertTrue(mTM.isTetheringSupported()); 732 } finally { 733 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 734 } 735 } 736 737 @Test testCarrierPrivilegedStartTetheringNonWifiFails()738 public void testCarrierPrivilegedStartTetheringNonWifiFails() throws Exception { 739 assumeTrue(SdkLevel.isAtLeastB()); 740 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 741 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 742 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 743 final TestTetheringEventCallback tetherEventCallback = 744 mCtsTetheringUtils.registerTetheringEventCallback(); 745 try { 746 tetherEventCallback.assumeWifiTetheringSupported(mContext); 747 tetherEventCallback.expectNoTetheringActive(); 748 StartTetheringCallback callback = new StartTetheringCallback(); 749 TetheringRequest request = new TetheringRequest.Builder(TETHERING_USB).build(); 750 751 mTM.startTethering(request, Runnable::run, callback); 752 753 callback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 754 } finally { 755 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 756 } 757 } 758 759 @Test testCarrierPrivilegedStartTetheringWifiWithoutConfigFails()760 public void testCarrierPrivilegedStartTetheringWifiWithoutConfigFails() throws Exception { 761 assumeTrue(SdkLevel.isAtLeastB()); 762 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 763 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 764 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 765 final TestTetheringEventCallback tetherEventCallback = 766 mCtsTetheringUtils.registerTetheringEventCallback(); 767 try { 768 tetherEventCallback.assumeWifiTetheringSupported(mContext); 769 tetherEventCallback.expectNoTetheringActive(); 770 StartTetheringCallback callback = new StartTetheringCallback(); 771 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build(); 772 773 mTM.startTethering(request, Runnable::run, callback); 774 775 callback.expectTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 776 } finally { 777 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 778 } 779 } 780 781 @Test testCarrierPrivilegedStartTetheringWifiWithConfigSucceeds()782 public void testCarrierPrivilegedStartTetheringWifiWithConfigSucceeds() throws Exception { 783 assumeTrue(SdkLevel.isAtLeastB()); 784 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 785 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 786 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 787 final TestTetheringEventCallback tetherEventCallback = 788 mCtsTetheringUtils.registerTetheringEventCallback(); 789 try { 790 tetherEventCallback.assumeWifiTetheringSupported(mContext); 791 tetherEventCallback.expectNoTetheringActive(); 792 SoftApConfiguration softApConfig = createSoftApConfiguration("Carrier-privileged"); 793 794 mCtsTetheringUtils.startWifiTetheringNoPermissions(tetherEventCallback, softApConfig); 795 } finally { 796 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 797 } 798 } 799 800 @Test testCarrierPrivilegedStopTetheringNonWifiFails()801 public void testCarrierPrivilegedStopTetheringNonWifiFails() throws Exception { 802 assumeTrue(SdkLevel.isAtLeastB()); 803 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 804 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 805 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 806 final TestTetheringEventCallback tetherEventCallback = 807 mCtsTetheringUtils.registerTetheringEventCallback(); 808 try { 809 tetherEventCallback.assumeWifiTetheringSupported(mContext); 810 tetherEventCallback.expectNoTetheringActive(); 811 TetheringRequest request = new TetheringRequest.Builder(TETHERING_USB).build(); 812 CtsTetheringUtils.StopTetheringCallback 813 callback = new CtsTetheringUtils.StopTetheringCallback(); 814 815 mTM.stopTethering(request, Runnable::run, callback); 816 817 callback.expectStopTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 818 } finally { 819 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 820 } 821 } 822 823 @Test testCarrierPrivilegedStopTetheringWifiWithoutConfigFails()824 public void testCarrierPrivilegedStopTetheringWifiWithoutConfigFails() throws Exception { 825 assumeTrue(SdkLevel.isAtLeastB()); 826 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 827 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 828 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 829 final TestTetheringEventCallback tetherEventCallback = 830 mCtsTetheringUtils.registerTetheringEventCallback(); 831 try { 832 tetherEventCallback.assumeWifiTetheringSupported(mContext); 833 tetherEventCallback.expectNoTetheringActive(); 834 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI).build(); 835 CtsTetheringUtils.StopTetheringCallback 836 callback = new CtsTetheringUtils.StopTetheringCallback(); 837 838 mTM.stopTethering(request, Runnable::run, callback); 839 840 callback.expectStopTetheringFailed(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION); 841 } finally { 842 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 843 } 844 } 845 846 @Test testCarrierPrivilegedStopTetheringWifiWithConfigButNoActiveRequestFails()847 public void testCarrierPrivilegedStopTetheringWifiWithConfigButNoActiveRequestFails() 848 throws Exception { 849 assumeTrue(SdkLevel.isAtLeastB()); 850 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 851 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 852 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 853 final TestTetheringEventCallback tetherEventCallback = 854 mCtsTetheringUtils.registerTetheringEventCallback(); 855 try { 856 tetherEventCallback.assumeWifiTetheringSupported(mContext); 857 tetherEventCallback.expectNoTetheringActive(); 858 SoftApConfiguration softApConfig = createSoftApConfiguration("Carrier-privileged"); 859 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) 860 .setSoftApConfiguration(softApConfig) 861 .build(); 862 CtsTetheringUtils.StopTetheringCallback 863 callback = new CtsTetheringUtils.StopTetheringCallback(); 864 865 mTM.stopTethering(request, Runnable::run, callback); 866 867 callback.expectStopTetheringFailed(TETHER_ERROR_UNKNOWN_REQUEST); 868 } finally { 869 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 870 } 871 } 872 873 @Test testCarrierPrivilegedStopTetheringWifiWithConfigSucceeds()874 public void testCarrierPrivilegedStopTetheringWifiWithConfigSucceeds() throws Exception { 875 assumeTrue(SdkLevel.isAtLeastB()); 876 assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY)); 877 int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); 878 mCarrierConfigRule.acquireCarrierPrivilege(defaultSubId); 879 final TestTetheringEventCallback tetherEventCallback = 880 mCtsTetheringUtils.registerTetheringEventCallback(); 881 try { 882 tetherEventCallback.assumeWifiTetheringSupported(mContext); 883 tetherEventCallback.expectNoTetheringActive(); 884 SoftApConfiguration softApConfig = createSoftApConfiguration("Carrier-privileged"); 885 mCtsTetheringUtils.startWifiTetheringNoPermissions(tetherEventCallback, softApConfig); 886 TetheringRequest request = new TetheringRequest.Builder(TETHERING_WIFI) 887 .setSoftApConfiguration(softApConfig) 888 .build(); 889 CtsTetheringUtils.StopTetheringCallback 890 callback = new CtsTetheringUtils.StopTetheringCallback(); 891 892 mTM.stopTethering(request, Runnable::run, callback); 893 894 callback.verifyStopTetheringSucceeded(); 895 } finally { 896 mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback); 897 } 898 } 899 } 900