blob: d010f14ffa29d165f882cc803858b465700c1b4a [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;
Christopher Wiley497c1472016-10-11 13:26:03 -070032import static org.junit.Assert.assertTrue;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090033import static org.mockito.ArgumentMatchers.argThat;
34import static org.mockito.ArgumentMatchers.notNull;
Christopher Wiley497c1472016-10-11 13:26:03 -070035import static org.mockito.Matchers.anyBoolean;
Erik Klineea9cc482017-03-10 19:35:34 +090036import static org.mockito.Matchers.anyInt;
37import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070038import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090039import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090040import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090041import static org.mockito.Mockito.doThrow;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090042import static org.mockito.Mockito.never;
Erik Klineea9cc482017-03-10 19:35:34 +090043import static org.mockito.Mockito.times;
44import static org.mockito.Mockito.verify;
45import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070046import static org.mockito.Mockito.when;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010047import static org.mockito.Mockito.mock;
Christopher Wiley497c1472016-10-11 13:26:03 -070048
Erik Kline8351faa2017-04-17 16:47:23 +090049import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090050import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070051import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090052import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090053import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090054import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070055import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090056import android.hardware.usb.UsbManager;
57import android.net.ConnectivityManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090058import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070059import android.net.INetworkPolicyManager;
60import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090061import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090062import android.net.IpPrefix;
63import android.net.LinkAddress;
64import android.net.LinkProperties;
65import android.net.MacAddress;
66import android.net.Network;
67import android.net.NetworkCapabilities;
68import android.net.NetworkInfo;
69import android.net.NetworkState;
70import android.net.NetworkUtils;
71import android.net.RouteInfo;
72import android.net.ip.RouterAdvertisementDaemon;
73import android.net.util.InterfaceParams;
74import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090075import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090076import android.net.wifi.WifiConfiguration;
77import android.net.wifi.WifiManager;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010078import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090079import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070080import android.os.INetworkManagementService;
81import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090082import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070083import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090084import android.os.UserHandle;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010085import android.os.UserManager;
Erik Kline92c4db02017-05-31 10:21:32 +090086import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070087import android.support.test.filters.SmallTest;
88import android.support.test.runner.AndroidJUnit4;
89import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090090import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070091
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090092import com.android.internal.util.ArrayUtils;
93import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +090094import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +090095import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090096import com.android.server.connectivity.tethering.IControlsTethering;
97import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +090098import com.android.server.connectivity.tethering.OffloadHardwareInterface;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090099import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900100import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900101import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900102
Erik Kline8351faa2017-04-17 16:47:23 +0900103import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700104import org.junit.Before;
105import org.junit.Test;
106import org.junit.runner.RunWith;
107import org.mockito.Mock;
108import org.mockito.MockitoAnnotations;
109
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900110import java.net.Inet4Address;
111import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900112import java.util.ArrayList;
113import java.util.Vector;
114
Christopher Wiley497c1472016-10-11 13:26:03 -0700115@RunWith(AndroidJUnit4.class)
116@SmallTest
117public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900118 private static final int IFINDEX_OFFSET = 100;
119
Christopher Wiley497c1472016-10-11 13:26:03 -0700120 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900121 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
122 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
123 private static final String TEST_USB_IFNAME = "test_rndis0";
124 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700125
Erik Klinef3a08b42017-06-07 16:33:19 +0900126 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700127 @Mock private Context mContext;
Erik Klineea9cc482017-03-10 19:35:34 +0900128 @Mock private ConnectivityManager mConnectivityManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700129 @Mock private INetworkManagementService mNMService;
130 @Mock private INetworkStatsService mStatsService;
131 @Mock private INetworkPolicyManager mPolicyManager;
132 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900133 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700134 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900135 @Mock private UsbManager mUsbManager;
136 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700137 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900138 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
139 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
140 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
141 @Mock private INetd mNetd;
142
143 private final MockTetheringDependencies mTetheringDependencies =
144 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700145
146 // Like so many Android system APIs, these cannot be mocked because it is marked final.
147 // We have to use the real versions.
148 private final PersistableBundle mCarrierConfig = new PersistableBundle();
149 private final TestLooper mLooper = new TestLooper();
150
Erik Kline8351faa2017-04-17 16:47:23 +0900151 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900152 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900153 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900154 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700155 private Tethering mTethering;
156
Erik Klineea9cc482017-03-10 19:35:34 +0900157 private class MockContext extends BroadcastInterceptingContext {
158 MockContext(Context base) {
159 super(base);
160 }
161
162 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900163 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
164
165 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900166 public ContentResolver getContentResolver() { return mContentResolver; }
167
168 @Override
169 public String getPackageName() { return "TetheringTest"; }
170
171 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900172 public Resources getResources() { return mResources; }
173
174 @Override
175 public Object getSystemService(String name) {
176 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
177 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900178 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900179 return super.getSystemService(name);
180 }
181 }
182
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900183 public class MockTetheringDependencies extends TetheringDependencies {
184 private StateMachine upstreamNetworkMonitorMasterSM;
185 private ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
186
187 @Override
188 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
189 return mOffloadHardwareInterface;
190 }
191
192 @Override
193 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
194 StateMachine target, SharedLog log, int what) {
195 upstreamNetworkMonitorMasterSM = target;
196 return mUpstreamNetworkMonitor;
197 }
198
199 @Override
200 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
201 ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
202 ipv6CoordinatorNotifyList = notifyList;
203 return mIPv6TetheringCoordinator;
204 }
205
206 @Override
207 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
208 return mRouterAdvertisementDaemon;
209 }
210
211 @Override
212 public INetd getNetdService() {
213 return mNetd;
214 }
215
216 @Override
217 public InterfaceParams getInterfaceParams(String ifName) {
218 final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
219 TEST_MOBILE_IFNAME };
220 final int index = ArrayUtils.indexOf(ifaces, ifName);
221 assertTrue("Non-mocked interface: " + ifName, index >= 0);
222 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
223 MacAddress.ALL_ZEROS_ADDRESS);
224 }
225 }
226
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900227 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
228 boolean with464xlat) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900229 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
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900248 if (with464xlat) {
249 final LinkProperties stackedLink = new LinkProperties();
250 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
251 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
252 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
253
254 prop.addStackedLink(stackedLink);
255 }
256
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900257
258 final NetworkCapabilities capabilities = new NetworkCapabilities()
259 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
260 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
261 }
262
263 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900264 return buildMobileUpstreamState(true, false, false);
265 }
266
267 private static NetworkState buildMobileIPv6UpstreamState() {
268 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900269 }
270
271 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900272 return buildMobileUpstreamState(true, true, false);
273 }
274
275 private static NetworkState buildMobile464xlatUpstreamState() {
276 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900277 }
278
Erik Kline8351faa2017-04-17 16:47:23 +0900279 @Before
280 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700281 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700282 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
283 .thenReturn(new String[0]);
284 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900285 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700286 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900287 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700288 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
289 .thenReturn(new String[0]);
290 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
291 .thenReturn(new int[0]);
Erik Klineea9cc482017-03-10 19:35:34 +0900292 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900293 .thenReturn(new String[] {
294 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900295 when(mNMService.getInterfaceConfig(anyString()))
296 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900297 when(mRouterAdvertisementDaemon.start())
298 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900299
300 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900301 mContentResolver = new MockContentResolver(mServiceContext);
302 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900303 mIntents = new Vector<>();
304 mBroadcastReceiver = new BroadcastReceiver() {
305 @Override
306 public void onReceive(Context context, Intent intent) {
307 mIntents.addElement(intent);
308 }
309 };
310 mServiceContext.registerReceiver(mBroadcastReceiver,
311 new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
Erik Klineea9cc482017-03-10 19:35:34 +0900312 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900313 mLooper.getLooper(), mSystemProperties,
314 mTetheringDependencies);
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900315 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700316 }
317
Erik Kline8351faa2017-04-17 16:47:23 +0900318 @After
319 public void tearDown() {
320 mServiceContext.unregisterReceiver(mBroadcastReceiver);
321 }
322
Christopher Wiley497c1472016-10-11 13:26:03 -0700323 private void setupForRequiredProvisioning() {
324 // Produce some acceptable looking provision app setting if requested.
325 when(mResources.getStringArray(
326 com.android.internal.R.array.config_mobile_hotspot_provision_app))
327 .thenReturn(PROVISIONING_APP_NAME);
328 // Don't disable tethering provisioning unless requested.
329 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
330 anyBoolean())).thenReturn(false);
331 // Act like the CarrierConfigManager is present and ready unless told otherwise.
332 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
333 .thenReturn(mCarrierConfigManager);
334 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
335 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
336 }
337
338 @Test
339 public void canRequireProvisioning() {
340 setupForRequiredProvisioning();
341 assertTrue(mTethering.isTetherProvisioningRequired());
342 }
343
344 @Test
345 public void toleratesCarrierConfigManagerMissing() {
346 setupForRequiredProvisioning();
347 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
348 .thenReturn(null);
349 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
350 // We therefore still require provisioning.
351 assertTrue(mTethering.isTetherProvisioningRequired());
352 }
353
354 @Test
355 public void toleratesCarrierConfigMissing() {
356 setupForRequiredProvisioning();
357 when(mCarrierConfigManager.getConfig()).thenReturn(null);
358 // We still have a provisioning app configured, so still require provisioning.
359 assertTrue(mTethering.isTetherProvisioningRequired());
360 }
361
362 @Test
363 public void provisioningNotRequiredWhenAppNotFound() {
364 setupForRequiredProvisioning();
365 when(mResources.getStringArray(
366 com.android.internal.R.array.config_mobile_hotspot_provision_app))
367 .thenReturn(null);
368 assertTrue(!mTethering.isTetherProvisioningRequired());
369 when(mResources.getStringArray(
370 com.android.internal.R.array.config_mobile_hotspot_provision_app))
371 .thenReturn(new String[] {"malformedApp"});
372 assertTrue(!mTethering.isTetherProvisioningRequired());
373 }
Erik Klineea9cc482017-03-10 19:35:34 +0900374
375 private void sendWifiApStateChanged(int state) {
376 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900377 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900378 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
379 }
380
Erik Kline2efb8272017-05-31 15:53:53 +0900381 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
382 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
383 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
384 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
385 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
386 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
387 }
388
Erik Klinec438e302017-07-04 22:02:49 +0900389 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
390 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
391 intent.putExtra(USB_CONNECTED, connected);
392 intent.putExtra(USB_CONFIGURED, configured);
393 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
394 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
395 }
396
Erik Kline9e225542017-06-08 17:48:48 +0900397 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900398 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900399 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900400 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
401 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900402 }
403
404 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
405 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
406 final Intent bcast = mIntents.get(0);
407 assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
408 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
409 assertTrue(ifnames.contains(ifname));
410 mIntents.remove(bcast);
411 }
412
Erik Klinea9cde8b2017-06-20 21:18:31 +0900413 public void failingLocalOnlyHotspotLegacyApBroadcast(
414 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900415 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900416
417 // Emulate externally-visible WifiManager effects, causing the
418 // per-interface state machine to start up, and telling us that
419 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900420 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900421 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900422 }
Erik Kline9e225542017-06-08 17:48:48 +0900423 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900424 mLooper.dispatchAll();
425
Erik Klinea9cde8b2017-06-20 21:18:31 +0900426 // If, and only if, Tethering received an interface status changed
427 // then it creates a TetherInterfaceStateMachine and sends out a
428 // broadcast indicating that the interface is "available".
429 if (emulateInterfaceStatusChanged) {
430 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900431 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900432 }
Erik Kline9e225542017-06-08 17:48:48 +0900433 verifyNoMoreInteractions(mConnectivityManager);
434 verifyNoMoreInteractions(mNMService);
435 verifyNoMoreInteractions(mWifiManager);
436 }
437
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900438 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Klinec438e302017-07-04 22:02:49 +0900439 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900440 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
441 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900442
443 // Emulate pressing the USB tethering button in Settings UI.
444 mTethering.startTethering(TETHERING_USB, null, false);
445 mLooper.dispatchAll();
446 verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
447
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900448 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
449 }
450
451 @Test
452 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
453 NetworkState upstreamState = buildMobileIPv4UpstreamState();
454 prepareUsbTethering(upstreamState);
455
Erik Klinec438e302017-07-04 22:02:49 +0900456 // This should produce no activity of any kind.
457 verifyNoMoreInteractions(mConnectivityManager);
458 verifyNoMoreInteractions(mNMService);
459
460 // Pretend we then receive USB configured broadcast.
461 sendUsbBroadcast(true, true, true);
462 mLooper.dispatchAll();
463 // Now we should see the start of tethering mechanics (in this case:
464 // tetherMatchingInterfaces() which starts by fetching all interfaces).
465 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900466
467 // UpstreamNetworkMonitor should receive selected upstream
468 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
469 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900470 }
471
472 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900473 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
474 failingLocalOnlyHotspotLegacyApBroadcast(true);
475 }
476
477 @Test
478 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
479 failingLocalOnlyHotspotLegacyApBroadcast(false);
480 }
481
482 public void workingLocalOnlyHotspotEnrichedApBroadcast(
483 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900484 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
485
486 // Emulate externally-visible WifiManager effects, causing the
487 // per-interface state machine to start up, and telling us that
488 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900489 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900490 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900491 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900492 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900493 mLooper.dispatchAll();
494
495 verifyInterfaceServingModeStarted();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900496 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900497 verify(mNMService, times(1)).setIpForwardingEnabled(true);
498 verify(mNMService, times(1)).startTethering(any(String[].class));
499 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900500 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900501 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900502 verifyNoMoreInteractions(mWifiManager);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900503 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
504 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900505 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
506 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
507 verifyNoMoreInteractions(mConnectivityManager);
508
509 // Emulate externally-visible WifiManager effects, when hotspot mode
510 // is being torn down.
511 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900512 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900513 mLooper.dispatchAll();
514
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900515 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900516 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900517 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900518 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900519 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900520 verify(mNMService, times(1)).stopTethering();
521 verify(mNMService, times(1)).setIpForwardingEnabled(false);
522 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900523 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900524 // Asking for the last error after the per-interface state machine
525 // has been reaped yields an unknown interface error.
526 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900527 mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900528 }
529
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900530 /**
531 * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
532 */
533 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
534 // IPv6TetheringCoordinator must have been notified of downstream
535 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
536 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
537 eq(IControlsTethering.STATE_TETHERED));
538
539 for (TetherInterfaceStateMachine tism :
540 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900541 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900542 tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
543 upstreamState.linkProperties.isIPv6Provisioned()
544 ? ipv6OnlyState.linkProperties
545 : null);
546 }
547 mLooper.dispatchAll();
548 }
549
550 private void runUsbTethering(NetworkState upstreamState) {
551 prepareUsbTethering(upstreamState);
552 sendUsbBroadcast(true, true, true);
553 mLooper.dispatchAll();
554 }
555
556 @Test
557 public void workingMobileUsbTethering_IPv4() throws Exception {
558 NetworkState upstreamState = buildMobileIPv4UpstreamState();
559 runUsbTethering(upstreamState);
560
561 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
562 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
563
564 sendIPv6TetherUpdates(upstreamState);
565 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
566 }
567
568 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900569 public void workingMobileUsbTethering_IPv6() throws Exception {
570 NetworkState upstreamState = buildMobileIPv6UpstreamState();
571 runUsbTethering(upstreamState);
572
573 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
574 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
575
576 sendIPv6TetherUpdates(upstreamState);
577 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
578 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
579 }
580
581 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900582 public void workingMobileUsbTethering_DualStack() throws Exception {
583 NetworkState upstreamState = buildMobileDualStackUpstreamState();
584 runUsbTethering(upstreamState);
585
586 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
587 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
588 verify(mRouterAdvertisementDaemon, times(1)).start();
589
590 sendIPv6TetherUpdates(upstreamState);
591 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
592 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
593 }
594
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900595 @Test
596 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
597 NetworkState upstreamState = buildMobile464xlatUpstreamState();
598 runUsbTethering(upstreamState);
599
600 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
601 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
602 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
603 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
604 TEST_XLAT_MOBILE_IFNAME);
605
606 sendIPv6TetherUpdates(upstreamState);
607 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
608 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
609 }
610
611 @Test
612 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
613 // Setup IPv6
614 NetworkState upstreamState = buildMobileIPv6UpstreamState();
615 runUsbTethering(upstreamState);
616
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
620 // Then 464xlat comes up
621 upstreamState = buildMobile464xlatUpstreamState();
622 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
623 .thenReturn(upstreamState);
624
625 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
626 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
627 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
628 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
629 0,
630 upstreamState);
631 mLooper.dispatchAll();
632
633 // Forwarding is added for 464xlat
634 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
635 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
636 TEST_XLAT_MOBILE_IFNAME);
637 // Forwarding was not re-added for v6 (still times(1))
638 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
639 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
640 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900641
Erik Klineea9cc482017-03-10 19:35:34 +0900642 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900643 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
644 workingLocalOnlyHotspotEnrichedApBroadcast(true);
645 }
646
647 @Test
648 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
649 workingLocalOnlyHotspotEnrichedApBroadcast(false);
650 }
651
652 // TODO: Test with and without interfaceStatusChanged().
653 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900654 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900655 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineceb54c62017-04-18 14:22:25 +0900656 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900657
658 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900659 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900660 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900661 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900662 verifyNoMoreInteractions(mWifiManager);
663 verifyNoMoreInteractions(mConnectivityManager);
664 verifyNoMoreInteractions(mNMService);
665
666 // Emulate externally-visible WifiManager effects, causing the
667 // per-interface state machine to start up, and telling us that
668 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900669 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900670 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900671 mLooper.dispatchAll();
672
Erik Kline9e225542017-06-08 17:48:48 +0900673 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900674 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900675 verifyNoMoreInteractions(mConnectivityManager);
676 verifyNoMoreInteractions(mNMService);
677 verifyNoMoreInteractions(mWifiManager);
678 }
679
Erik Klinea9cde8b2017-06-20 21:18:31 +0900680 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900681 @Test
682 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
683 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
684 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
685
686 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900687 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900688 mLooper.dispatchAll();
689 verify(mWifiManager, times(1)).startSoftAp(null);
690 verifyNoMoreInteractions(mWifiManager);
691 verifyNoMoreInteractions(mConnectivityManager);
692 verifyNoMoreInteractions(mNMService);
693
694 // Emulate externally-visible WifiManager effects, causing the
695 // per-interface state machine to start up, and telling us that
696 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900697 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
698 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900699 mLooper.dispatchAll();
700
701 verifyInterfaceServingModeStarted();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900702 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900703 verify(mNMService, times(1)).setIpForwardingEnabled(true);
704 verify(mNMService, times(1)).startTethering(any(String[].class));
705 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900706 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900707 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900708 verifyNoMoreInteractions(mWifiManager);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900709 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_ACTIVE_TETHER);
710 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900711 // In tethering mode, in the default configuration, an explicit request
712 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900713 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900714 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
715 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
716 verifyNoMoreInteractions(mConnectivityManager);
717
718 /////
719 // We do not currently emulate any upstream being found.
720 //
721 // This is why there are no calls to verify mNMService.enableNat() or
722 // mNMService.startInterfaceForwarding().
723 /////
724
725 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900726 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900727 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900728 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900729 verifyNoMoreInteractions(mWifiManager);
730 verifyNoMoreInteractions(mConnectivityManager);
731 verifyNoMoreInteractions(mNMService);
732
733 // Emulate externally-visible WifiManager effects, when tethering mode
734 // is being torn down.
735 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900736 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900737 mLooper.dispatchAll();
738
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900739 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900740 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900741 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900742 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900743 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900744 verify(mNMService, times(1)).stopTethering();
745 verify(mNMService, times(1)).setIpForwardingEnabled(false);
746 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900747 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900748 // Asking for the last error after the per-interface state machine
749 // has been reaped yields an unknown interface error.
750 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900751 mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900752 }
753
Erik Klinea9cde8b2017-06-20 21:18:31 +0900754 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900755 @Test
756 public void failureEnablingIpForwarding() throws Exception {
757 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
758 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
759 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
760
761 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900762 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900763 mLooper.dispatchAll();
764 verify(mWifiManager, times(1)).startSoftAp(null);
765 verifyNoMoreInteractions(mWifiManager);
766 verifyNoMoreInteractions(mConnectivityManager);
767 verifyNoMoreInteractions(mNMService);
768
769 // Emulate externally-visible WifiManager effects, causing the
770 // per-interface state machine to start up, and telling us that
771 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900772 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
773 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900774 mLooper.dispatchAll();
775
Erik Kline1fdc2e22017-05-08 17:56:35 +0900776 // We verify get/set called twice here: once for setup and once during
777 // teardown because all events happen over the course of the single
778 // dispatchAll() above.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900779 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900780 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900781 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
782 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900783 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900784 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900785 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900786 verifyTetheringBroadcast(TEST_WLAN_IFNAME, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900787 // This is called, but will throw.
788 verify(mNMService, times(1)).setIpForwardingEnabled(true);
789 // This never gets called because of the exception thrown above.
790 verify(mNMService, times(0)).startTethering(any(String[].class));
791 // When the master state machine transitions to an error state it tells
792 // downstream interfaces, which causes us to tell Wi-Fi about the error
793 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900794 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900795 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900796 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900797
798 verifyNoMoreInteractions(mWifiManager);
799 verifyNoMoreInteractions(mConnectivityManager);
800 verifyNoMoreInteractions(mNMService);
801 }
802
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100803 private void userRestrictionsListenerBehaviour(
804 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
805 int expectedInteractionsWithShowNotification) throws Exception {
806 final int userId = 0;
807 final Bundle currRestrictions = new Bundle();
808 final Bundle newRestrictions = new Bundle();
809 Tethering tethering = mock(Tethering.class);
810 Tethering.TetheringUserRestrictionListener turl =
811 new Tethering.TetheringUserRestrictionListener(tethering);
812
813 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
814 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
815 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
816
817 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
818
819 verify(tethering, times(expectedInteractionsWithShowNotification))
820 .showTetheredNotification(anyInt(), eq(false));
821
822 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
823 }
824
825 @Test
826 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
827 final String[] emptyActiveIfacesList = new String[]{};
828 final boolean currDisallow = false;
829 final boolean nextDisallow = true;
830 final int expectedInteractionsWithShowNotification = 0;
831
832 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
833 expectedInteractionsWithShowNotification);
834 }
835
836 @Test
837 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900838 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100839 final boolean currDisallow = false;
840 final boolean nextDisallow = true;
841 final int expectedInteractionsWithShowNotification = 1;
842
843 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
844 expectedInteractionsWithShowNotification);
845 }
846
847 @Test
848 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
849 final String[] nonEmptyActiveIfacesList = new String[]{};
850 final boolean currDisallow = true;
851 final boolean nextDisallow = false;
852 final int expectedInteractionsWithShowNotification = 0;
853
854 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
855 expectedInteractionsWithShowNotification);
856 }
857
858 @Test
859 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900860 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100861 final boolean currDisallow = true;
862 final boolean nextDisallow = false;
863 final int expectedInteractionsWithShowNotification = 0;
864
865 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
866 expectedInteractionsWithShowNotification);
867 }
868
869 @Test
870 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900871 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100872 final int expectedInteractionsWithShowNotification = 0;
873 boolean currDisallow = true;
874 boolean nextDisallow = true;
875
876 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
877 expectedInteractionsWithShowNotification);
878
879 currDisallow = false;
880 nextDisallow = false;
881
882 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
883 expectedInteractionsWithShowNotification);
884 }
885
886
Erik Kline1fdc2e22017-05-08 17:56:35 +0900887 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900888 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700889}