1 /* 2 * Copyright (C) 2016 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 17 package com.android.server.connectivity; 18 19 import static android.hardware.usb.UsbManager.USB_CONFIGURED; 20 import static android.hardware.usb.UsbManager.USB_CONNECTED; 21 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; 22 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; 23 import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY; 24 import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER; 25 import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER; 26 import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 27 import static android.net.ConnectivityManager.TETHERING_WIFI; 28 import static android.net.ConnectivityManager.TETHERING_USB; 29 import static android.net.ConnectivityManager.TYPE_MOBILE; 30 import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY; 31 import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED; 32 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; 33 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; 34 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; 35 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 36 37 import static org.junit.Assert.assertEquals; 38 import static org.junit.Assert.assertTrue; 39 import static org.mockito.ArgumentMatchers.argThat; 40 import static org.mockito.ArgumentMatchers.notNull; 41 import static org.mockito.Matchers.anyBoolean; 42 import static org.mockito.Matchers.anyInt; 43 import static org.mockito.Matchers.anyString; 44 import static org.mockito.Matchers.eq; 45 import static org.mockito.Mockito.any; 46 import static org.mockito.Mockito.atLeastOnce; 47 import static org.mockito.Mockito.doThrow; 48 import static org.mockito.Mockito.never; 49 import static org.mockito.Mockito.times; 50 import static org.mockito.Mockito.verify; 51 import static org.mockito.Mockito.verifyNoMoreInteractions; 52 import static org.mockito.Mockito.when; 53 import static org.mockito.Mockito.mock; 54 55 import android.content.BroadcastReceiver; 56 import android.content.ContentResolver; 57 import android.content.Context; 58 import android.content.Intent; 59 import android.content.IntentFilter; 60 import android.content.pm.ApplicationInfo; 61 import android.content.res.Resources; 62 import android.hardware.usb.UsbManager; 63 import android.net.INetd; 64 import android.net.INetworkPolicyManager; 65 import android.net.INetworkStatsService; 66 import android.net.InterfaceConfiguration; 67 import android.net.IpPrefix; 68 import android.net.LinkAddress; 69 import android.net.LinkProperties; 70 import android.net.MacAddress; 71 import android.net.Network; 72 import android.net.NetworkCapabilities; 73 import android.net.NetworkInfo; 74 import android.net.NetworkState; 75 import android.net.NetworkUtils; 76 import android.net.RouteInfo; 77 import android.net.ip.RouterAdvertisementDaemon; 78 import android.net.util.InterfaceParams; 79 import android.net.util.NetworkConstants; 80 import android.net.util.SharedLog; 81 import android.net.wifi.WifiConfiguration; 82 import android.net.wifi.WifiManager; 83 import android.os.Bundle; 84 import android.os.Handler; 85 import android.os.INetworkManagementService; 86 import android.os.PersistableBundle; 87 import android.os.RemoteException; 88 import android.os.test.TestLooper; 89 import android.os.UserHandle; 90 import android.os.UserManager; 91 import android.provider.Settings; 92 import android.support.test.filters.SmallTest; 93 import android.support.test.runner.AndroidJUnit4; 94 import android.telephony.CarrierConfigManager; 95 import android.test.mock.MockContentResolver; 96 97 import com.android.internal.util.ArrayUtils; 98 import com.android.internal.util.StateMachine; 99 import com.android.internal.util.test.BroadcastInterceptingContext; 100 import com.android.internal.util.test.FakeSettingsProvider; 101 import com.android.server.connectivity.tethering.IControlsTethering; 102 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator; 103 import com.android.server.connectivity.tethering.OffloadHardwareInterface; 104 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine; 105 import com.android.server.connectivity.tethering.TetheringDependencies; 106 import com.android.server.connectivity.tethering.UpstreamNetworkMonitor; 107 108 import org.junit.After; 109 import org.junit.Before; 110 import org.junit.Test; 111 import org.junit.runner.RunWith; 112 import org.mockito.Mock; 113 import org.mockito.MockitoAnnotations; 114 115 import java.net.Inet4Address; 116 import java.net.Inet6Address; 117 import java.util.ArrayList; 118 import java.util.Vector; 119 120 @RunWith(AndroidJUnit4.class) 121 @SmallTest 122 public class TetheringTest { 123 private static final int IFINDEX_OFFSET = 100; 124 125 private static final String[] PROVISIONING_APP_NAME = {"some", "app"}; 126 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0"; 127 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0"; 128 private static final String TEST_USB_IFNAME = "test_rndis0"; 129 private static final String TEST_WLAN_IFNAME = "test_wlan0"; 130 131 @Mock private ApplicationInfo mApplicationInfo; 132 @Mock private Context mContext; 133 @Mock private INetworkManagementService mNMService; 134 @Mock private INetworkStatsService mStatsService; 135 @Mock private INetworkPolicyManager mPolicyManager; 136 @Mock private MockableSystemProperties mSystemProperties; 137 @Mock private OffloadHardwareInterface mOffloadHardwareInterface; 138 @Mock private Resources mResources; 139 @Mock private UsbManager mUsbManager; 140 @Mock private WifiManager mWifiManager; 141 @Mock private CarrierConfigManager mCarrierConfigManager; 142 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor; 143 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator; 144 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon; 145 @Mock private INetd mNetd; 146 147 private final MockTetheringDependencies mTetheringDependencies = 148 new MockTetheringDependencies(); 149 150 // Like so many Android system APIs, these cannot be mocked because it is marked final. 151 // We have to use the real versions. 152 private final PersistableBundle mCarrierConfig = new PersistableBundle(); 153 private final TestLooper mLooper = new TestLooper(); 154 155 private Vector<Intent> mIntents; 156 private BroadcastInterceptingContext mServiceContext; 157 private MockContentResolver mContentResolver; 158 private BroadcastReceiver mBroadcastReceiver; 159 private Tethering mTethering; 160 161 private class MockContext extends BroadcastInterceptingContext { MockContext(Context base)162 MockContext(Context base) { 163 super(base); 164 } 165 166 @Override getApplicationInfo()167 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; } 168 169 @Override getContentResolver()170 public ContentResolver getContentResolver() { return mContentResolver; } 171 172 @Override getPackageName()173 public String getPackageName() { return "TetheringTest"; } 174 175 @Override getResources()176 public Resources getResources() { return mResources; } 177 178 @Override getSystemService(String name)179 public Object getSystemService(String name) { 180 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager; 181 if (Context.USB_SERVICE.equals(name)) return mUsbManager; 182 return super.getSystemService(name); 183 } 184 } 185 186 public class MockTetheringDependencies extends TetheringDependencies { 187 StateMachine upstreamNetworkMonitorMasterSM; 188 ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList; 189 int isTetheringSupportedCalls; 190 reset()191 public void reset() { 192 upstreamNetworkMonitorMasterSM = null; 193 ipv6CoordinatorNotifyList = null; 194 isTetheringSupportedCalls = 0; 195 } 196 197 @Override getOffloadHardwareInterface(Handler h, SharedLog log)198 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) { 199 return mOffloadHardwareInterface; 200 } 201 202 @Override getUpstreamNetworkMonitor(Context ctx, StateMachine target, SharedLog log, int what)203 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx, 204 StateMachine target, SharedLog log, int what) { 205 upstreamNetworkMonitorMasterSM = target; 206 return mUpstreamNetworkMonitor; 207 } 208 209 @Override getIPv6TetheringCoordinator( ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log)210 public IPv6TetheringCoordinator getIPv6TetheringCoordinator( 211 ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) { 212 ipv6CoordinatorNotifyList = notifyList; 213 return mIPv6TetheringCoordinator; 214 } 215 216 @Override getRouterAdvertisementDaemon(InterfaceParams ifParams)217 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) { 218 return mRouterAdvertisementDaemon; 219 } 220 221 @Override getNetdService()222 public INetd getNetdService() { 223 return mNetd; 224 } 225 226 @Override getInterfaceParams(String ifName)227 public InterfaceParams getInterfaceParams(String ifName) { 228 final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME, 229 TEST_MOBILE_IFNAME }; 230 final int index = ArrayUtils.indexOf(ifaces, ifName); 231 assertTrue("Non-mocked interface: " + ifName, index >= 0); 232 return new InterfaceParams(ifName, index + IFINDEX_OFFSET, 233 MacAddress.ALL_ZEROS_ADDRESS); 234 } 235 236 @Override isTetheringSupported()237 public boolean isTetheringSupported() { 238 isTetheringSupportedCalls++; 239 return true; 240 } 241 } 242 buildMobileUpstreamState(boolean withIPv4, boolean withIPv6, boolean with464xlat)243 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6, 244 boolean with464xlat) { 245 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null); 246 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 247 final LinkProperties prop = new LinkProperties(); 248 prop.setInterfaceName(TEST_MOBILE_IFNAME); 249 250 if (withIPv4) { 251 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 252 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME)); 253 } 254 255 if (withIPv6) { 256 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2")); 257 prop.addLinkAddress( 258 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"), 259 NetworkConstants.RFC7421_PREFIX_LENGTH)); 260 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), 261 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME)); 262 } 263 264 if (with464xlat) { 265 final LinkProperties stackedLink = new LinkProperties(); 266 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME); 267 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 268 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME)); 269 270 prop.addStackedLink(stackedLink); 271 } 272 273 274 final NetworkCapabilities capabilities = new NetworkCapabilities() 275 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);; 276 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid"); 277 } 278 buildMobileIPv4UpstreamState()279 private static NetworkState buildMobileIPv4UpstreamState() { 280 return buildMobileUpstreamState(true, false, false); 281 } 282 buildMobileIPv6UpstreamState()283 private static NetworkState buildMobileIPv6UpstreamState() { 284 return buildMobileUpstreamState(false, true, false); 285 } 286 buildMobileDualStackUpstreamState()287 private static NetworkState buildMobileDualStackUpstreamState() { 288 return buildMobileUpstreamState(true, true, false); 289 } 290 buildMobile464xlatUpstreamState()291 private static NetworkState buildMobile464xlatUpstreamState() { 292 return buildMobileUpstreamState(false, true, true); 293 } 294 295 @Before setUp()296 public void setUp() throws Exception { 297 MockitoAnnotations.initMocks(this); 298 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range)) 299 .thenReturn(new String[0]); 300 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs)) 301 .thenReturn(new String[] { "test_rndis\\d" }); 302 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs)) 303 .thenReturn(new String[]{ "test_wlan\\d" }); 304 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs)) 305 .thenReturn(new String[0]); 306 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types)) 307 .thenReturn(new int[0]); 308 when(mNMService.listInterfaces()) 309 .thenReturn(new String[] { 310 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME}); 311 when(mNMService.getInterfaceConfig(anyString())) 312 .thenReturn(new InterfaceConfiguration()); 313 when(mRouterAdvertisementDaemon.start()) 314 .thenReturn(true); 315 316 mServiceContext = new MockContext(mContext); 317 mContentResolver = new MockContentResolver(mServiceContext); 318 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); 319 mIntents = new Vector<>(); 320 mBroadcastReceiver = new BroadcastReceiver() { 321 @Override 322 public void onReceive(Context context, Intent intent) { 323 mIntents.addElement(intent); 324 } 325 }; 326 mServiceContext.registerReceiver(mBroadcastReceiver, 327 new IntentFilter(ACTION_TETHER_STATE_CHANGED)); 328 mTetheringDependencies.reset(); 329 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager, 330 mLooper.getLooper(), mSystemProperties, 331 mTetheringDependencies); 332 verify(mNMService).registerTetheringStatsProvider(any(), anyString()); 333 } 334 335 @After tearDown()336 public void tearDown() { 337 mServiceContext.unregisterReceiver(mBroadcastReceiver); 338 } 339 setupForRequiredProvisioning()340 private void setupForRequiredProvisioning() { 341 // Produce some acceptable looking provision app setting if requested. 342 when(mResources.getStringArray( 343 com.android.internal.R.array.config_mobile_hotspot_provision_app)) 344 .thenReturn(PROVISIONING_APP_NAME); 345 // Don't disable tethering provisioning unless requested. 346 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY), 347 anyBoolean())).thenReturn(false); 348 // Act like the CarrierConfigManager is present and ready unless told otherwise. 349 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) 350 .thenReturn(mCarrierConfigManager); 351 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig); 352 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); 353 } 354 355 @Test canRequireProvisioning()356 public void canRequireProvisioning() { 357 setupForRequiredProvisioning(); 358 sendConfigurationChanged(); 359 assertTrue(mTethering.isTetherProvisioningRequired()); 360 } 361 362 @Test toleratesCarrierConfigManagerMissing()363 public void toleratesCarrierConfigManagerMissing() { 364 setupForRequiredProvisioning(); 365 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE)) 366 .thenReturn(null); 367 sendConfigurationChanged(); 368 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app. 369 // We therefore still require provisioning. 370 assertTrue(mTethering.isTetherProvisioningRequired()); 371 } 372 373 @Test toleratesCarrierConfigMissing()374 public void toleratesCarrierConfigMissing() { 375 setupForRequiredProvisioning(); 376 when(mCarrierConfigManager.getConfig()).thenReturn(null); 377 sendConfigurationChanged(); 378 // We still have a provisioning app configured, so still require provisioning. 379 assertTrue(mTethering.isTetherProvisioningRequired()); 380 } 381 382 @Test provisioningNotRequiredWhenAppNotFound()383 public void provisioningNotRequiredWhenAppNotFound() { 384 setupForRequiredProvisioning(); 385 when(mResources.getStringArray( 386 com.android.internal.R.array.config_mobile_hotspot_provision_app)) 387 .thenReturn(null); 388 assertTrue(!mTethering.isTetherProvisioningRequired()); 389 when(mResources.getStringArray( 390 com.android.internal.R.array.config_mobile_hotspot_provision_app)) 391 .thenReturn(new String[] {"malformedApp"}); 392 assertTrue(!mTethering.isTetherProvisioningRequired()); 393 } 394 sendWifiApStateChanged(int state)395 private void sendWifiApStateChanged(int state) { 396 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 397 intent.putExtra(EXTRA_WIFI_AP_STATE, state); 398 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 399 } 400 sendWifiApStateChanged(int state, String ifname, int ipmode)401 private void sendWifiApStateChanged(int state, String ifname, int ipmode) { 402 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 403 intent.putExtra(EXTRA_WIFI_AP_STATE, state); 404 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname); 405 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode); 406 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 407 } 408 sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction)409 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) { 410 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE); 411 intent.putExtra(USB_CONNECTED, connected); 412 intent.putExtra(USB_CONFIGURED, configured); 413 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction); 414 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 415 } 416 sendConfigurationChanged()417 private void sendConfigurationChanged() { 418 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED); 419 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 420 } 421 verifyInterfaceServingModeStarted()422 private void verifyInterfaceServingModeStarted() throws Exception { 423 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME); 424 verify(mNMService, times(1)) 425 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); 426 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME); 427 } 428 verifyTetheringBroadcast(String ifname, String whichExtra)429 private void verifyTetheringBroadcast(String ifname, String whichExtra) { 430 // Verify that ifname is in the whichExtra array of the tether state changed broadcast. 431 final Intent bcast = mIntents.get(0); 432 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction()); 433 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra); 434 assertTrue(ifnames.contains(ifname)); 435 mIntents.remove(bcast); 436 } 437 failingLocalOnlyHotspotLegacyApBroadcast( boolean emulateInterfaceStatusChanged)438 public void failingLocalOnlyHotspotLegacyApBroadcast( 439 boolean emulateInterfaceStatusChanged) throws Exception { 440 // Emulate externally-visible WifiManager effects, causing the 441 // per-interface state machine to start up, and telling us that 442 // hotspot mode is to be started. 443 if (emulateInterfaceStatusChanged) { 444 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); 445 } 446 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED); 447 mLooper.dispatchAll(); 448 449 // If, and only if, Tethering received an interface status changed 450 // then it creates a TetherInterfaceStateMachine and sends out a 451 // broadcast indicating that the interface is "available". 452 if (emulateInterfaceStatusChanged) { 453 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls); 454 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); 455 } 456 verifyNoMoreInteractions(mNMService); 457 verifyNoMoreInteractions(mWifiManager); 458 } 459 prepareUsbTethering(NetworkState upstreamState)460 private void prepareUsbTethering(NetworkState upstreamState) { 461 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) 462 .thenReturn(upstreamState); 463 464 // Emulate pressing the USB tethering button in Settings UI. 465 mTethering.startTethering(TETHERING_USB, null, false); 466 mLooper.dispatchAll(); 467 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); 468 469 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true); 470 } 471 472 @Test testUsbConfiguredBroadcastStartsTethering()473 public void testUsbConfiguredBroadcastStartsTethering() throws Exception { 474 NetworkState upstreamState = buildMobileIPv4UpstreamState(); 475 prepareUsbTethering(upstreamState); 476 477 // This should produce no activity of any kind. 478 verifyNoMoreInteractions(mNMService); 479 480 // Pretend we then receive USB configured broadcast. 481 sendUsbBroadcast(true, true, true); 482 mLooper.dispatchAll(); 483 // Now we should see the start of tethering mechanics (in this case: 484 // tetherMatchingInterfaces() which starts by fetching all interfaces). 485 verify(mNMService, times(1)).listInterfaces(); 486 487 // UpstreamNetworkMonitor should receive selected upstream 488 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any()); 489 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network); 490 } 491 492 @Test failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged()493 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception { 494 failingLocalOnlyHotspotLegacyApBroadcast(true); 495 } 496 497 @Test failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged()498 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception { 499 failingLocalOnlyHotspotLegacyApBroadcast(false); 500 } 501 workingLocalOnlyHotspotEnrichedApBroadcast( boolean emulateInterfaceStatusChanged)502 public void workingLocalOnlyHotspotEnrichedApBroadcast( 503 boolean emulateInterfaceStatusChanged) throws Exception { 504 // Emulate externally-visible WifiManager effects, causing the 505 // per-interface state machine to start up, and telling us that 506 // hotspot mode is to be started. 507 if (emulateInterfaceStatusChanged) { 508 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); 509 } 510 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY); 511 mLooper.dispatchAll(); 512 513 verifyInterfaceServingModeStarted(); 514 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); 515 verify(mNMService, times(1)).setIpForwardingEnabled(true); 516 verify(mNMService, times(1)).startTethering(any(String[].class)); 517 verifyNoMoreInteractions(mNMService); 518 verify(mWifiManager).updateInterfaceIpState( 519 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 520 verifyNoMoreInteractions(mWifiManager); 521 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY); 522 verify(mUpstreamNetworkMonitor, times(1)).start(); 523 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast(). 524 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls); 525 526 // Emulate externally-visible WifiManager effects, when hotspot mode 527 // is being torn down. 528 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); 529 mTethering.interfaceRemoved(TEST_WLAN_IFNAME); 530 mLooper.dispatchAll(); 531 532 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); 533 // TODO: Why is {g,s}etInterfaceConfig() called more than once? 534 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME); 535 verify(mNMService, atLeastOnce()) 536 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); 537 verify(mNMService, times(1)).stopTethering(); 538 verify(mNMService, times(1)).setIpForwardingEnabled(false); 539 verifyNoMoreInteractions(mNMService); 540 verifyNoMoreInteractions(mWifiManager); 541 // Asking for the last error after the per-interface state machine 542 // has been reaped yields an unknown interface error. 543 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME)); 544 } 545 546 /** 547 * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator. 548 */ sendIPv6TetherUpdates(NetworkState upstreamState)549 private void sendIPv6TetherUpdates(NetworkState upstreamState) { 550 // IPv6TetheringCoordinator must have been notified of downstream 551 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream( 552 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)), 553 eq(IControlsTethering.STATE_TETHERED)); 554 555 for (TetherInterfaceStateMachine tism : 556 mTetheringDependencies.ipv6CoordinatorNotifyList) { 557 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false); 558 tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, 559 upstreamState.linkProperties.isIPv6Provisioned() 560 ? ipv6OnlyState.linkProperties 561 : null); 562 } 563 mLooper.dispatchAll(); 564 } 565 runUsbTethering(NetworkState upstreamState)566 private void runUsbTethering(NetworkState upstreamState) { 567 prepareUsbTethering(upstreamState); 568 sendUsbBroadcast(true, true, true); 569 mLooper.dispatchAll(); 570 } 571 572 @Test workingMobileUsbTethering_IPv4()573 public void workingMobileUsbTethering_IPv4() throws Exception { 574 NetworkState upstreamState = buildMobileIPv4UpstreamState(); 575 runUsbTethering(upstreamState); 576 577 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 578 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 579 580 sendIPv6TetherUpdates(upstreamState); 581 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull()); 582 } 583 584 @Test workingMobileUsbTethering_IPv6()585 public void workingMobileUsbTethering_IPv6() throws Exception { 586 NetworkState upstreamState = buildMobileIPv6UpstreamState(); 587 runUsbTethering(upstreamState); 588 589 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 590 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 591 592 sendIPv6TetherUpdates(upstreamState); 593 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); 594 verify(mNetd, times(1)).tetherApplyDnsInterfaces(); 595 } 596 597 @Test workingMobileUsbTethering_DualStack()598 public void workingMobileUsbTethering_DualStack() throws Exception { 599 NetworkState upstreamState = buildMobileDualStackUpstreamState(); 600 runUsbTethering(upstreamState); 601 602 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 603 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 604 verify(mRouterAdvertisementDaemon, times(1)).start(); 605 606 sendIPv6TetherUpdates(upstreamState); 607 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); 608 verify(mNetd, times(1)).tetherApplyDnsInterfaces(); 609 } 610 611 @Test workingMobileUsbTethering_MultipleUpstreams()612 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception { 613 NetworkState upstreamState = buildMobile464xlatUpstreamState(); 614 runUsbTethering(upstreamState); 615 616 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); 617 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 618 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 619 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, 620 TEST_XLAT_MOBILE_IFNAME); 621 622 sendIPv6TetherUpdates(upstreamState); 623 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull()); 624 verify(mNetd, times(1)).tetherApplyDnsInterfaces(); 625 } 626 627 @Test workingMobileUsbTethering_v6Then464xlat()628 public void workingMobileUsbTethering_v6Then464xlat() throws Exception { 629 // Setup IPv6 630 NetworkState upstreamState = buildMobileIPv6UpstreamState(); 631 runUsbTethering(upstreamState); 632 633 // Then 464xlat comes up 634 upstreamState = buildMobile464xlatUpstreamState(); 635 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any())) 636 .thenReturn(upstreamState); 637 638 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES. 639 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage( 640 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK, 641 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 642 0, 643 upstreamState); 644 mLooper.dispatchAll(); 645 646 // Forwarding is added for 464xlat, and was still added only once for v6 647 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME); 648 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 649 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME); 650 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, 651 TEST_XLAT_MOBILE_IFNAME); 652 } 653 654 @Test workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged()655 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception { 656 workingLocalOnlyHotspotEnrichedApBroadcast(true); 657 } 658 659 @Test workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged()660 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception { 661 workingLocalOnlyHotspotEnrichedApBroadcast(false); 662 } 663 664 // TODO: Test with and without interfaceStatusChanged(). 665 @Test failingWifiTetheringLegacyApBroadcast()666 public void failingWifiTetheringLegacyApBroadcast() throws Exception { 667 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); 668 669 // Emulate pressing the WiFi tethering button. 670 mTethering.startTethering(TETHERING_WIFI, null, false); 671 mLooper.dispatchAll(); 672 verify(mWifiManager, times(1)).startSoftAp(null); 673 verifyNoMoreInteractions(mWifiManager); 674 verifyNoMoreInteractions(mNMService); 675 676 // Emulate externally-visible WifiManager effects, causing the 677 // per-interface state machine to start up, and telling us that 678 // tethering mode is to be started. 679 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); 680 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED); 681 mLooper.dispatchAll(); 682 683 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls); 684 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); 685 verifyNoMoreInteractions(mNMService); 686 verifyNoMoreInteractions(mWifiManager); 687 } 688 689 // TODO: Test with and without interfaceStatusChanged(). 690 @Test workingWifiTetheringEnrichedApBroadcast()691 public void workingWifiTetheringEnrichedApBroadcast() throws Exception { 692 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); 693 694 // Emulate pressing the WiFi tethering button. 695 mTethering.startTethering(TETHERING_WIFI, null, false); 696 mLooper.dispatchAll(); 697 verify(mWifiManager, times(1)).startSoftAp(null); 698 verifyNoMoreInteractions(mWifiManager); 699 verifyNoMoreInteractions(mNMService); 700 701 // Emulate externally-visible WifiManager effects, causing the 702 // per-interface state machine to start up, and telling us that 703 // tethering mode is to be started. 704 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); 705 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); 706 mLooper.dispatchAll(); 707 708 verifyInterfaceServingModeStarted(); 709 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); 710 verify(mNMService, times(1)).setIpForwardingEnabled(true); 711 verify(mNMService, times(1)).startTethering(any(String[].class)); 712 verifyNoMoreInteractions(mNMService); 713 verify(mWifiManager).updateInterfaceIpState( 714 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED); 715 verifyNoMoreInteractions(mWifiManager); 716 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER); 717 verify(mUpstreamNetworkMonitor, times(1)).start(); 718 // In tethering mode, in the default configuration, an explicit request 719 // for a mobile network is also made. 720 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest(); 721 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast(). 722 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls); 723 724 ///// 725 // We do not currently emulate any upstream being found. 726 // 727 // This is why there are no calls to verify mNMService.enableNat() or 728 // mNMService.startInterfaceForwarding(). 729 ///// 730 731 // Emulate pressing the WiFi tethering button. 732 mTethering.stopTethering(TETHERING_WIFI); 733 mLooper.dispatchAll(); 734 verify(mWifiManager, times(1)).stopSoftAp(); 735 verifyNoMoreInteractions(mWifiManager); 736 verifyNoMoreInteractions(mNMService); 737 738 // Emulate externally-visible WifiManager effects, when tethering mode 739 // is being torn down. 740 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED); 741 mTethering.interfaceRemoved(TEST_WLAN_IFNAME); 742 mLooper.dispatchAll(); 743 744 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); 745 // TODO: Why is {g,s}etInterfaceConfig() called more than once? 746 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME); 747 verify(mNMService, atLeastOnce()) 748 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); 749 verify(mNMService, times(1)).stopTethering(); 750 verify(mNMService, times(1)).setIpForwardingEnabled(false); 751 verifyNoMoreInteractions(mNMService); 752 verifyNoMoreInteractions(mWifiManager); 753 // Asking for the last error after the per-interface state machine 754 // has been reaped yields an unknown interface error. 755 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME)); 756 } 757 758 // TODO: Test with and without interfaceStatusChanged(). 759 @Test failureEnablingIpForwarding()760 public void failureEnablingIpForwarding() throws Exception { 761 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true); 762 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true); 763 764 // Emulate pressing the WiFi tethering button. 765 mTethering.startTethering(TETHERING_WIFI, null, false); 766 mLooper.dispatchAll(); 767 verify(mWifiManager, times(1)).startSoftAp(null); 768 verifyNoMoreInteractions(mWifiManager); 769 verifyNoMoreInteractions(mNMService); 770 771 // Emulate externally-visible WifiManager effects, causing the 772 // per-interface state machine to start up, and telling us that 773 // tethering mode is to be started. 774 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); 775 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED); 776 mLooper.dispatchAll(); 777 778 // We verify get/set called thrice here: once for setup and twice during 779 // teardown because all events happen over the course of the single 780 // dispatchAll() above. Note that once the TISM IPv4 address config 781 // code is refactored the two calls during shutdown will revert to one. 782 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME); 783 verify(mNMService, times(3)) 784 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class)); 785 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME); 786 verify(mWifiManager).updateInterfaceIpState( 787 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED); 788 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast(). 789 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls); 790 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER); 791 // This is called, but will throw. 792 verify(mNMService, times(1)).setIpForwardingEnabled(true); 793 // This never gets called because of the exception thrown above. 794 verify(mNMService, times(0)).startTethering(any(String[].class)); 795 // When the master state machine transitions to an error state it tells 796 // downstream interfaces, which causes us to tell Wi-Fi about the error 797 // so it can take down AP mode. 798 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME); 799 verify(mWifiManager).updateInterfaceIpState( 800 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR); 801 802 verifyNoMoreInteractions(mWifiManager); 803 verifyNoMoreInteractions(mNMService); 804 } 805 userRestrictionsListenerBehaviour( boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList, int expectedInteractionsWithShowNotification)806 private void userRestrictionsListenerBehaviour( 807 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList, 808 int expectedInteractionsWithShowNotification) throws Exception { 809 final int userId = 0; 810 final Bundle currRestrictions = new Bundle(); 811 final Bundle newRestrictions = new Bundle(); 812 Tethering tethering = mock(Tethering.class); 813 Tethering.TetheringUserRestrictionListener turl = 814 new Tethering.TetheringUserRestrictionListener(tethering); 815 816 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow); 817 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow); 818 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList); 819 820 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions); 821 822 verify(tethering, times(expectedInteractionsWithShowNotification)) 823 .showTetheredNotification(anyInt(), eq(false)); 824 825 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll(); 826 } 827 828 @Test testDisallowTetheringWhenNoTetheringInterfaceIsActive()829 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception { 830 final String[] emptyActiveIfacesList = new String[]{}; 831 final boolean currDisallow = false; 832 final boolean nextDisallow = true; 833 final int expectedInteractionsWithShowNotification = 0; 834 835 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList, 836 expectedInteractionsWithShowNotification); 837 } 838 839 @Test testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive()840 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception { 841 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME}; 842 final boolean currDisallow = false; 843 final boolean nextDisallow = true; 844 final int expectedInteractionsWithShowNotification = 1; 845 846 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, 847 expectedInteractionsWithShowNotification); 848 } 849 850 @Test testAllowTetheringWhenNoTetheringInterfaceIsActive()851 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception { 852 final String[] nonEmptyActiveIfacesList = new String[]{}; 853 final boolean currDisallow = true; 854 final boolean nextDisallow = false; 855 final int expectedInteractionsWithShowNotification = 0; 856 857 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, 858 expectedInteractionsWithShowNotification); 859 } 860 861 @Test testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive()862 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception { 863 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME}; 864 final boolean currDisallow = true; 865 final boolean nextDisallow = false; 866 final int expectedInteractionsWithShowNotification = 0; 867 868 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, 869 expectedInteractionsWithShowNotification); 870 } 871 872 @Test testDisallowTetheringUnchanged()873 public void testDisallowTetheringUnchanged() throws Exception { 874 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME}; 875 final int expectedInteractionsWithShowNotification = 0; 876 boolean currDisallow = true; 877 boolean nextDisallow = true; 878 879 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, 880 expectedInteractionsWithShowNotification); 881 882 currDisallow = false; 883 nextDisallow = false; 884 885 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList, 886 expectedInteractionsWithShowNotification); 887 } 888 889 890 // TODO: Test that a request for hotspot mode doesn't interfere with an 891 // already operating tethering mode interface. 892 } 893