• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
MockContext(Context base)176         MockContext(Context base) {
177             super(base);
178         }
179 
180         @Override
getApplicationInfo()181         public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
182 
183         @Override
getContentResolver()184         public ContentResolver getContentResolver() { return mContentResolver; }
185 
186         @Override
getPackageName()187         public String getPackageName() { return "TetheringTest"; }
188 
189         @Override
getResources()190         public Resources getResources() { return mResources; }
191 
192         @Override
getSystemService(String name)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
getRouterAdvertisementDaemon( InterfaceParams ifParams)202         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
203                 InterfaceParams ifParams) {
204             return mRouterAdvertisementDaemon;
205         }
206 
207         @Override
getInterfaceParams(String ifName)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
getNetdService()220         public INetd getNetdService() {
221             return mNetd;
222         }
223 
224         @Override
makeDhcpServer(String ifName, DhcpServingParamsParcel params, DhcpServerCallbacks cb)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 
reset()242         public void reset() {
243             upstreamNetworkMonitorMasterSM = null;
244             ipv6CoordinatorNotifyList = null;
245             isTetheringSupportedCalls = 0;
246         }
247 
248         @Override
getOffloadHardwareInterface(Handler h, SharedLog log)249         public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
250             return mOffloadHardwareInterface;
251         }
252 
253         @Override
getUpstreamNetworkMonitor(Context ctx, StateMachine target, SharedLog log, int what)254         public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
255                 StateMachine target, SharedLog log, int what) {
256             upstreamNetworkMonitorMasterSM = target;
257             return mUpstreamNetworkMonitor;
258         }
259 
260         @Override
getIPv6TetheringCoordinator( ArrayList<IpServer> notifyList, SharedLog log)261         public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
262                 ArrayList<IpServer> notifyList, SharedLog log) {
263             ipv6CoordinatorNotifyList = notifyList;
264             return mIPv6TetheringCoordinator;
265         }
266 
267         @Override
getIpServerDependencies()268         public IpServer.Dependencies getIpServerDependencies() {
269             return mIpServerDependencies;
270         }
271 
272         @Override
isTetheringSupported()273         public boolean isTetheringSupported() {
274             isTetheringSupportedCalls++;
275             return true;
276         }
277 
278         @Override
getDefaultDataSubscriptionId()279         public int getDefaultDataSubscriptionId() {
280             return INVALID_SUBSCRIPTION_ID;
281         }
282     }
283 
buildMobileUpstreamState(boolean withIPv4, boolean withIPv6, boolean with464xlat)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 
buildMobileIPv4UpstreamState()320     private static NetworkState buildMobileIPv4UpstreamState() {
321         return buildMobileUpstreamState(true, false, false);
322     }
323 
buildMobileIPv6UpstreamState()324     private static NetworkState buildMobileIPv6UpstreamState() {
325         return buildMobileUpstreamState(false, true, false);
326     }
327 
buildMobileDualStackUpstreamState()328     private static NetworkState buildMobileDualStackUpstreamState() {
329         return buildMobileUpstreamState(true, true, false);
330     }
331 
buildMobile464xlatUpstreamState()332     private static NetworkState buildMobile464xlatUpstreamState() {
333         return buildMobileUpstreamState(false, true, true);
334     }
335 
336     @Before
setUp()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 
makeTethering()377     private Tethering makeTethering() {
378         return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
379                 mLooper.getLooper(), mSystemProperties,
380                 mTetheringDependencies);
381     }
382 
383     @After
tearDown()384     public void tearDown() {
385         mServiceContext.unregisterReceiver(mBroadcastReceiver);
386     }
387 
sendWifiApStateChanged(int state)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 
sendWifiApStateChanged(int state, String ifname, int ipmode)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 
sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction)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 
sendConfigurationChanged()410     private void sendConfigurationChanged() {
411         final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
412         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
413     }
414 
verifyInterfaceServingModeStarted()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 
verifyTetheringBroadcast(String ifname, String whichExtra)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 
failingLocalOnlyHotspotLegacyApBroadcast( boolean emulateInterfaceStatusChanged)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 
prepareUsbTethering(NetworkState upstreamState)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
testUsbConfiguredBroadcastStartsTethering()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
failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged()487     public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
488         failingLocalOnlyHotspotLegacyApBroadcast(true);
489     }
490 
491     @Test
failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged()492     public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
493         failingLocalOnlyHotspotLegacyApBroadcast(false);
494     }
495 
workingLocalOnlyHotspotEnrichedApBroadcast( boolean emulateInterfaceStatusChanged)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      */
sendIPv6TetherUpdates(NetworkState upstreamState)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 
runUsbTethering(NetworkState upstreamState)560     private void runUsbTethering(NetworkState upstreamState) {
561         prepareUsbTethering(upstreamState);
562         sendUsbBroadcast(true, true, true);
563         mLooper.dispatchAll();
564     }
565 
566     @Test
workingMobileUsbTethering_IPv4()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
workingMobileUsbTethering_IPv4LegacyDhcp()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
workingMobileUsbTethering_IPv6()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
workingMobileUsbTethering_DualStack()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
workingMobileUsbTethering_MultipleUpstreams()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
workingMobileUsbTethering_v6Then464xlat()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
configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes()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
workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged()688     public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
689         workingLocalOnlyHotspotEnrichedApBroadcast(true);
690     }
691 
692     @Test
workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged()693     public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
694         workingLocalOnlyHotspotEnrichedApBroadcast(false);
695     }
696 
697     // TODO: Test with and without interfaceStatusChanged().
698     @Test
failingWifiTetheringLegacyApBroadcast()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
workingWifiTetheringEnrichedApBroadcast()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
failureEnablingIpForwarding()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 
userRestrictionsListenerBehaviour( boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList, int expectedInteractionsWithShowNotification)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
testDisallowTetheringWhenNoTetheringInterfaceIsActive()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
testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive()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
testAllowTetheringWhenNoTetheringInterfaceIsActive()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
testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive()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
testDisallowTetheringUnchanged()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 
expectUpstreamChanged(Network... networks)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
onUpstreamChanged(Network network)937         public void onUpstreamChanged(Network network) {
938             mActualUpstreams.add(network);
939         }
940 
assertNoCallback()941         public void assertNoCallback() {
942             assertTrue(mActualUpstreams.isEmpty());
943         }
944     }
945 
946     @Test
testRegisterTetheringEventCallback()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