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