blob: c727bd2e00dc4c043d8e77a56d5f948efa0fbfc2 [file] [log] [blame]
Christopher Wiley497c1472016-10-11 13:26:03 -07001/*
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
17package com.android.server.connectivity;
18
Erik Klinec438e302017-07-04 22:02:49 +090019import static android.hardware.usb.UsbManager.USB_CONFIGURED;
20import static android.hardware.usb.UsbManager.USB_CONNECTED;
21import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
22import static android.net.ConnectivityManager.TETHERING_WIFI;
23import static android.net.ConnectivityManager.TETHERING_USB;
Erik Kline2efb8272017-05-31 15:53:53 +090024import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
25import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
26import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
27import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
28import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
29import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090030
Erik Klineea9cc482017-03-10 19:35:34 +090031import static org.junit.Assert.assertEquals;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090032import static org.junit.Assert.assertNotNull;
Christopher Wiley497c1472016-10-11 13:26:03 -070033import static org.junit.Assert.assertTrue;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090034import static org.mockito.ArgumentMatchers.argThat;
35import static org.mockito.ArgumentMatchers.notNull;
Christopher Wiley497c1472016-10-11 13:26:03 -070036import static org.mockito.Matchers.anyBoolean;
Erik Klineea9cc482017-03-10 19:35:34 +090037import static org.mockito.Matchers.anyInt;
38import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070039import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090040import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090041import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090042import static org.mockito.Mockito.doThrow;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090043import static org.mockito.Mockito.never;
Erik Klineea9cc482017-03-10 19:35:34 +090044import static org.mockito.Mockito.times;
45import static org.mockito.Mockito.verify;
46import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070047import static org.mockito.Mockito.when;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010048import static org.mockito.Mockito.mock;
Christopher Wiley497c1472016-10-11 13:26:03 -070049
Erik Kline8351faa2017-04-17 16:47:23 +090050import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090051import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070052import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090053import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090054import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090055import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070056import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090057import android.hardware.usb.UsbManager;
58import android.net.ConnectivityManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090059import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070060import android.net.INetworkPolicyManager;
61import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090062import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090063import android.net.IpPrefix;
64import android.net.LinkAddress;
65import android.net.LinkProperties;
66import android.net.MacAddress;
67import android.net.Network;
68import android.net.NetworkCapabilities;
69import android.net.NetworkInfo;
70import android.net.NetworkState;
71import android.net.NetworkUtils;
72import android.net.RouteInfo;
73import android.net.ip.RouterAdvertisementDaemon;
74import android.net.util.InterfaceParams;
75import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090076import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090077import android.net.wifi.WifiConfiguration;
78import android.net.wifi.WifiManager;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010079import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090080import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070081import android.os.INetworkManagementService;
82import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090083import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070084import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090085import android.os.UserHandle;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010086import android.os.UserManager;
Erik Kline92c4db02017-05-31 10:21:32 +090087import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070088import android.support.test.filters.SmallTest;
89import android.support.test.runner.AndroidJUnit4;
90import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090091import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070092
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090093import com.android.internal.util.ArrayUtils;
94import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +090095import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +090096import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090097import com.android.server.connectivity.tethering.IControlsTethering;
98import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +090099import com.android.server.connectivity.tethering.OffloadHardwareInterface;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900100import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900101import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900102import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900103
Erik Kline8351faa2017-04-17 16:47:23 +0900104import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700105import org.junit.Before;
106import org.junit.Test;
107import org.junit.runner.RunWith;
108import org.mockito.Mock;
109import org.mockito.MockitoAnnotations;
110
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900111import java.net.Inet4Address;
112import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900113import java.util.ArrayList;
114import java.util.Vector;
115
Christopher Wiley497c1472016-10-11 13:26:03 -0700116@RunWith(AndroidJUnit4.class)
117@SmallTest
118public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900119 private static final int IFINDEX_OFFSET = 100;
120
Christopher Wiley497c1472016-10-11 13:26:03 -0700121 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900122 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
123 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
124 private static final String TEST_USB_IFNAME = "test_rndis0";
125 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700126
Erik Klinef3a08b42017-06-07 16:33:19 +0900127 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700128 @Mock private Context mContext;
Erik Klineea9cc482017-03-10 19:35:34 +0900129 @Mock private ConnectivityManager mConnectivityManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700130 @Mock private INetworkManagementService mNMService;
131 @Mock private INetworkStatsService mStatsService;
132 @Mock private INetworkPolicyManager mPolicyManager;
133 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900134 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700135 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900136 @Mock private UsbManager mUsbManager;
137 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700138 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900139 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
140 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
141 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
142 @Mock private INetd mNetd;
143
144 private final MockTetheringDependencies mTetheringDependencies =
145 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700146
147 // Like so many Android system APIs, these cannot be mocked because it is marked final.
148 // We have to use the real versions.
149 private final PersistableBundle mCarrierConfig = new PersistableBundle();
150 private final TestLooper mLooper = new TestLooper();
151
Erik Kline8351faa2017-04-17 16:47:23 +0900152 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900153 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900154 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900155 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700156 private Tethering mTethering;
157
Erik Klineea9cc482017-03-10 19:35:34 +0900158 private class MockContext extends BroadcastInterceptingContext {
159 MockContext(Context base) {
160 super(base);
161 }
162
163 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900164 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
165
166 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900167 public ContentResolver getContentResolver() { return mContentResolver; }
168
169 @Override
170 public String getPackageName() { return "TetheringTest"; }
171
172 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900173 public Resources getResources() { return mResources; }
174
175 @Override
176 public Object getSystemService(String name) {
177 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
178 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900179 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900180 return super.getSystemService(name);
181 }
182 }
183
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900184 public class MockTetheringDependencies extends TetheringDependencies {
185 private StateMachine upstreamNetworkMonitorMasterSM;
186 private ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
187
188 @Override
189 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
190 return mOffloadHardwareInterface;
191 }
192
193 @Override
194 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
195 StateMachine target, SharedLog log, int what) {
196 upstreamNetworkMonitorMasterSM = target;
197 return mUpstreamNetworkMonitor;
198 }
199
200 @Override
201 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
202 ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
203 ipv6CoordinatorNotifyList = notifyList;
204 return mIPv6TetheringCoordinator;
205 }
206
207 @Override
208 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
209 return mRouterAdvertisementDaemon;
210 }
211
212 @Override
213 public INetd getNetdService() {
214 return mNetd;
215 }
216
217 @Override
218 public InterfaceParams getInterfaceParams(String ifName) {
219 final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
220 TEST_MOBILE_IFNAME };
221 final int index = ArrayUtils.indexOf(ifaces, ifName);
222 assertTrue("Non-mocked interface: " + ifName, index >= 0);
223 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
224 MacAddress.ALL_ZEROS_ADDRESS);
225 }
226 }
227
228 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6) {
229 final NetworkInfo info = new NetworkInfo(ConnectivityManager.TYPE_MOBILE, 0, null, null);
230 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
231 final LinkProperties prop = new LinkProperties();
232 prop.setInterfaceName(TEST_MOBILE_IFNAME);
233
234 if (withIPv4) {
235 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
236 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
237 }
238
239 if (withIPv6) {
240 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
241 prop.addLinkAddress(
242 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
243 NetworkConstants.RFC7421_PREFIX_LENGTH));
244 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
245 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
246 }
247
248
249 final NetworkCapabilities capabilities = new NetworkCapabilities()
250 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
251 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
252 }
253
254 private static NetworkState buildMobileIPv4UpstreamState() {
255 return buildMobileUpstreamState(true, false);
256 }
257
258 private static NetworkState buildMobileDualStackUpstreamState() {
259 return buildMobileUpstreamState(true, true);
260 }
261
Erik Kline8351faa2017-04-17 16:47:23 +0900262 @Before
263 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700264 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700265 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
266 .thenReturn(new String[0]);
267 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900268 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700269 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900270 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700271 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
272 .thenReturn(new String[0]);
273 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
274 .thenReturn(new int[0]);
Erik Klineea9cc482017-03-10 19:35:34 +0900275 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900276 .thenReturn(new String[] {
277 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900278 when(mNMService.getInterfaceConfig(anyString()))
279 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900280 when(mRouterAdvertisementDaemon.start())
281 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900282
283 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900284 mContentResolver = new MockContentResolver(mServiceContext);
285 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900286 mIntents = new Vector<>();
287 mBroadcastReceiver = new BroadcastReceiver() {
288 @Override
289 public void onReceive(Context context, Intent intent) {
290 mIntents.addElement(intent);
291 }
292 };
293 mServiceContext.registerReceiver(mBroadcastReceiver,
294 new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
Erik Klineea9cc482017-03-10 19:35:34 +0900295 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900296 mLooper.getLooper(), mSystemProperties,
297 mTetheringDependencies);
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900298 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700299 }
300
Erik Kline8351faa2017-04-17 16:47:23 +0900301 @After
302 public void tearDown() {
303 mServiceContext.unregisterReceiver(mBroadcastReceiver);
304 }
305
Christopher Wiley497c1472016-10-11 13:26:03 -0700306 private void setupForRequiredProvisioning() {
307 // Produce some acceptable looking provision app setting if requested.
308 when(mResources.getStringArray(
309 com.android.internal.R.array.config_mobile_hotspot_provision_app))
310 .thenReturn(PROVISIONING_APP_NAME);
311 // Don't disable tethering provisioning unless requested.
312 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
313 anyBoolean())).thenReturn(false);
314 // Act like the CarrierConfigManager is present and ready unless told otherwise.
315 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
316 .thenReturn(mCarrierConfigManager);
317 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
318 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
319 }
320
321 @Test
322 public void canRequireProvisioning() {
323 setupForRequiredProvisioning();
324 assertTrue(mTethering.isTetherProvisioningRequired());
325 }
326
327 @Test
328 public void toleratesCarrierConfigManagerMissing() {
329 setupForRequiredProvisioning();
330 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
331 .thenReturn(null);
332 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
333 // We therefore still require provisioning.
334 assertTrue(mTethering.isTetherProvisioningRequired());
335 }
336
337 @Test
338 public void toleratesCarrierConfigMissing() {
339 setupForRequiredProvisioning();
340 when(mCarrierConfigManager.getConfig()).thenReturn(null);
341 // We still have a provisioning app configured, so still require provisioning.
342 assertTrue(mTethering.isTetherProvisioningRequired());
343 }
344
345 @Test
346 public void provisioningNotRequiredWhenAppNotFound() {
347 setupForRequiredProvisioning();
348 when(mResources.getStringArray(
349 com.android.internal.R.array.config_mobile_hotspot_provision_app))
350 .thenReturn(null);
351 assertTrue(!mTethering.isTetherProvisioningRequired());
352 when(mResources.getStringArray(
353 com.android.internal.R.array.config_mobile_hotspot_provision_app))
354 .thenReturn(new String[] {"malformedApp"});
355 assertTrue(!mTethering.isTetherProvisioningRequired());
356 }
Erik Klineea9cc482017-03-10 19:35:34 +0900357
358 private void sendWifiApStateChanged(int state) {
359 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900360 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900361 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
362 }
363
Erik Kline2efb8272017-05-31 15:53:53 +0900364 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
365 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
366 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
367 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
368 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
369 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
370 }
371
Erik Klinec438e302017-07-04 22:02:49 +0900372 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
373 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
374 intent.putExtra(USB_CONNECTED, connected);
375 intent.putExtra(USB_CONFIGURED, configured);
376 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
377 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
378 }
379
Erik Kline9e225542017-06-08 17:48:48 +0900380 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900381 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900382 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900383 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
384 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900385 }
386
387 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
388 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
389 final Intent bcast = mIntents.get(0);
390 assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
391 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
392 assertTrue(ifnames.contains(ifname));
393 mIntents.remove(bcast);
394 }
395
Erik Klinea9cde8b2017-06-20 21:18:31 +0900396 public void failingLocalOnlyHotspotLegacyApBroadcast(
397 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900398 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900399
400 // Emulate externally-visible WifiManager effects, causing the
401 // per-interface state machine to start up, and telling us that
402 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900403 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900404 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900405 }
Erik Kline9e225542017-06-08 17:48:48 +0900406 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900407 mLooper.dispatchAll();
408
Erik Klinea9cde8b2017-06-20 21:18:31 +0900409 // If, and only if, Tethering received an interface status changed
410 // then it creates a TetherInterfaceStateMachine and sends out a
411 // broadcast indicating that the interface is "available".
412 if (emulateInterfaceStatusChanged) {
413 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900414 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900415 }
Erik Kline9e225542017-06-08 17:48:48 +0900416 verifyNoMoreInteractions(mConnectivityManager);
417 verifyNoMoreInteractions(mNMService);
418 verifyNoMoreInteractions(mWifiManager);
419 }
420
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900421 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Klinec438e302017-07-04 22:02:49 +0900422 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900423 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
424 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900425
426 // Emulate pressing the USB tethering button in Settings UI.
427 mTethering.startTethering(TETHERING_USB, null, false);
428 mLooper.dispatchAll();
429 verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
430
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900431 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
432 }
433
434 @Test
435 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
436 NetworkState upstreamState = buildMobileIPv4UpstreamState();
437 prepareUsbTethering(upstreamState);
438
Erik Klinec438e302017-07-04 22:02:49 +0900439 // This should produce no activity of any kind.
440 verifyNoMoreInteractions(mConnectivityManager);
441 verifyNoMoreInteractions(mNMService);
442
443 // Pretend we then receive USB configured broadcast.
444 sendUsbBroadcast(true, true, true);
445 mLooper.dispatchAll();
446 // Now we should see the start of tethering mechanics (in this case:
447 // tetherMatchingInterfaces() which starts by fetching all interfaces).
448 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900449
450 // UpstreamNetworkMonitor should receive selected upstream
451 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
452 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900453 }
454
455 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900456 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
457 failingLocalOnlyHotspotLegacyApBroadcast(true);
458 }
459
460 @Test
461 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
462 failingLocalOnlyHotspotLegacyApBroadcast(false);
463 }
464
465 public void workingLocalOnlyHotspotEnrichedApBroadcast(
466 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900467 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
468
469 // Emulate externally-visible WifiManager effects, causing the
470 // per-interface state machine to start up, and telling us that
471 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900472 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900473 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900474 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900475 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900476 mLooper.dispatchAll();
477
478 verifyInterfaceServingModeStarted();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900479 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900480 verify(mNMService, times(1)).setIpForwardingEnabled(true);
481 verify(mNMService, times(1)).startTethering(any(String[].class));
482 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900483 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900484 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900485 verifyNoMoreInteractions(mWifiManager);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900486 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
487 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900488 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
489 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
490 verifyNoMoreInteractions(mConnectivityManager);
491
492 // Emulate externally-visible WifiManager effects, when hotspot mode
493 // is being torn down.
494 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900495 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900496 mLooper.dispatchAll();
497
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900498 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900499 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900500 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900501 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900502 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900503 verify(mNMService, times(1)).stopTethering();
504 verify(mNMService, times(1)).setIpForwardingEnabled(false);
505 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900506 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900507 // Asking for the last error after the per-interface state machine
508 // has been reaped yields an unknown interface error.
509 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900510 mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900511 }
512
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900513 /**
514 * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
515 */
516 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
517 // IPv6TetheringCoordinator must have been notified of downstream
518 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
519 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
520 eq(IControlsTethering.STATE_TETHERED));
521
522 for (TetherInterfaceStateMachine tism :
523 mTetheringDependencies.ipv6CoordinatorNotifyList) {
524 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true);
525 tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
526 upstreamState.linkProperties.isIPv6Provisioned()
527 ? ipv6OnlyState.linkProperties
528 : null);
529 }
530 mLooper.dispatchAll();
531 }
532
533 private void runUsbTethering(NetworkState upstreamState) {
534 prepareUsbTethering(upstreamState);
535 sendUsbBroadcast(true, true, true);
536 mLooper.dispatchAll();
537 }
538
539 @Test
540 public void workingMobileUsbTethering_IPv4() throws Exception {
541 NetworkState upstreamState = buildMobileIPv4UpstreamState();
542 runUsbTethering(upstreamState);
543
544 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
545 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
546
547 sendIPv6TetherUpdates(upstreamState);
548 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
549 }
550
551 @Test
552 public void workingMobileUsbTethering_DualStack() throws Exception {
553 NetworkState upstreamState = buildMobileDualStackUpstreamState();
554 runUsbTethering(upstreamState);
555
556 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
557 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
558 verify(mRouterAdvertisementDaemon, times(1)).start();
559
560 sendIPv6TetherUpdates(upstreamState);
561 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
562 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
563 }
564
565
Erik Klineea9cc482017-03-10 19:35:34 +0900566 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900567 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
568 workingLocalOnlyHotspotEnrichedApBroadcast(true);
569 }
570
571 @Test
572 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
573 workingLocalOnlyHotspotEnrichedApBroadcast(false);
574 }
575
576 // TODO: Test with and without interfaceStatusChanged().
577 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900578 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900579 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineceb54c62017-04-18 14:22:25 +0900580 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900581
582 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900583 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900584 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900585 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900586 verifyNoMoreInteractions(mWifiManager);
587 verifyNoMoreInteractions(mConnectivityManager);
588 verifyNoMoreInteractions(mNMService);
589
590 // Emulate externally-visible WifiManager effects, causing the
591 // per-interface state machine to start up, and telling us that
592 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900593 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900594 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900595 mLooper.dispatchAll();
596
Erik Kline9e225542017-06-08 17:48:48 +0900597 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900598 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900599 verifyNoMoreInteractions(mConnectivityManager);
600 verifyNoMoreInteractions(mNMService);
601 verifyNoMoreInteractions(mWifiManager);
602 }
603
Erik Klinea9cde8b2017-06-20 21:18:31 +0900604 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900605 @Test
606 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
607 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
608 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
609
610 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900611 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900612 mLooper.dispatchAll();
613 verify(mWifiManager, times(1)).startSoftAp(null);
614 verifyNoMoreInteractions(mWifiManager);
615 verifyNoMoreInteractions(mConnectivityManager);
616 verifyNoMoreInteractions(mNMService);
617
618 // Emulate externally-visible WifiManager effects, causing the
619 // per-interface state machine to start up, and telling us that
620 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900621 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
622 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900623 mLooper.dispatchAll();
624
625 verifyInterfaceServingModeStarted();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900626 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900627 verify(mNMService, times(1)).setIpForwardingEnabled(true);
628 verify(mNMService, times(1)).startTethering(any(String[].class));
629 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900630 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900631 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900632 verifyNoMoreInteractions(mWifiManager);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900633 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_ACTIVE_TETHER);
634 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900635 // In tethering mode, in the default configuration, an explicit request
636 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900637 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900638 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
639 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
640 verifyNoMoreInteractions(mConnectivityManager);
641
642 /////
643 // We do not currently emulate any upstream being found.
644 //
645 // This is why there are no calls to verify mNMService.enableNat() or
646 // mNMService.startInterfaceForwarding().
647 /////
648
649 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900650 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900651 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900652 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900653 verifyNoMoreInteractions(mWifiManager);
654 verifyNoMoreInteractions(mConnectivityManager);
655 verifyNoMoreInteractions(mNMService);
656
657 // Emulate externally-visible WifiManager effects, when tethering mode
658 // is being torn down.
659 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900660 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900661 mLooper.dispatchAll();
662
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900663 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900664 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900665 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900666 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900667 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900668 verify(mNMService, times(1)).stopTethering();
669 verify(mNMService, times(1)).setIpForwardingEnabled(false);
670 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900671 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900672 // Asking for the last error after the per-interface state machine
673 // has been reaped yields an unknown interface error.
674 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900675 mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900676 }
677
Erik Klinea9cde8b2017-06-20 21:18:31 +0900678 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900679 @Test
680 public void failureEnablingIpForwarding() throws Exception {
681 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
682 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
683 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
684
685 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900686 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900687 mLooper.dispatchAll();
688 verify(mWifiManager, times(1)).startSoftAp(null);
689 verifyNoMoreInteractions(mWifiManager);
690 verifyNoMoreInteractions(mConnectivityManager);
691 verifyNoMoreInteractions(mNMService);
692
693 // Emulate externally-visible WifiManager effects, causing the
694 // per-interface state machine to start up, and telling us that
695 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900696 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
697 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900698 mLooper.dispatchAll();
699
Erik Kline1fdc2e22017-05-08 17:56:35 +0900700 // We verify get/set called twice here: once for setup and once during
701 // teardown because all events happen over the course of the single
702 // dispatchAll() above.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900703 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900704 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900705 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
706 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900707 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900708 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900709 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900710 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900711 // This is called, but will throw.
712 verify(mNMService, times(1)).setIpForwardingEnabled(true);
713 // This never gets called because of the exception thrown above.
714 verify(mNMService, times(0)).startTethering(any(String[].class));
715 // When the master state machine transitions to an error state it tells
716 // downstream interfaces, which causes us to tell Wi-Fi about the error
717 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900718 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900719 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900720 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900721
722 verifyNoMoreInteractions(mWifiManager);
723 verifyNoMoreInteractions(mConnectivityManager);
724 verifyNoMoreInteractions(mNMService);
725 }
726
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100727 private void userRestrictionsListenerBehaviour(
728 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
729 int expectedInteractionsWithShowNotification) throws Exception {
730 final int userId = 0;
731 final Bundle currRestrictions = new Bundle();
732 final Bundle newRestrictions = new Bundle();
733 Tethering tethering = mock(Tethering.class);
734 Tethering.TetheringUserRestrictionListener turl =
735 new Tethering.TetheringUserRestrictionListener(tethering);
736
737 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
738 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
739 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
740
741 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
742
743 verify(tethering, times(expectedInteractionsWithShowNotification))
744 .showTetheredNotification(anyInt(), eq(false));
745
746 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
747 }
748
749 @Test
750 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
751 final String[] emptyActiveIfacesList = new String[]{};
752 final boolean currDisallow = false;
753 final boolean nextDisallow = true;
754 final int expectedInteractionsWithShowNotification = 0;
755
756 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
757 expectedInteractionsWithShowNotification);
758 }
759
760 @Test
761 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900762 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100763 final boolean currDisallow = false;
764 final boolean nextDisallow = true;
765 final int expectedInteractionsWithShowNotification = 1;
766
767 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
768 expectedInteractionsWithShowNotification);
769 }
770
771 @Test
772 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
773 final String[] nonEmptyActiveIfacesList = new String[]{};
774 final boolean currDisallow = true;
775 final boolean nextDisallow = false;
776 final int expectedInteractionsWithShowNotification = 0;
777
778 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
779 expectedInteractionsWithShowNotification);
780 }
781
782 @Test
783 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900784 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100785 final boolean currDisallow = true;
786 final boolean nextDisallow = false;
787 final int expectedInteractionsWithShowNotification = 0;
788
789 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
790 expectedInteractionsWithShowNotification);
791 }
792
793 @Test
794 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900795 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100796 final int expectedInteractionsWithShowNotification = 0;
797 boolean currDisallow = true;
798 boolean nextDisallow = true;
799
800 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
801 expectedInteractionsWithShowNotification);
802
803 currDisallow = false;
804 nextDisallow = false;
805
806 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
807 expectedInteractionsWithShowNotification);
808 }
809
810
Erik Kline1fdc2e22017-05-08 17:56:35 +0900811 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900812 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700813}