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