blob: bca9be77270421be728a5c0bfd7cda6039475e64 [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;
Erik Klinec438e302017-07-04 22:02:49 +090026import static android.net.ConnectivityManager.TETHERING_USB;
markchienb6eb2c22018-07-18 14:29:20 +080027import static android.net.ConnectivityManager.TETHERING_WIFI;
28import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
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.EXTRA_WIFI_AP_INTERFACE_NAME;
31import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
32import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
markchienb6eb2c22018-07-18 14:29:20 +080033import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
34import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
Erik Kline2efb8272017-05-31 15:53:53 +090035import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090036import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090037
Erik Klineea9cc482017-03-10 19:35:34 +090038import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070039import static org.junit.Assert.assertTrue;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090040import static org.mockito.ArgumentMatchers.argThat;
41import static org.mockito.ArgumentMatchers.notNull;
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;
markchienb6eb2c22018-07-18 14:29:20 +080048import static org.mockito.Mockito.mock;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090049import static org.mockito.Mockito.never;
Erik Klineea9cc482017-03-10 19:35:34 +090050import static org.mockito.Mockito.times;
51import static org.mockito.Mockito.verify;
52import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070053import static org.mockito.Mockito.when;
54
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;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090077import android.net.dhcp.DhcpServer;
78import android.net.dhcp.DhcpServingParams;
Erik Kline7a4ccc62018-08-27 17:26:47 +090079import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090080import android.net.ip.RouterAdvertisementDaemon;
81import android.net.util.InterfaceParams;
82import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090083import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090084import android.net.wifi.WifiConfiguration;
85import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010086import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090087import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070088import android.os.INetworkManagementService;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090089import android.os.Looper;
Christopher Wiley497c1472016-10-11 13:26:03 -070090import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090091import android.os.RemoteException;
Erik Klineea9cc482017-03-10 19:35:34 +090092import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010093import android.os.UserManager;
markchienb6eb2c22018-07-18 14:29:20 +080094import android.os.test.TestLooper;
Erik Kline92c4db02017-05-31 10:21:32 +090095import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070096import android.support.test.filters.SmallTest;
97import android.support.test.runner.AndroidJUnit4;
98import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090099import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700100
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900101import com.android.internal.util.ArrayUtils;
102import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900103import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900104import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900105import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900106import com.android.server.connectivity.tethering.OffloadHardwareInterface;
107import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900108import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900109
Erik Kline8351faa2017-04-17 16:47:23 +0900110import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700111import org.junit.Before;
112import org.junit.Test;
113import org.junit.runner.RunWith;
114import org.mockito.Mock;
115import org.mockito.MockitoAnnotations;
116
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900117import java.net.Inet4Address;
118import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900119import java.util.ArrayList;
120import java.util.Vector;
121
Christopher Wiley497c1472016-10-11 13:26:03 -0700122@RunWith(AndroidJUnit4.class)
123@SmallTest
124public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900125 private static final int IFINDEX_OFFSET = 100;
126
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 Klinef3a08b42017-06-07 16:33:19 +0900132 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700133 @Mock private Context mContext;
134 @Mock private INetworkManagementService mNMService;
135 @Mock private INetworkStatsService mStatsService;
136 @Mock private INetworkPolicyManager mPolicyManager;
137 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900138 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700139 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900140 @Mock private UsbManager mUsbManager;
141 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700142 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900143 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
144 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
145 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900146 @Mock private DhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900147 @Mock private INetd mNetd;
148
149 private final MockTetheringDependencies mTetheringDependencies =
150 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700151
152 // Like so many Android system APIs, these cannot be mocked because it is marked final.
153 // We have to use the real versions.
154 private final PersistableBundle mCarrierConfig = new PersistableBundle();
155 private final TestLooper mLooper = new TestLooper();
156
Erik Kline8351faa2017-04-17 16:47:23 +0900157 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900158 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900159 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900160 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700161 private Tethering mTethering;
162
Erik Klineea9cc482017-03-10 19:35:34 +0900163 private class MockContext extends BroadcastInterceptingContext {
164 MockContext(Context base) {
165 super(base);
166 }
167
168 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900169 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
170
171 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900172 public ContentResolver getContentResolver() { return mContentResolver; }
173
174 @Override
175 public String getPackageName() { return "TetheringTest"; }
176
177 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900178 public Resources getResources() { return mResources; }
179
180 @Override
181 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900182 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900183 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900184 return super.getSystemService(name);
185 }
186 }
187
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900188 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900189 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900190 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900191 int isTetheringSupportedCalls;
192
193 public void reset() {
194 upstreamNetworkMonitorMasterSM = null;
195 ipv6CoordinatorNotifyList = null;
196 isTetheringSupportedCalls = 0;
197 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900198
199 @Override
200 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
201 return mOffloadHardwareInterface;
202 }
203
204 @Override
205 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
206 StateMachine target, SharedLog log, int what) {
207 upstreamNetworkMonitorMasterSM = target;
208 return mUpstreamNetworkMonitor;
209 }
210
211 @Override
212 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900213 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900214 ipv6CoordinatorNotifyList = notifyList;
215 return mIPv6TetheringCoordinator;
216 }
217
218 @Override
Erik Kline7a4ccc62018-08-27 17:26:47 +0900219 public IpServer.Dependencies getIpServerDependencies() {
220 return new IpServer.Dependencies() {
221 @Override
222 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
223 InterfaceParams ifParams) {
224 return mRouterAdvertisementDaemon;
225 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900226
Erik Kline7a4ccc62018-08-27 17:26:47 +0900227 @Override
228 public InterfaceParams getInterfaceParams(String ifName) {
229 final String[] ifaces = new String[] {
230 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
231 final int index = ArrayUtils.indexOf(ifaces, ifName);
232 assertTrue("Non-mocked interface: " + ifName, index >= 0);
233 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
234 MacAddress.ALL_ZEROS_ADDRESS);
235 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900236
Erik Kline7a4ccc62018-08-27 17:26:47 +0900237 @Override
238 public INetd getNetdService() {
239 return mNetd;
240 }
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900241
242 @Override
243 public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
244 DhcpServingParams params, SharedLog log) {
245 return mDhcpServer;
246 }
Erik Kline7a4ccc62018-08-27 17:26:47 +0900247 };
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900248 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900249
250 @Override
251 public boolean isTetheringSupported() {
252 isTetheringSupportedCalls++;
253 return true;
254 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900255 }
256
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900257 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
258 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900259 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900260 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
261 final LinkProperties prop = new LinkProperties();
262 prop.setInterfaceName(TEST_MOBILE_IFNAME);
263
264 if (withIPv4) {
265 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
266 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
267 }
268
269 if (withIPv6) {
270 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
271 prop.addLinkAddress(
272 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
273 NetworkConstants.RFC7421_PREFIX_LENGTH));
274 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
275 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
276 }
277
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900278 if (with464xlat) {
279 final LinkProperties stackedLink = new LinkProperties();
280 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
281 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
282 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
283
284 prop.addStackedLink(stackedLink);
285 }
286
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900287
288 final NetworkCapabilities capabilities = new NetworkCapabilities()
289 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
290 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
291 }
292
293 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900294 return buildMobileUpstreamState(true, false, false);
295 }
296
297 private static NetworkState buildMobileIPv6UpstreamState() {
298 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900299 }
300
301 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900302 return buildMobileUpstreamState(true, true, false);
303 }
304
305 private static NetworkState buildMobile464xlatUpstreamState() {
306 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900307 }
308
Erik Kline8351faa2017-04-17 16:47:23 +0900309 @Before
310 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700311 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700312 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
313 .thenReturn(new String[0]);
314 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900315 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700316 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900317 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700318 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
319 .thenReturn(new String[0]);
320 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
321 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900322 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
323 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900324 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900325 .thenReturn(new String[] {
326 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900327 when(mNMService.getInterfaceConfig(anyString()))
328 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900329 when(mRouterAdvertisementDaemon.start())
330 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900331
332 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900333 mContentResolver = new MockContentResolver(mServiceContext);
334 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900335 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900336 mIntents = new Vector<>();
337 mBroadcastReceiver = new BroadcastReceiver() {
338 @Override
339 public void onReceive(Context context, Intent intent) {
340 mIntents.addElement(intent);
341 }
342 };
343 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900344 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
345 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900346 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900347 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700348 }
349
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900350 private Tethering makeTethering() {
351 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
352 mLooper.getLooper(), mSystemProperties,
353 mTetheringDependencies);
354 }
355
Erik Kline8351faa2017-04-17 16:47:23 +0900356 @After
357 public void tearDown() {
358 mServiceContext.unregisterReceiver(mBroadcastReceiver);
359 }
360
Erik Klineea9cc482017-03-10 19:35:34 +0900361 private void sendWifiApStateChanged(int state) {
362 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900363 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900364 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
365 }
366
Erik Kline2efb8272017-05-31 15:53:53 +0900367 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
368 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
369 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
370 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
371 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
372 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
373 }
374
Erik Klinec438e302017-07-04 22:02:49 +0900375 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
376 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
377 intent.putExtra(USB_CONNECTED, connected);
378 intent.putExtra(USB_CONFIGURED, configured);
379 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
380 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
381 }
382
Erik Kline80b7a9f2018-02-28 15:01:35 +0900383 private void sendConfigurationChanged() {
384 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
385 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
386 }
387
Erik Kline9e225542017-06-08 17:48:48 +0900388 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900389 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900390 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900391 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
392 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900393 }
394
395 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
396 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
397 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900398 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900399 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
400 assertTrue(ifnames.contains(ifname));
401 mIntents.remove(bcast);
402 }
403
Erik Klinea9cde8b2017-06-20 21:18:31 +0900404 public void failingLocalOnlyHotspotLegacyApBroadcast(
405 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900406 // Emulate externally-visible WifiManager effects, causing the
407 // per-interface state machine to start up, and telling us that
408 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900409 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900410 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900411 }
Erik Kline9e225542017-06-08 17:48:48 +0900412 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900413 mLooper.dispatchAll();
414
Erik Kline7a4ccc62018-08-27 17:26:47 +0900415 // If, and only if, Tethering received an interface status changed then
416 // it creates a IpServer and sends out a broadcast indicating that the
417 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900418 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900419 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
420 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900421 }
Erik Kline9e225542017-06-08 17:48:48 +0900422 verifyNoMoreInteractions(mNMService);
423 verifyNoMoreInteractions(mWifiManager);
424 }
425
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900426 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900427 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900428 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
429 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900430
431 // Emulate pressing the USB tethering button in Settings UI.
432 mTethering.startTethering(TETHERING_USB, null, false);
433 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800434 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900435
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900436 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
437 }
438
439 @Test
440 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
441 NetworkState upstreamState = buildMobileIPv4UpstreamState();
442 prepareUsbTethering(upstreamState);
443
Erik Klinec438e302017-07-04 22:02:49 +0900444 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900445 verifyNoMoreInteractions(mNMService);
446
447 // Pretend we then receive USB configured broadcast.
448 sendUsbBroadcast(true, true, true);
449 mLooper.dispatchAll();
450 // Now we should see the start of tethering mechanics (in this case:
451 // tetherMatchingInterfaces() which starts by fetching all interfaces).
452 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900453
454 // UpstreamNetworkMonitor should receive selected upstream
455 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
456 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900457 }
458
459 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900460 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
461 failingLocalOnlyHotspotLegacyApBroadcast(true);
462 }
463
464 @Test
465 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
466 failingLocalOnlyHotspotLegacyApBroadcast(false);
467 }
468
469 public void workingLocalOnlyHotspotEnrichedApBroadcast(
470 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900471 // Emulate externally-visible WifiManager effects, causing the
472 // per-interface state machine to start up, and telling us that
473 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900474 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900475 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900476 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900477 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900478 mLooper.dispatchAll();
479
480 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900481 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900482 verify(mNMService, times(1)).setIpForwardingEnabled(true);
483 verify(mNMService, times(1)).startTethering(any(String[].class));
484 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900485 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900486 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900487 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900488 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
markchiena6c72872018-11-13 18:34:56 +0900489 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900490 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900491 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900492
493 // Emulate externally-visible WifiManager effects, when hotspot mode
494 // is being torn down.
495 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900496 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900497 mLooper.dispatchAll();
498
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900499 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900500 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900501 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900502 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900503 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900504 verify(mNMService, times(1)).stopTethering();
505 verify(mNMService, times(1)).setIpForwardingEnabled(false);
506 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900507 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900508 // Asking for the last error after the per-interface state machine
509 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900510 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900511 }
512
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900513 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900514 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900515 */
516 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
517 // IPv6TetheringCoordinator must have been notified of downstream
518 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
519 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900520 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900521
Erik Kline7a4ccc62018-08-27 17:26:47 +0900522 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900524 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900525 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900526 upstreamState.linkProperties.isIPv6Provisioned()
527 ? ipv6OnlyState.linkProperties
528 : null);
529 }
530 mLooper.dispatchAll();
531 }
532
533 private void runUsbTethering(NetworkState upstreamState) {
534 prepareUsbTethering(upstreamState);
535 sendUsbBroadcast(true, true, true);
536 mLooper.dispatchAll();
537 }
538
539 @Test
540 public void workingMobileUsbTethering_IPv4() throws Exception {
541 NetworkState upstreamState = buildMobileIPv4UpstreamState();
542 runUsbTethering(upstreamState);
543
544 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
545 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
546
547 sendIPv6TetherUpdates(upstreamState);
548 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900549 verify(mDhcpServer, times(1)).start();
550 }
551
552 @Test
553 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
554 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
555 mTethering = makeTethering();
556 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
557 runUsbTethering(upstreamState);
558 sendIPv6TetherUpdates(upstreamState);
559
560 verify(mDhcpServer, never()).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900561 }
562
563 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900564 public void workingMobileUsbTethering_IPv6() throws Exception {
565 NetworkState upstreamState = buildMobileIPv6UpstreamState();
566 runUsbTethering(upstreamState);
567
568 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
569 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
570
571 sendIPv6TetherUpdates(upstreamState);
572 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
573 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
574 }
575
576 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900577 public void workingMobileUsbTethering_DualStack() throws Exception {
578 NetworkState upstreamState = buildMobileDualStackUpstreamState();
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 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900584 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900585
586 sendIPv6TetherUpdates(upstreamState);
587 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
588 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
589 }
590
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900591 @Test
592 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
593 NetworkState upstreamState = buildMobile464xlatUpstreamState();
594 runUsbTethering(upstreamState);
595
596 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
597 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900598 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900599 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
600 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
601 TEST_XLAT_MOBILE_IFNAME);
602
603 sendIPv6TetherUpdates(upstreamState);
604 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
605 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
606 }
607
608 @Test
609 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
610 // Setup IPv6
611 NetworkState upstreamState = buildMobileIPv6UpstreamState();
612 runUsbTethering(upstreamState);
613
614 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900615 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900616 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
617
618 // Then 464xlat comes up
619 upstreamState = buildMobile464xlatUpstreamState();
620 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
621 .thenReturn(upstreamState);
622
623 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
624 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
625 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
626 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
627 0,
628 upstreamState);
629 mLooper.dispatchAll();
630
631 // Forwarding is added for 464xlat
632 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
633 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
634 TEST_XLAT_MOBILE_IFNAME);
635 // Forwarding was not re-added for v6 (still times(1))
636 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
637 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900638 // DHCP not restarted on downstream (still times(1))
639 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900640 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900641
Erik Klineea9cc482017-03-10 19:35:34 +0900642 @Test
Erik Kline72302902018-06-14 17:36:40 +0900643 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
644 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
645 .thenReturn(true);
646 sendConfigurationChanged();
647
648 // Setup IPv6
649 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
650 runUsbTethering(upstreamState);
651
652 // UpstreamNetworkMonitor should choose upstream automatically
653 // (in this specific case: choose the default network).
654 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
655 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
656
657 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
658 }
659
660 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900661 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
662 workingLocalOnlyHotspotEnrichedApBroadcast(true);
663 }
664
665 @Test
666 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
667 workingLocalOnlyHotspotEnrichedApBroadcast(false);
668 }
669
670 // TODO: Test with and without interfaceStatusChanged().
671 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900672 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900673 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900674
675 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900676 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900677 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900678 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900679 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900680 verifyNoMoreInteractions(mNMService);
681
682 // Emulate externally-visible WifiManager effects, causing the
683 // per-interface state machine to start up, and telling us that
684 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900685 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900686 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900687 mLooper.dispatchAll();
688
Erik Kline465ff3a2018-03-09 14:18:02 +0900689 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
690 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900691 verifyNoMoreInteractions(mNMService);
692 verifyNoMoreInteractions(mWifiManager);
693 }
694
Erik Klinea9cde8b2017-06-20 21:18:31 +0900695 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900696 @Test
697 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900698 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
699
700 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900701 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900702 mLooper.dispatchAll();
703 verify(mWifiManager, times(1)).startSoftAp(null);
704 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900705 verifyNoMoreInteractions(mNMService);
706
707 // Emulate externally-visible WifiManager effects, causing the
708 // per-interface state machine to start up, and telling us that
709 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900710 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
711 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900712 mLooper.dispatchAll();
713
714 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900715 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900716 verify(mNMService, times(1)).setIpForwardingEnabled(true);
717 verify(mNMService, times(1)).startTethering(any(String[].class));
718 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900719 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900720 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900721 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900722 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
markchiena6c72872018-11-13 18:34:56 +0900723 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900724 // In tethering mode, in the default configuration, an explicit request
725 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900726 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900727 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900728 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900729
730 /////
731 // We do not currently emulate any upstream being found.
732 //
733 // This is why there are no calls to verify mNMService.enableNat() or
734 // mNMService.startInterfaceForwarding().
735 /////
736
737 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900738 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900739 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900740 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900741 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900742 verifyNoMoreInteractions(mNMService);
743
744 // Emulate externally-visible WifiManager effects, when tethering mode
745 // is being torn down.
746 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900747 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900748 mLooper.dispatchAll();
749
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900750 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900751 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900752 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900753 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900754 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900755 verify(mNMService, times(1)).stopTethering();
756 verify(mNMService, times(1)).setIpForwardingEnabled(false);
757 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900758 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900759 // Asking for the last error after the per-interface state machine
760 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900761 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900762 }
763
Erik Klinea9cde8b2017-06-20 21:18:31 +0900764 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900765 @Test
766 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900767 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
768 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
769
770 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900771 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900772 mLooper.dispatchAll();
773 verify(mWifiManager, times(1)).startSoftAp(null);
774 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900775 verifyNoMoreInteractions(mNMService);
776
777 // Emulate externally-visible WifiManager effects, causing the
778 // per-interface state machine to start up, and telling us that
779 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900780 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
781 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900782 mLooper.dispatchAll();
783
Erik Kline472276a2018-05-18 16:09:24 +0900784 // We verify get/set called thrice here: once for setup and twice during
Erik Kline1fdc2e22017-05-08 17:56:35 +0900785 // teardown because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900786 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900787 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900788 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline472276a2018-05-18 16:09:24 +0900789 verify(mNMService, times(3))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900790 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
791 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900792 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900793 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900794 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
795 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
796 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900797 // This is called, but will throw.
798 verify(mNMService, times(1)).setIpForwardingEnabled(true);
799 // This never gets called because of the exception thrown above.
800 verify(mNMService, times(0)).startTethering(any(String[].class));
801 // When the master state machine transitions to an error state it tells
802 // downstream interfaces, which causes us to tell Wi-Fi about the error
803 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900804 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900805 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900806 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900807
808 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900809 verifyNoMoreInteractions(mNMService);
810 }
811
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100812 private void userRestrictionsListenerBehaviour(
813 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
814 int expectedInteractionsWithShowNotification) throws Exception {
815 final int userId = 0;
816 final Bundle currRestrictions = new Bundle();
817 final Bundle newRestrictions = new Bundle();
818 Tethering tethering = mock(Tethering.class);
819 Tethering.TetheringUserRestrictionListener turl =
820 new Tethering.TetheringUserRestrictionListener(tethering);
821
822 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
823 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
824 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
825
826 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
827
828 verify(tethering, times(expectedInteractionsWithShowNotification))
829 .showTetheredNotification(anyInt(), eq(false));
830
831 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
832 }
833
834 @Test
835 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
836 final String[] emptyActiveIfacesList = new String[]{};
837 final boolean currDisallow = false;
838 final boolean nextDisallow = true;
839 final int expectedInteractionsWithShowNotification = 0;
840
841 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
842 expectedInteractionsWithShowNotification);
843 }
844
845 @Test
846 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900847 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100848 final boolean currDisallow = false;
849 final boolean nextDisallow = true;
850 final int expectedInteractionsWithShowNotification = 1;
851
852 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
853 expectedInteractionsWithShowNotification);
854 }
855
856 @Test
857 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
858 final String[] nonEmptyActiveIfacesList = new String[]{};
859 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 testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() 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 boolean currDisallow = true;
871 final boolean nextDisallow = false;
872 final int expectedInteractionsWithShowNotification = 0;
873
874 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
875 expectedInteractionsWithShowNotification);
876 }
877
878 @Test
879 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900880 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100881 final int expectedInteractionsWithShowNotification = 0;
882 boolean currDisallow = true;
883 boolean nextDisallow = true;
884
885 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
886 expectedInteractionsWithShowNotification);
887
888 currDisallow = false;
889 nextDisallow = false;
890
891 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
892 expectedInteractionsWithShowNotification);
893 }
894
895
Erik Kline1fdc2e22017-05-08 17:56:35 +0900896 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900897 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700898}