blob: 44d8f313f18e035a3f095cdeb505269846308d1c [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 Rotaru9f3bad72017-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;
Erik Kline72302902018-06-14 17:36:40 +090074import android.net.NetworkRequest;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090075import android.net.NetworkState;
76import android.net.NetworkUtils;
77import android.net.RouteInfo;
78import android.net.ip.RouterAdvertisementDaemon;
79import android.net.util.InterfaceParams;
80import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090081import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090082import android.net.wifi.WifiConfiguration;
83import android.net.wifi.WifiManager;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010084import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090085import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070086import android.os.INetworkManagementService;
87import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090088import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070089import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090090import android.os.UserHandle;
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +010091import android.os.UserManager;
Erik Kline92c4db02017-05-31 10:21:32 +090092import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070093import android.support.test.filters.SmallTest;
94import android.support.test.runner.AndroidJUnit4;
95import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090096import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070097
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090098import com.android.internal.util.ArrayUtils;
99import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900100import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900101import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900102import com.android.server.connectivity.tethering.IControlsTethering;
103import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900104import com.android.server.connectivity.tethering.OffloadHardwareInterface;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900105import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900106import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900107import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900108
Erik Kline8351faa2017-04-17 16:47:23 +0900109import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700110import org.junit.Before;
111import org.junit.Test;
112import org.junit.runner.RunWith;
113import org.mockito.Mock;
114import org.mockito.MockitoAnnotations;
115
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900116import java.net.Inet4Address;
117import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900118import java.util.ArrayList;
119import java.util.Vector;
120
Christopher Wiley497c1472016-10-11 13:26:03 -0700121@RunWith(AndroidJUnit4.class)
122@SmallTest
123public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900124 private static final int IFINDEX_OFFSET = 100;
125
Christopher Wiley497c1472016-10-11 13:26:03 -0700126 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900127 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
128 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
129 private static final String TEST_USB_IFNAME = "test_rndis0";
130 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700131
Erik Kline72302902018-06-14 17:36:40 +0900132 // Actual contents of the request don't matter for this test. The lack of
133 // any specific TRANSPORT_* is sufficient to identify this request.
134 private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();
135
Erik Klinef3a08b42017-06-07 16:33:19 +0900136 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700137 @Mock private Context mContext;
138 @Mock private INetworkManagementService mNMService;
139 @Mock private INetworkStatsService mStatsService;
140 @Mock private INetworkPolicyManager mPolicyManager;
141 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900142 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700143 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900144 @Mock private UsbManager mUsbManager;
145 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700146 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900147 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
148 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
149 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
150 @Mock private INetd mNetd;
151
152 private final MockTetheringDependencies mTetheringDependencies =
153 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700154
155 // Like so many Android system APIs, these cannot be mocked because it is marked final.
156 // We have to use the real versions.
157 private final PersistableBundle mCarrierConfig = new PersistableBundle();
158 private final TestLooper mLooper = new TestLooper();
159
Erik Kline8351faa2017-04-17 16:47:23 +0900160 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900161 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900162 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900163 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700164 private Tethering mTethering;
165
Erik Klineea9cc482017-03-10 19:35:34 +0900166 private class MockContext extends BroadcastInterceptingContext {
167 MockContext(Context base) {
168 super(base);
169 }
170
171 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900172 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
173
174 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900175 public ContentResolver getContentResolver() { return mContentResolver; }
176
177 @Override
178 public String getPackageName() { return "TetheringTest"; }
179
180 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900181 public Resources getResources() { return mResources; }
182
183 @Override
184 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900185 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900186 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900187 return super.getSystemService(name);
188 }
189 }
190
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900191 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900192 StateMachine upstreamNetworkMonitorMasterSM;
193 ArrayList<TetherInterfaceStateMachine> ipv6CoordinatorNotifyList;
194 int isTetheringSupportedCalls;
195
196 public void reset() {
197 upstreamNetworkMonitorMasterSM = null;
198 ipv6CoordinatorNotifyList = null;
199 isTetheringSupportedCalls = 0;
200 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900201
202 @Override
203 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
204 return mOffloadHardwareInterface;
205 }
206
207 @Override
208 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
209 StateMachine target, SharedLog log, int what) {
210 upstreamNetworkMonitorMasterSM = target;
211 return mUpstreamNetworkMonitor;
212 }
213
214 @Override
215 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
216 ArrayList<TetherInterfaceStateMachine> notifyList, SharedLog log) {
217 ipv6CoordinatorNotifyList = notifyList;
218 return mIPv6TetheringCoordinator;
219 }
220
221 @Override
222 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
223 return mRouterAdvertisementDaemon;
224 }
225
226 @Override
227 public INetd getNetdService() {
228 return mNetd;
229 }
230
231 @Override
232 public InterfaceParams getInterfaceParams(String ifName) {
233 final String[] ifaces = new String[] { TEST_USB_IFNAME, TEST_WLAN_IFNAME,
234 TEST_MOBILE_IFNAME };
235 final int index = ArrayUtils.indexOf(ifaces, ifName);
236 assertTrue("Non-mocked interface: " + ifName, index >= 0);
237 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
238 MacAddress.ALL_ZEROS_ADDRESS);
239 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900240
241 @Override
242 public boolean isTetheringSupported() {
243 isTetheringSupportedCalls++;
244 return true;
245 }
Erik Kline72302902018-06-14 17:36:40 +0900246
247 @Override
248 public NetworkRequest getDefaultNetworkRequest() {
249 return mDefaultRequest;
250 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900251 }
252
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900253 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
254 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900255 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900256 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
257 final LinkProperties prop = new LinkProperties();
258 prop.setInterfaceName(TEST_MOBILE_IFNAME);
259
260 if (withIPv4) {
261 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
262 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
263 }
264
265 if (withIPv6) {
266 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
267 prop.addLinkAddress(
268 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
269 NetworkConstants.RFC7421_PREFIX_LENGTH));
270 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
271 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
272 }
273
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900274 if (with464xlat) {
275 final LinkProperties stackedLink = new LinkProperties();
276 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
277 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
278 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
279
280 prop.addStackedLink(stackedLink);
281 }
282
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900283
284 final NetworkCapabilities capabilities = new NetworkCapabilities()
285 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
286 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
287 }
288
289 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900290 return buildMobileUpstreamState(true, false, false);
291 }
292
293 private static NetworkState buildMobileIPv6UpstreamState() {
294 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900295 }
296
297 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900298 return buildMobileUpstreamState(true, true, false);
299 }
300
301 private static NetworkState buildMobile464xlatUpstreamState() {
302 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900303 }
304
Erik Kline8351faa2017-04-17 16:47:23 +0900305 @Before
306 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700307 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700308 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
309 .thenReturn(new String[0]);
310 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900311 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700312 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900313 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700314 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
315 .thenReturn(new String[0]);
316 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
317 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900318 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
319 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900320 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900321 .thenReturn(new String[] {
322 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900323 when(mNMService.getInterfaceConfig(anyString()))
324 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900325 when(mRouterAdvertisementDaemon.start())
326 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900327
328 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900329 mContentResolver = new MockContentResolver(mServiceContext);
330 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900331 mIntents = new Vector<>();
332 mBroadcastReceiver = new BroadcastReceiver() {
333 @Override
334 public void onReceive(Context context, Intent intent) {
335 mIntents.addElement(intent);
336 }
337 };
338 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900339 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
340 mTetheringDependencies.reset();
Erik Klineea9cc482017-03-10 19:35:34 +0900341 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900342 mLooper.getLooper(), mSystemProperties,
343 mTetheringDependencies);
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900344 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700345 }
346
Erik Kline8351faa2017-04-17 16:47:23 +0900347 @After
348 public void tearDown() {
349 mServiceContext.unregisterReceiver(mBroadcastReceiver);
350 }
351
Christopher Wiley497c1472016-10-11 13:26:03 -0700352 private void setupForRequiredProvisioning() {
353 // Produce some acceptable looking provision app setting if requested.
354 when(mResources.getStringArray(
355 com.android.internal.R.array.config_mobile_hotspot_provision_app))
356 .thenReturn(PROVISIONING_APP_NAME);
357 // Don't disable tethering provisioning unless requested.
358 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
359 anyBoolean())).thenReturn(false);
360 // Act like the CarrierConfigManager is present and ready unless told otherwise.
361 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
362 .thenReturn(mCarrierConfigManager);
363 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
364 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
365 }
366
367 @Test
368 public void canRequireProvisioning() {
369 setupForRequiredProvisioning();
Erik Klinee0f34032018-02-28 15:01:35 +0900370 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700371 assertTrue(mTethering.isTetherProvisioningRequired());
372 }
373
374 @Test
375 public void toleratesCarrierConfigManagerMissing() {
376 setupForRequiredProvisioning();
377 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
378 .thenReturn(null);
Erik Klinee0f34032018-02-28 15:01:35 +0900379 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700380 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
381 // We therefore still require provisioning.
382 assertTrue(mTethering.isTetherProvisioningRequired());
383 }
384
385 @Test
386 public void toleratesCarrierConfigMissing() {
387 setupForRequiredProvisioning();
388 when(mCarrierConfigManager.getConfig()).thenReturn(null);
Erik Klinee0f34032018-02-28 15:01:35 +0900389 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700390 // We still have a provisioning app configured, so still require provisioning.
391 assertTrue(mTethering.isTetherProvisioningRequired());
392 }
393
394 @Test
395 public void provisioningNotRequiredWhenAppNotFound() {
396 setupForRequiredProvisioning();
397 when(mResources.getStringArray(
398 com.android.internal.R.array.config_mobile_hotspot_provision_app))
399 .thenReturn(null);
400 assertTrue(!mTethering.isTetherProvisioningRequired());
401 when(mResources.getStringArray(
402 com.android.internal.R.array.config_mobile_hotspot_provision_app))
403 .thenReturn(new String[] {"malformedApp"});
404 assertTrue(!mTethering.isTetherProvisioningRequired());
405 }
Erik Klineea9cc482017-03-10 19:35:34 +0900406
407 private void sendWifiApStateChanged(int state) {
408 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900409 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900410 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
411 }
412
Erik Kline2efb8272017-05-31 15:53:53 +0900413 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
414 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
415 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
416 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
417 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
418 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
419 }
420
Erik Klinec438e302017-07-04 22:02:49 +0900421 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
422 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
423 intent.putExtra(USB_CONNECTED, connected);
424 intent.putExtra(USB_CONFIGURED, configured);
425 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
426 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
427 }
428
Erik Klinee0f34032018-02-28 15:01:35 +0900429 private void sendConfigurationChanged() {
430 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
431 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
432 }
433
Erik Kline9e225542017-06-08 17:48:48 +0900434 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900435 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900436 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900437 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
438 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900439 }
440
441 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
442 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
443 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900444 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900445 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
446 assertTrue(ifnames.contains(ifname));
447 mIntents.remove(bcast);
448 }
449
Erik Klinea9cde8b2017-06-20 21:18:31 +0900450 public void failingLocalOnlyHotspotLegacyApBroadcast(
451 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900452 // Emulate externally-visible WifiManager effects, causing the
453 // per-interface state machine to start up, and telling us that
454 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900455 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900456 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900457 }
Erik Kline9e225542017-06-08 17:48:48 +0900458 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900459 mLooper.dispatchAll();
460
Erik Klinea9cde8b2017-06-20 21:18:31 +0900461 // If, and only if, Tethering received an interface status changed
462 // then it creates a TetherInterfaceStateMachine and sends out a
463 // broadcast indicating that the interface is "available".
464 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900465 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
466 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900467 }
Erik Kline9e225542017-06-08 17:48:48 +0900468 verifyNoMoreInteractions(mNMService);
469 verifyNoMoreInteractions(mWifiManager);
470 }
471
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900472 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900473 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900474 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
475 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900476
477 // Emulate pressing the USB tethering button in Settings UI.
478 mTethering.startTethering(TETHERING_USB, null, false);
479 mLooper.dispatchAll();
480 verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
481
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900482 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
483 }
484
485 @Test
486 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
487 NetworkState upstreamState = buildMobileIPv4UpstreamState();
488 prepareUsbTethering(upstreamState);
489
Erik Klinec438e302017-07-04 22:02:49 +0900490 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900491 verifyNoMoreInteractions(mNMService);
492
493 // Pretend we then receive USB configured broadcast.
494 sendUsbBroadcast(true, true, true);
495 mLooper.dispatchAll();
496 // Now we should see the start of tethering mechanics (in this case:
497 // tetherMatchingInterfaces() which starts by fetching all interfaces).
498 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900499
500 // UpstreamNetworkMonitor should receive selected upstream
501 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
502 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900503 }
504
505 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900506 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
507 failingLocalOnlyHotspotLegacyApBroadcast(true);
508 }
509
510 @Test
511 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
512 failingLocalOnlyHotspotLegacyApBroadcast(false);
513 }
514
515 public void workingLocalOnlyHotspotEnrichedApBroadcast(
516 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900517 // Emulate externally-visible WifiManager effects, causing the
518 // per-interface state machine to start up, and telling us that
519 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900520 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900521 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900522 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900524 mLooper.dispatchAll();
525
526 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900527 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900528 verify(mNMService, times(1)).setIpForwardingEnabled(true);
529 verify(mNMService, times(1)).startTethering(any(String[].class));
530 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900531 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900532 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900533 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900534 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
Erik Kline72302902018-06-14 17:36:40 +0900535 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900536 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900537 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900538
539 // Emulate externally-visible WifiManager effects, when hotspot mode
540 // is being torn down.
541 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900542 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900543 mLooper.dispatchAll();
544
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900545 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900546 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900547 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900548 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900549 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900550 verify(mNMService, times(1)).stopTethering();
551 verify(mNMService, times(1)).setIpForwardingEnabled(false);
552 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900553 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900554 // Asking for the last error after the per-interface state machine
555 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900556 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900557 }
558
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900559 /**
560 * Send CMD_IPV6_TETHER_UPDATE to TISMs as would be done by IPv6TetheringCoordinator.
561 */
562 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
563 // IPv6TetheringCoordinator must have been notified of downstream
564 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
565 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
566 eq(IControlsTethering.STATE_TETHERED));
567
568 for (TetherInterfaceStateMachine tism :
569 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900570 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900571 tism.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0,
572 upstreamState.linkProperties.isIPv6Provisioned()
573 ? ipv6OnlyState.linkProperties
574 : null);
575 }
576 mLooper.dispatchAll();
577 }
578
579 private void runUsbTethering(NetworkState upstreamState) {
580 prepareUsbTethering(upstreamState);
581 sendUsbBroadcast(true, true, true);
582 mLooper.dispatchAll();
583 }
584
585 @Test
586 public void workingMobileUsbTethering_IPv4() throws Exception {
587 NetworkState upstreamState = buildMobileIPv4UpstreamState();
588 runUsbTethering(upstreamState);
589
590 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
591 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
592
593 sendIPv6TetherUpdates(upstreamState);
594 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
595 }
596
597 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900598 public void workingMobileUsbTethering_IPv6() throws Exception {
599 NetworkState upstreamState = buildMobileIPv6UpstreamState();
600 runUsbTethering(upstreamState);
601
602 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
603 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
604
605 sendIPv6TetherUpdates(upstreamState);
606 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
607 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
608 }
609
610 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900611 public void workingMobileUsbTethering_DualStack() throws Exception {
612 NetworkState upstreamState = buildMobileDualStackUpstreamState();
613 runUsbTethering(upstreamState);
614
615 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
616 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
617 verify(mRouterAdvertisementDaemon, times(1)).start();
618
619 sendIPv6TetherUpdates(upstreamState);
620 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
621 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
622 }
623
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900624 @Test
625 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
626 NetworkState upstreamState = buildMobile464xlatUpstreamState();
627 runUsbTethering(upstreamState);
628
629 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
630 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
631 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
632 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
633 TEST_XLAT_MOBILE_IFNAME);
634
635 sendIPv6TetherUpdates(upstreamState);
636 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
637 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
638 }
639
640 @Test
641 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
642 // Setup IPv6
643 NetworkState upstreamState = buildMobileIPv6UpstreamState();
644 runUsbTethering(upstreamState);
645
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
649 // Then 464xlat comes up
650 upstreamState = buildMobile464xlatUpstreamState();
651 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
652 .thenReturn(upstreamState);
653
654 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
655 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
656 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
657 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
658 0,
659 upstreamState);
660 mLooper.dispatchAll();
661
662 // Forwarding is added for 464xlat
663 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
664 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
665 TEST_XLAT_MOBILE_IFNAME);
666 // Forwarding was not re-added for v6 (still times(1))
667 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
668 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
669 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900670
Erik Klineea9cc482017-03-10 19:35:34 +0900671 @Test
Erik Kline72302902018-06-14 17:36:40 +0900672 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
673 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
674 .thenReturn(true);
675 sendConfigurationChanged();
676
677 // Setup IPv6
678 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
679 runUsbTethering(upstreamState);
680
681 // UpstreamNetworkMonitor should choose upstream automatically
682 // (in this specific case: choose the default network).
683 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
684 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
685
686 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
687 }
688
689 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900690 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
691 workingLocalOnlyHotspotEnrichedApBroadcast(true);
692 }
693
694 @Test
695 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
696 workingLocalOnlyHotspotEnrichedApBroadcast(false);
697 }
698
699 // TODO: Test with and without interfaceStatusChanged().
700 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900701 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900702 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900703
704 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900705 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900706 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900707 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900708 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900709 verifyNoMoreInteractions(mNMService);
710
711 // Emulate externally-visible WifiManager effects, causing the
712 // per-interface state machine to start up, and telling us that
713 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900714 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900715 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900716 mLooper.dispatchAll();
717
Erik Kline465ff3a2018-03-09 14:18:02 +0900718 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
719 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900720 verifyNoMoreInteractions(mNMService);
721 verifyNoMoreInteractions(mWifiManager);
722 }
723
Erik Klinea9cde8b2017-06-20 21:18:31 +0900724 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900725 @Test
726 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900727 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
728
729 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900730 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900731 mLooper.dispatchAll();
732 verify(mWifiManager, times(1)).startSoftAp(null);
733 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900734 verifyNoMoreInteractions(mNMService);
735
736 // Emulate externally-visible WifiManager effects, causing the
737 // per-interface state machine to start up, and telling us that
738 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900739 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
740 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900741 mLooper.dispatchAll();
742
743 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900744 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900745 verify(mNMService, times(1)).setIpForwardingEnabled(true);
746 verify(mNMService, times(1)).startTethering(any(String[].class));
747 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900748 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900749 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900750 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900751 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
Erik Kline72302902018-06-14 17:36:40 +0900752 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900753 // In tethering mode, in the default configuration, an explicit request
754 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900755 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900756 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900757 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900758
759 /////
760 // We do not currently emulate any upstream being found.
761 //
762 // This is why there are no calls to verify mNMService.enableNat() or
763 // mNMService.startInterfaceForwarding().
764 /////
765
766 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900767 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900768 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900769 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900770 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900771 verifyNoMoreInteractions(mNMService);
772
773 // Emulate externally-visible WifiManager effects, when tethering mode
774 // is being torn down.
775 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900776 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900777 mLooper.dispatchAll();
778
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900779 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900780 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900781 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900782 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900783 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900784 verify(mNMService, times(1)).stopTethering();
785 verify(mNMService, times(1)).setIpForwardingEnabled(false);
786 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900787 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900788 // Asking for the last error after the per-interface state machine
789 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900790 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900791 }
792
Erik Klinea9cde8b2017-06-20 21:18:31 +0900793 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900794 @Test
795 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900796 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
797 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
798
799 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900800 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900801 mLooper.dispatchAll();
802 verify(mWifiManager, times(1)).startSoftAp(null);
803 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900804 verifyNoMoreInteractions(mNMService);
805
806 // Emulate externally-visible WifiManager effects, causing the
807 // per-interface state machine to start up, and telling us that
808 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900809 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
810 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900811 mLooper.dispatchAll();
812
Erik Klinef8bba5b2018-05-18 16:09:24 +0900813 // We verify get/set called thrice here: once for setup and twice during
Erik Kline1fdc2e22017-05-08 17:56:35 +0900814 // teardown because all events happen over the course of the single
Erik Klinef8bba5b2018-05-18 16:09:24 +0900815 // dispatchAll() above. Note that once the TISM IPv4 address config
816 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900817 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klinef8bba5b2018-05-18 16:09:24 +0900818 verify(mNMService, times(3))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900819 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
820 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900821 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900822 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900823 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
824 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
825 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900826 // This is called, but will throw.
827 verify(mNMService, times(1)).setIpForwardingEnabled(true);
828 // This never gets called because of the exception thrown above.
829 verify(mNMService, times(0)).startTethering(any(String[].class));
830 // When the master state machine transitions to an error state it tells
831 // downstream interfaces, which causes us to tell Wi-Fi about the error
832 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900833 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900834 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900835 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900836
837 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900838 verifyNoMoreInteractions(mNMService);
839 }
840
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100841 private void userRestrictionsListenerBehaviour(
842 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
843 int expectedInteractionsWithShowNotification) throws Exception {
844 final int userId = 0;
845 final Bundle currRestrictions = new Bundle();
846 final Bundle newRestrictions = new Bundle();
847 Tethering tethering = mock(Tethering.class);
848 Tethering.TetheringUserRestrictionListener turl =
849 new Tethering.TetheringUserRestrictionListener(tethering);
850
851 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
852 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
853 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
854
855 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
856
857 verify(tethering, times(expectedInteractionsWithShowNotification))
858 .showTetheredNotification(anyInt(), eq(false));
859
860 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
861 }
862
863 @Test
864 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
865 final String[] emptyActiveIfacesList = new String[]{};
866 final boolean currDisallow = false;
867 final boolean nextDisallow = true;
868 final int expectedInteractionsWithShowNotification = 0;
869
870 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
871 expectedInteractionsWithShowNotification);
872 }
873
874 @Test
875 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900876 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100877 final boolean currDisallow = false;
878 final boolean nextDisallow = true;
879 final int expectedInteractionsWithShowNotification = 1;
880
881 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
882 expectedInteractionsWithShowNotification);
883 }
884
885 @Test
886 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
887 final String[] nonEmptyActiveIfacesList = new String[]{};
888 final boolean currDisallow = true;
889 final boolean nextDisallow = false;
890 final int expectedInteractionsWithShowNotification = 0;
891
892 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
893 expectedInteractionsWithShowNotification);
894 }
895
896 @Test
897 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900898 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100899 final boolean currDisallow = true;
900 final boolean nextDisallow = false;
901 final int expectedInteractionsWithShowNotification = 0;
902
903 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
904 expectedInteractionsWithShowNotification);
905 }
906
907 @Test
908 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900909 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotaru9f3bad72017-07-18 16:49:22 +0100910 final int expectedInteractionsWithShowNotification = 0;
911 boolean currDisallow = true;
912 boolean nextDisallow = true;
913
914 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
915 expectedInteractionsWithShowNotification);
916
917 currDisallow = false;
918 nextDisallow = false;
919
920 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
921 expectedInteractionsWithShowNotification);
922 }
923
924
Erik Kline1fdc2e22017-05-08 17:56:35 +0900925 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900926 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700927}