blob: 662e0ba3b4c030e2d417eb5d0d892f15d6310203 [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;
Erik Kline465ff3a2018-03-09 14:18:02 +090022import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
23import static android.net.ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY;
24import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
25import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
26import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Erik Klinec438e302017-07-04 22:02:49 +090027import static android.net.ConnectivityManager.TETHERING_WIFI;
28import static android.net.ConnectivityManager.TETHERING_USB;
Erik Kline465ff3a2018-03-09 14:18:02 +090029import static android.net.ConnectivityManager.TYPE_MOBILE;
Erik Kline2efb8272017-05-31 15:53:53 +090030import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
31import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
32import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
33import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
34import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
35import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090036
Erik Klineea9cc482017-03-10 19:35:34 +090037import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070038import static org.junit.Assert.assertTrue;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090039import static org.mockito.ArgumentMatchers.argThat;
40import static org.mockito.ArgumentMatchers.notNull;
Christopher Wiley497c1472016-10-11 13:26:03 -070041import static org.mockito.Matchers.anyBoolean;
Erik Klineea9cc482017-03-10 19:35:34 +090042import static org.mockito.Matchers.anyInt;
43import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070044import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090045import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090046import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090047import static org.mockito.Mockito.doThrow;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090048import static org.mockito.Mockito.never;
Erik Klineea9cc482017-03-10 19:35:34 +090049import static org.mockito.Mockito.times;
50import static org.mockito.Mockito.verify;
51import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070052import static org.mockito.Mockito.when;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010053import static org.mockito.Mockito.mock;
Christopher Wiley497c1472016-10-11 13:26:03 -070054
Erik Kline8351faa2017-04-17 16:47:23 +090055import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090056import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070057import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090058import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090059import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090060import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070061import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090062import android.hardware.usb.UsbManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090063import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070064import android.net.INetworkPolicyManager;
65import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090066import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090067import android.net.IpPrefix;
68import android.net.LinkAddress;
69import android.net.LinkProperties;
70import android.net.MacAddress;
71import android.net.Network;
72import android.net.NetworkCapabilities;
73import android.net.NetworkInfo;
74import android.net.NetworkState;
75import android.net.NetworkUtils;
76import android.net.RouteInfo;
77import android.net.ip.RouterAdvertisementDaemon;
78import android.net.util.InterfaceParams;
79import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090080import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090081import android.net.wifi.WifiConfiguration;
82import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010083import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090084import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070085import android.os.INetworkManagementService;
86import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090087import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070088import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090089import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010090import android.os.UserManager;
Erik Kline92c4db02017-05-31 10:21:32 +090091import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070092import android.support.test.filters.SmallTest;
93import android.support.test.runner.AndroidJUnit4;
94import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090095import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070096
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090097import com.android.internal.util.ArrayUtils;
98import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +090099import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900100import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900101import com.android.server.connectivity.tethering.IControlsTethering;
102import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900103import com.android.server.connectivity.tethering.OffloadHardwareInterface;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900104import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900105import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900106import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900107
Erik Kline8351faa2017-04-17 16:47:23 +0900108import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700109import org.junit.Before;
110import org.junit.Test;
111import org.junit.runner.RunWith;
112import org.mockito.Mock;
113import org.mockito.MockitoAnnotations;
114
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900115import java.net.Inet4Address;
116import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900117import java.util.ArrayList;
118import java.util.Vector;
119
Christopher Wiley497c1472016-10-11 13:26:03 -0700120@RunWith(AndroidJUnit4.class)
121@SmallTest
122public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900123 private static final int IFINDEX_OFFSET = 100;
124
Christopher Wiley497c1472016-10-11 13:26:03 -0700125 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900126 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
127 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
128 private static final String TEST_USB_IFNAME = "test_rndis0";
129 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700130
Erik Klinef3a08b42017-06-07 16:33:19 +0900131 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700132 @Mock private Context mContext;
133 @Mock private INetworkManagementService mNMService;
134 @Mock private INetworkStatsService mStatsService;
135 @Mock private INetworkPolicyManager mPolicyManager;
136 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900137 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700138 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900139 @Mock private UsbManager mUsbManager;
140 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700141 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900142 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
143 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
144 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
145 @Mock private INetd mNetd;
146
147 private final MockTetheringDependencies mTetheringDependencies =
148 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700149
150 // Like so many Android system APIs, these cannot be mocked because it is marked final.
151 // We have to use the real versions.
152 private final PersistableBundle mCarrierConfig = new PersistableBundle();
153 private final TestLooper mLooper = new TestLooper();
154
Erik Kline8351faa2017-04-17 16:47:23 +0900155 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900156 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900157 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900158 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700159 private Tethering mTethering;
160
Erik Klineea9cc482017-03-10 19:35:34 +0900161 private class MockContext extends BroadcastInterceptingContext {
162 MockContext(Context base) {
163 super(base);
164 }
165
166 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900167 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
168
169 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900170 public ContentResolver getContentResolver() { return mContentResolver; }
171
172 @Override
173 public String getPackageName() { return "TetheringTest"; }
174
175 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900176 public Resources getResources() { return mResources; }
177
178 @Override
179 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900180 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900181 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900182 return super.getSystemService(name);
183 }
184 }
185
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900186 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900187 StateMachine upstreamNetworkMonitorMasterSM;
188 ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
189 int isTetheringSupportedCalls;
190
191 public void reset() {
192 upstreamNetworkMonitorMasterSM = null;
193 ipv6CoordinatorNotifyList = null;
194 isTetheringSupportedCalls = 0;
195 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900196
197 @Override
198 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
199 return mOffloadHardwareInterface;
200 }
201
202 @Override
203 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
204 StateMachine target, SharedLog log, int what) {
205 upstreamNetworkMonitorMasterSM = target;
206 return mUpstreamNetworkMonitor;
207 }
208
209 @Override
210 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
211 ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
212 ipv6CoordinatorNotifyList = notifyList;
213 return mIPv6TetheringCoordinator;
214 }
215
216 @Override
217 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
218 return mRouterAdvertisementDaemon;
219 }
220
221 @Override
222 public INetd getNetdService() {
223 return mNetd;
224 }
225
226 @Override
227 public InterfaceParams getInterfaceParams(String ifName) {
228 final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
229 TEST_MOBILE_IFNAME };
230 final int index = ArrayUtils.indexOf(ifaces, ifName);
231 assertTrue("Non-mocked interface: " + ifName, index >= 0);
232 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
233 MacAddress.ALL_ZEROS_ADDRESS);
234 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900235
236 @Override
237 public boolean isTetheringSupported() {
238 isTetheringSupportedCalls++;
239 return true;
240 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900241 }
242
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900243 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
244 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900245 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900246 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
247 final LinkProperties prop = new LinkProperties();
248 prop.setInterfaceName(TEST_MOBILE_IFNAME);
249
250 if (withIPv4) {
251 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
252 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
253 }
254
255 if (withIPv6) {
256 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
257 prop.addLinkAddress(
258 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
259 NetworkConstants.RFC7421_PREFIX_LENGTH));
260 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
261 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
262 }
263
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900264 if (with464xlat) {
265 final LinkProperties stackedLink = new LinkProperties();
266 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
267 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
268 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
269
270 prop.addStackedLink(stackedLink);
271 }
272
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900273
274 final NetworkCapabilities capabilities = new NetworkCapabilities()
275 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
276 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
277 }
278
279 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900280 return buildMobileUpstreamState(true, false, false);
281 }
282
283 private static NetworkState buildMobileIPv6UpstreamState() {
284 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900285 }
286
287 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900288 return buildMobileUpstreamState(true, true, false);
289 }
290
291 private static NetworkState buildMobile464xlatUpstreamState() {
292 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900293 }
294
Erik Kline8351faa2017-04-17 16:47:23 +0900295 @Before
296 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700297 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700298 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
299 .thenReturn(new String[0]);
300 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900301 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700302 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900303 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700304 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
305 .thenReturn(new String[0]);
306 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
307 .thenReturn(new int[0]);
Erik Klineea9cc482017-03-10 19:35:34 +0900308 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900309 .thenReturn(new String[] {
310 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900311 when(mNMService.getInterfaceConfig(anyString()))
312 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900313 when(mRouterAdvertisementDaemon.start())
314 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900315
316 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900317 mContentResolver = new MockContentResolver(mServiceContext);
318 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900319 mIntents = new Vector<>();
320 mBroadcastReceiver = new BroadcastReceiver() {
321 @Override
322 public void onReceive(Context context, Intent intent) {
323 mIntents.addElement(intent);
324 }
325 };
326 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900327 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
328 mTetheringDependencies.reset();
Erik Klineea9cc482017-03-10 19:35:34 +0900329 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900330 mLooper.getLooper(), mSystemProperties,
331 mTetheringDependencies);
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900332 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700333 }
334
Erik Kline8351faa2017-04-17 16:47:23 +0900335 @After
336 public void tearDown() {
337 mServiceContext.unregisterReceiver(mBroadcastReceiver);
338 }
339
Christopher Wiley497c1472016-10-11 13:26:03 -0700340 private void setupForRequiredProvisioning() {
341 // Produce some acceptable looking provision app setting if requested.
342 when(mResources.getStringArray(
343 com.android.internal.R.array.config_mobile_hotspot_provision_app))
344 .thenReturn(PROVISIONING_APP_NAME);
345 // Don't disable tethering provisioning unless requested.
346 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
347 anyBoolean())).thenReturn(false);
348 // Act like the CarrierConfigManager is present and ready unless told otherwise.
349 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
350 .thenReturn(mCarrierConfigManager);
351 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
352 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
353 }
354
355 @Test
356 public void canRequireProvisioning() {
357 setupForRequiredProvisioning();
358 assertTrue(mTethering.isTetherProvisioningRequired());
359 }
360
361 @Test
362 public void toleratesCarrierConfigManagerMissing() {
363 setupForRequiredProvisioning();
364 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
365 .thenReturn(null);
366 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
367 // We therefore still require provisioning.
368 assertTrue(mTethering.isTetherProvisioningRequired());
369 }
370
371 @Test
372 public void toleratesCarrierConfigMissing() {
373 setupForRequiredProvisioning();
374 when(mCarrierConfigManager.getConfig()).thenReturn(null);
375 // We still have a provisioning app configured, so still require provisioning.
376 assertTrue(mTethering.isTetherProvisioningRequired());
377 }
378
379 @Test
380 public void provisioningNotRequiredWhenAppNotFound() {
381 setupForRequiredProvisioning();
382 when(mResources.getStringArray(
383 com.android.internal.R.array.config_mobile_hotspot_provision_app))
384 .thenReturn(null);
385 assertTrue(!mTethering.isTetherProvisioningRequired());
386 when(mResources.getStringArray(
387 com.android.internal.R.array.config_mobile_hotspot_provision_app))
388 .thenReturn(new String[] {"malformedApp"});
389 assertTrue(!mTethering.isTetherProvisioningRequired());
390 }
Erik Klineea9cc482017-03-10 19:35:34 +0900391
392 private void sendWifiApStateChanged(int state) {
393 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900394 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900395 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
396 }
397
Erik Kline2efb8272017-05-31 15:53:53 +0900398 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
399 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
400 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
401 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
402 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
403 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
404 }
405
Erik Klinec438e302017-07-04 22:02:49 +0900406 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
407 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
408 intent.putExtra(USB_CONNECTED, connected);
409 intent.putExtra(USB_CONFIGURED, configured);
410 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
411 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
412 }
413
Erik Kline9e225542017-06-08 17:48:48 +0900414 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900415 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900416 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900417 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
418 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900419 }
420
421 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
422 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
423 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900424 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900425 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
426 assertTrue(ifnames.contains(ifname));
427 mIntents.remove(bcast);
428 }
429
Erik Klinea9cde8b2017-06-20 21:18:31 +0900430 public void failingLocalOnlyHotspotLegacyApBroadcast(
431 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900432 // Emulate externally-visible WifiManager effects, causing the
433 // per-interface state machine to start up, and telling us that
434 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900435 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900436 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900437 }
Erik Kline9e225542017-06-08 17:48:48 +0900438 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900439 mLooper.dispatchAll();
440
Erik Klinea9cde8b2017-06-20 21:18:31 +0900441 // If, and only if, Tethering received an interface status changed
442 // then it creates a TetherInterfaceStateMachine and sends out a
443 // broadcast indicating that the interface is "available".
444 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900445 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
446 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900447 }
Erik Kline9e225542017-06-08 17:48:48 +0900448 verifyNoMoreInteractions(mNMService);
449 verifyNoMoreInteractions(mWifiManager);
450 }
451
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900452 private void prepareUsbTethering(NetworkState upstreamState) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900453 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
454 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900455
456 // Emulate pressing the USB tethering button in Settings UI.
457 mTethering.startTethering(TETHERING_USB, null, false);
458 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800459 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900460
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900461 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
462 }
463
464 @Test
465 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
466 NetworkState upstreamState = buildMobileIPv4UpstreamState();
467 prepareUsbTethering(upstreamState);
468
Erik Klinec438e302017-07-04 22:02:49 +0900469 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900470 verifyNoMoreInteractions(mNMService);
471
472 // Pretend we then receive USB configured broadcast.
473 sendUsbBroadcast(true, true, true);
474 mLooper.dispatchAll();
475 // Now we should see the start of tethering mechanics (in this case:
476 // tetherMatchingInterfaces() which starts by fetching all interfaces).
477 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900478
479 // UpstreamNetworkMonitor should receive selected upstream
480 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
481 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900482 }
483
484 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900485 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
486 failingLocalOnlyHotspotLegacyApBroadcast(true);
487 }
488
489 @Test
490 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
491 failingLocalOnlyHotspotLegacyApBroadcast(false);
492 }
493
494 public void workingLocalOnlyHotspotEnrichedApBroadcast(
495 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900496 // Emulate externally-visible WifiManager effects, causing the
497 // per-interface state machine to start up, and telling us that
498 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900499 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900500 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900501 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900502 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900503 mLooper.dispatchAll();
504
505 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900506 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900507 verify(mNMService, times(1)).setIpForwardingEnabled(true);
508 verify(mNMService, times(1)).startTethering(any(String[].class));
509 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900510 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900511 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900512 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900513 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900514 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900515 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900516 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900517
518 // Emulate externally-visible WifiManager effects, when hotspot mode
519 // is being torn down.
520 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900521 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900522 mLooper.dispatchAll();
523
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900524 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900525 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900526 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900527 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900528 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900529 verify(mNMService, times(1)).stopTethering();
530 verify(mNMService, times(1)).setIpForwardingEnabled(false);
531 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900532 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900533 // Asking for the last error after the per-interface state machine
534 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900535 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900536 }
537
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900538 /**
539 * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
540 */
541 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
542 // IPv6TetheringCoordinator must have been notified of downstream
543 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
544 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
545 eq(IControlsTethering.STATE_TETHERED));
546
547 for (TetherInterfaceStateMachine tism :
548 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900549 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900550 tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
551 upstreamState.linkProperties.isIPv6Provisioned()
552 ? ipv6OnlyState.linkProperties
553 : null);
554 }
555 mLooper.dispatchAll();
556 }
557
558 private void runUsbTethering(NetworkState upstreamState) {
559 prepareUsbTethering(upstreamState);
560 sendUsbBroadcast(true, true, true);
561 mLooper.dispatchAll();
562 }
563
564 @Test
565 public void workingMobileUsbTethering_IPv4() throws Exception {
566 NetworkState upstreamState = buildMobileIPv4UpstreamState();
567 runUsbTethering(upstreamState);
568
569 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
570 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
571
572 sendIPv6TetherUpdates(upstreamState);
573 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
574 }
575
576 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900577 public void workingMobileUsbTethering_IPv6() throws Exception {
578 NetworkState upstreamState = buildMobileIPv6UpstreamState();
579 runUsbTethering(upstreamState);
580
581 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
582 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
583
584 sendIPv6TetherUpdates(upstreamState);
585 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
586 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
587 }
588
589 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900590 public void workingMobileUsbTethering_DualStack() throws Exception {
591 NetworkState upstreamState = buildMobileDualStackUpstreamState();
592 runUsbTethering(upstreamState);
593
594 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
595 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
596 verify(mRouterAdvertisementDaemon, times(1)).start();
597
598 sendIPv6TetherUpdates(upstreamState);
599 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
600 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
601 }
602
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900603 @Test
604 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
605 NetworkState upstreamState = buildMobile464xlatUpstreamState();
606 runUsbTethering(upstreamState);
607
608 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
609 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
610 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
611 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
612 TEST_XLAT_MOBILE_IFNAME);
613
614 sendIPv6TetherUpdates(upstreamState);
615 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
616 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
617 }
618
619 @Test
620 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
621 // Setup IPv6
622 NetworkState upstreamState = buildMobileIPv6UpstreamState();
623 runUsbTethering(upstreamState);
624
625 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
626 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
627
628 // Then 464xlat comes up
629 upstreamState = buildMobile464xlatUpstreamState();
630 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
631 .thenReturn(upstreamState);
632
633 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
634 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
635 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
636 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
637 0,
638 upstreamState);
639 mLooper.dispatchAll();
640
641 // Forwarding is added for 464xlat
642 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
643 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
644 TEST_XLAT_MOBILE_IFNAME);
645 // Forwarding was not re-added for v6 (still times(1))
646 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
647 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
648 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900649
Erik Klineea9cc482017-03-10 19:35:34 +0900650 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900651 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
652 workingLocalOnlyHotspotEnrichedApBroadcast(true);
653 }
654
655 @Test
656 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
657 workingLocalOnlyHotspotEnrichedApBroadcast(false);
658 }
659
660 // TODO: Test with and without interfaceStatusChanged().
661 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900662 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900663 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900664
665 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900666 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900667 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900668 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900669 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900670 verifyNoMoreInteractions(mNMService);
671
672 // Emulate externally-visible WifiManager effects, causing the
673 // per-interface state machine to start up, and telling us that
674 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900675 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900676 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900677 mLooper.dispatchAll();
678
Erik Kline465ff3a2018-03-09 14:18:02 +0900679 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
680 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900681 verifyNoMoreInteractions(mNMService);
682 verifyNoMoreInteractions(mWifiManager);
683 }
684
Erik Klinea9cde8b2017-06-20 21:18:31 +0900685 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900686 @Test
687 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900688 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
689
690 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900691 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900692 mLooper.dispatchAll();
693 verify(mWifiManager, times(1)).startSoftAp(null);
694 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900695 verifyNoMoreInteractions(mNMService);
696
697 // Emulate externally-visible WifiManager effects, causing the
698 // per-interface state machine to start up, and telling us that
699 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900700 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
701 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900702 mLooper.dispatchAll();
703
704 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900705 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900706 verify(mNMService, times(1)).setIpForwardingEnabled(true);
707 verify(mNMService, times(1)).startTethering(any(String[].class));
708 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900709 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900710 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900711 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900712 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900713 verify(mUpstreamNetworkMonitor, times(1)).start();
Erik Klineea9cc482017-03-10 19:35:34 +0900714 // In tethering mode, in the default configuration, an explicit request
715 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900716 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900717 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900718 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900719
720 /////
721 // We do not currently emulate any upstream being found.
722 //
723 // This is why there are no calls to verify mNMService.enableNat() or
724 // mNMService.startInterfaceForwarding().
725 /////
726
727 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900728 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900729 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900730 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900731 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900732 verifyNoMoreInteractions(mNMService);
733
734 // Emulate externally-visible WifiManager effects, when tethering mode
735 // is being torn down.
736 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900737 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900738 mLooper.dispatchAll();
739
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900740 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900741 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900742 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900743 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900744 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900745 verify(mNMService, times(1)).stopTethering();
746 verify(mNMService, times(1)).setIpForwardingEnabled(false);
747 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900748 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900749 // Asking for the last error after the per-interface state machine
750 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900751 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, 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 {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900757 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
758 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
759
760 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900761 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900762 mLooper.dispatchAll();
763 verify(mWifiManager, times(1)).startSoftAp(null);
764 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900765 verifyNoMoreInteractions(mNMService);
766
767 // Emulate externally-visible WifiManager effects, causing the
768 // per-interface state machine to start up, and telling us that
769 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900770 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
771 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900772 mLooper.dispatchAll();
773
Erik Kline1fdc2e22017-05-08 17:56:35 +0900774 // We verify get/set called twice here: once for setup and once during
775 // teardown because all events happen over the course of the single
776 // dispatchAll() above.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900777 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900778 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900779 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
780 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900781 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900782 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900783 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
784 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
785 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900786 // This is called, but will throw.
787 verify(mNMService, times(1)).setIpForwardingEnabled(true);
788 // This never gets called because of the exception thrown above.
789 verify(mNMService, times(0)).startTethering(any(String[].class));
790 // When the master state machine transitions to an error state it tells
791 // downstream interfaces, which causes us to tell Wi-Fi about the error
792 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900793 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900794 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900795 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900796
797 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900798 verifyNoMoreInteractions(mNMService);
799 }
800
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100801 private void userRestrictionsListenerBehaviour(
802 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
803 int expectedInteractionsWithShowNotification) throws Exception {
804 final int userId = 0;
805 final Bundle currRestrictions = new Bundle();
806 final Bundle newRestrictions = new Bundle();
807 Tethering tethering = mock(Tethering.class);
808 Tethering.TetheringUserRestrictionListener turl =
809 new Tethering.TetheringUserRestrictionListener(tethering);
810
811 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
812 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
813 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
814
815 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
816
817 verify(tethering, times(expectedInteractionsWithShowNotification))
818 .showTetheredNotification(anyInt(), eq(false));
819
820 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
821 }
822
823 @Test
824 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
825 final String[] emptyActiveIfacesList = new String[]{};
826 final boolean currDisallow = false;
827 final boolean nextDisallow = true;
828 final int expectedInteractionsWithShowNotification = 0;
829
830 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
831 expectedInteractionsWithShowNotification);
832 }
833
834 @Test
835 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900836 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100837 final boolean currDisallow = false;
838 final boolean nextDisallow = true;
839 final int expectedInteractionsWithShowNotification = 1;
840
841 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
842 expectedInteractionsWithShowNotification);
843 }
844
845 @Test
846 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
847 final String[] nonEmptyActiveIfacesList = new String[]{};
848 final boolean currDisallow = true;
849 final boolean nextDisallow = false;
850 final int expectedInteractionsWithShowNotification = 0;
851
852 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
853 expectedInteractionsWithShowNotification);
854 }
855
856 @Test
857 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900858 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100859 final boolean currDisallow = true;
860 final boolean nextDisallow = false;
861 final int expectedInteractionsWithShowNotification = 0;
862
863 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
864 expectedInteractionsWithShowNotification);
865 }
866
867 @Test
868 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900869 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100870 final int expectedInteractionsWithShowNotification = 0;
871 boolean currDisallow = true;
872 boolean nextDisallow = true;
873
874 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
875 expectedInteractionsWithShowNotification);
876
877 currDisallow = false;
878 nextDisallow = false;
879
880 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
881 expectedInteractionsWithShowNotification);
882 }
883
884
Erik Kline1fdc2e22017-05-08 17:56:35 +0900885 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900886 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700887}