blob: b6356076db60260638a7bbb8e7424f55218db680 [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;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090030import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
Erik Kline2efb8272017-05-31 15:53:53 +090031import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
32import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
33import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
markchienb6eb2c22018-07-18 14:29:20 +080034import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
35import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
Erik Kline2efb8272017-05-31 15:53:53 +090036import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090037import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090038
Erik Klineea9cc482017-03-10 19:35:34 +090039import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070040import static org.junit.Assert.assertTrue;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090041import static org.junit.Assert.fail;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090042import static org.mockito.ArgumentMatchers.argThat;
43import static org.mockito.ArgumentMatchers.notNull;
Erik Klineea9cc482017-03-10 19:35:34 +090044import static org.mockito.Matchers.anyInt;
45import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070046import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090047import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090048import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090049import static org.mockito.Mockito.doThrow;
markchienb6eb2c22018-07-18 14:29:20 +080050import static org.mockito.Mockito.mock;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090051import static org.mockito.Mockito.never;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090052import static org.mockito.Mockito.spy;
53import static org.mockito.Mockito.timeout;
Erik Klineea9cc482017-03-10 19:35:34 +090054import static org.mockito.Mockito.times;
55import static org.mockito.Mockito.verify;
56import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070057import static org.mockito.Mockito.when;
58
Erik Kline8351faa2017-04-17 16:47:23 +090059import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090060import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070061import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090062import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090063import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090064import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070065import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090066import android.hardware.usb.UsbManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090067import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070068import android.net.INetworkPolicyManager;
69import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090070import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090071import android.net.IpPrefix;
72import android.net.LinkAddress;
73import android.net.LinkProperties;
74import android.net.MacAddress;
75import android.net.Network;
76import android.net.NetworkCapabilities;
77import android.net.NetworkInfo;
78import android.net.NetworkState;
79import android.net.NetworkUtils;
80import android.net.RouteInfo;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090081import android.net.dhcp.DhcpServerCallbacks;
82import android.net.dhcp.DhcpServingParamsParcel;
83import android.net.dhcp.IDhcpServer;
Erik Kline7a4ccc62018-08-27 17:26:47 +090084import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090085import android.net.ip.RouterAdvertisementDaemon;
86import android.net.util.InterfaceParams;
87import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090088import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090089import android.net.wifi.WifiConfiguration;
90import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010091import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090092import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070093import android.os.INetworkManagementService;
94import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090095import android.os.RemoteException;
Erik Klineea9cc482017-03-10 19:35:34 +090096import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010097import android.os.UserManager;
markchienb6eb2c22018-07-18 14:29:20 +080098import android.os.test.TestLooper;
Erik Kline92c4db02017-05-31 10:21:32 +090099import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -0700100import android.support.test.filters.SmallTest;
101import android.support.test.runner.AndroidJUnit4;
102import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +0900103import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700104
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900105import com.android.internal.util.ArrayUtils;
106import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900107import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900108import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900109import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900110import com.android.server.connectivity.tethering.OffloadHardwareInterface;
111import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900112import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900113
Erik Kline8351faa2017-04-17 16:47:23 +0900114import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700115import org.junit.Before;
116import org.junit.Test;
117import org.junit.runner.RunWith;
118import org.mockito.Mock;
119import org.mockito.MockitoAnnotations;
120
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900121import java.net.Inet4Address;
122import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900123import java.util.ArrayList;
124import java.util.Vector;
125
Christopher Wiley497c1472016-10-11 13:26:03 -0700126@RunWith(AndroidJUnit4.class)
127@SmallTest
128public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900129 private static final int IFINDEX_OFFSET = 100;
130
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900131 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
132 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
133 private static final String TEST_USB_IFNAME = "test_rndis0";
134 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700135
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900136 private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
137
Erik Klinef3a08b42017-06-07 16:33:19 +0900138 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700139 @Mock private Context mContext;
140 @Mock private INetworkManagementService mNMService;
141 @Mock private INetworkStatsService mStatsService;
142 @Mock private INetworkPolicyManager mPolicyManager;
143 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900144 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700145 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900146 @Mock private UsbManager mUsbManager;
147 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700148 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900149 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
150 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
151 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900152 @Mock private IDhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900153 @Mock private INetd mNetd;
154
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900155 private final MockIpServerDependencies mIpServerDependencies =
156 spy(new MockIpServerDependencies());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900157 private final MockTetheringDependencies mTetheringDependencies =
158 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700159
160 // Like so many Android system APIs, these cannot be mocked because it is marked final.
161 // We have to use the real versions.
162 private final PersistableBundle mCarrierConfig = new PersistableBundle();
163 private final TestLooper mLooper = new TestLooper();
164
Erik Kline8351faa2017-04-17 16:47:23 +0900165 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900166 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900167 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900168 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700169 private Tethering mTethering;
170
Erik Klineea9cc482017-03-10 19:35:34 +0900171 private class MockContext extends BroadcastInterceptingContext {
172 MockContext(Context base) {
173 super(base);
174 }
175
176 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900177 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
178
179 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900180 public ContentResolver getContentResolver() { return mContentResolver; }
181
182 @Override
183 public String getPackageName() { return "TetheringTest"; }
184
185 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900186 public Resources getResources() { return mResources; }
187
188 @Override
189 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900190 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900191 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900192 return super.getSystemService(name);
193 }
194 }
195
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900196 public class MockIpServerDependencies extends IpServer.Dependencies {
197 MockIpServerDependencies() {
198 super(null);
199 }
200
201 @Override
202 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
203 InterfaceParams ifParams) {
204 return mRouterAdvertisementDaemon;
205 }
206
207 @Override
208 public InterfaceParams getInterfaceParams(String ifName) {
209 assertTrue("Non-mocked interface " + ifName,
210 ifName.equals(TEST_USB_IFNAME)
211 || ifName.equals(TEST_WLAN_IFNAME)
212 || ifName.equals(TEST_MOBILE_IFNAME));
213 final String[] ifaces = new String[] {
214 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
215 return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
216 MacAddress.ALL_ZEROS_ADDRESS);
217 }
218
219 @Override
220 public INetd getNetdService() {
221 return mNetd;
222 }
223
224 @Override
225 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
226 DhcpServerCallbacks cb) {
227 new Thread(() -> {
228 try {
229 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
230 } catch (RemoteException e) {
231 fail(e.getMessage());
232 }
233 }).run();
234 }
235 }
236
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900237 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900238 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900239 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900240 int isTetheringSupportedCalls;
241
242 public void reset() {
243 upstreamNetworkMonitorMasterSM = null;
244 ipv6CoordinatorNotifyList = null;
245 isTetheringSupportedCalls = 0;
246 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900247
248 @Override
249 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
250 return mOffloadHardwareInterface;
251 }
252
253 @Override
254 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
255 StateMachine target, SharedLog log, int what) {
256 upstreamNetworkMonitorMasterSM = target;
257 return mUpstreamNetworkMonitor;
258 }
259
260 @Override
261 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900262 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900263 ipv6CoordinatorNotifyList = notifyList;
264 return mIPv6TetheringCoordinator;
265 }
266
267 @Override
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900268 public IpServer.Dependencies getIpServerDependencies(Context context) {
269 return mIpServerDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900270 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900271
272 @Override
273 public boolean isTetheringSupported() {
274 isTetheringSupportedCalls++;
275 return true;
276 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900277 }
278
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900279 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
280 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900281 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900282 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
283 final LinkProperties prop = new LinkProperties();
284 prop.setInterfaceName(TEST_MOBILE_IFNAME);
285
286 if (withIPv4) {
287 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
288 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
289 }
290
291 if (withIPv6) {
292 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
293 prop.addLinkAddress(
294 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
295 NetworkConstants.RFC7421_PREFIX_LENGTH));
296 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
297 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
298 }
299
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900300 if (with464xlat) {
301 final LinkProperties stackedLink = new LinkProperties();
302 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
303 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
304 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
305
306 prop.addStackedLink(stackedLink);
307 }
308
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900309
310 final NetworkCapabilities capabilities = new NetworkCapabilities()
311 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
312 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
313 }
314
315 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900316 return buildMobileUpstreamState(true, false, false);
317 }
318
319 private static NetworkState buildMobileIPv6UpstreamState() {
320 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900321 }
322
323 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900324 return buildMobileUpstreamState(true, true, false);
325 }
326
327 private static NetworkState buildMobile464xlatUpstreamState() {
328 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900329 }
330
Erik Kline8351faa2017-04-17 16:47:23 +0900331 @Before
332 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700333 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700334 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
335 .thenReturn(new String[0]);
336 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900337 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700338 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900339 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700340 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
341 .thenReturn(new String[0]);
342 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
343 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900344 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
345 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900346 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900347 .thenReturn(new String[] {
348 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900349 when(mNMService.getInterfaceConfig(anyString()))
350 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900351 when(mRouterAdvertisementDaemon.start())
352 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900353
354 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900355 mContentResolver = new MockContentResolver(mServiceContext);
356 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900357 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900358 mIntents = new Vector<>();
359 mBroadcastReceiver = new BroadcastReceiver() {
360 @Override
361 public void onReceive(Context context, Intent intent) {
362 mIntents.addElement(intent);
363 }
364 };
365 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900366 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
367 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900368 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900369 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700370 }
371
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900372 private Tethering makeTethering() {
373 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
374 mLooper.getLooper(), mSystemProperties,
375 mTetheringDependencies);
376 }
377
Erik Kline8351faa2017-04-17 16:47:23 +0900378 @After
379 public void tearDown() {
380 mServiceContext.unregisterReceiver(mBroadcastReceiver);
381 }
382
Erik Klineea9cc482017-03-10 19:35:34 +0900383 private void sendWifiApStateChanged(int state) {
384 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900385 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900386 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
387 }
388
Erik Kline2efb8272017-05-31 15:53:53 +0900389 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
390 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
391 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
392 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
393 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
394 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
395 }
396
Erik Klinec438e302017-07-04 22:02:49 +0900397 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
398 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
399 intent.putExtra(USB_CONNECTED, connected);
400 intent.putExtra(USB_CONFIGURED, configured);
401 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
402 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
403 }
404
Erik Kline80b7a9f2018-02-28 15:01:35 +0900405 private void sendConfigurationChanged() {
406 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
407 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
408 }
409
Erik Kline9e225542017-06-08 17:48:48 +0900410 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900411 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900412 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900413 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
414 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900415 }
416
417 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
418 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
419 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900420 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900421 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
422 assertTrue(ifnames.contains(ifname));
423 mIntents.remove(bcast);
424 }
425
Erik Klinea9cde8b2017-06-20 21:18:31 +0900426 public void failingLocalOnlyHotspotLegacyApBroadcast(
427 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900428 // Emulate externally-visible WifiManager effects, causing the
429 // per-interface state machine to start up, and telling us that
430 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900431 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900432 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900433 }
Erik Kline9e225542017-06-08 17:48:48 +0900434 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900435 mLooper.dispatchAll();
436
Erik Kline7a4ccc62018-08-27 17:26:47 +0900437 // If, and only if, Tethering received an interface status changed then
438 // it creates a IpServer and sends out a broadcast indicating that the
439 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900440 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900441 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
442 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900443 }
Erik Kline9e225542017-06-08 17:48:48 +0900444 verifyNoMoreInteractions(mNMService);
445 verifyNoMoreInteractions(mWifiManager);
446 }
447
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900448 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900449 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900450 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
451 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900452
453 // Emulate pressing the USB tethering button in Settings UI.
454 mTethering.startTethering(TETHERING_USB, null, false);
455 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800456 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900457
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900458 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
459 }
460
461 @Test
462 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
463 NetworkState upstreamState = buildMobileIPv4UpstreamState();
464 prepareUsbTethering(upstreamState);
465
Erik Klinec438e302017-07-04 22:02:49 +0900466 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900467 verifyNoMoreInteractions(mNMService);
468
469 // Pretend we then receive USB configured broadcast.
470 sendUsbBroadcast(true, true, true);
471 mLooper.dispatchAll();
472 // Now we should see the start of tethering mechanics (in this case:
473 // tetherMatchingInterfaces() which starts by fetching all interfaces).
474 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900475
476 // UpstreamNetworkMonitor should receive selected upstream
477 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
478 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900479 }
480
481 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900482 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
483 failingLocalOnlyHotspotLegacyApBroadcast(true);
484 }
485
486 @Test
487 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
488 failingLocalOnlyHotspotLegacyApBroadcast(false);
489 }
490
491 public void workingLocalOnlyHotspotEnrichedApBroadcast(
492 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900493 // Emulate externally-visible WifiManager effects, causing the
494 // per-interface state machine to start up, and telling us that
495 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900496 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900497 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900498 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900499 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900500 mLooper.dispatchAll();
501
502 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900503 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900504 verify(mNMService, times(1)).setIpForwardingEnabled(true);
505 verify(mNMService, times(1)).startTethering(any(String[].class));
506 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900507 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900508 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900509 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900510 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
markchiena6c72872018-11-13 18:34:56 +0900511 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900512 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900513 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900514
515 // Emulate externally-visible WifiManager effects, when hotspot mode
516 // is being torn down.
517 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900518 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900519 mLooper.dispatchAll();
520
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900521 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900522 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900524 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900525 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900526 verify(mNMService, times(1)).stopTethering();
527 verify(mNMService, times(1)).setIpForwardingEnabled(false);
528 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900529 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900530 // Asking for the last error after the per-interface state machine
531 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900532 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900533 }
534
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900535 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900536 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900537 */
538 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
539 // IPv6TetheringCoordinator must have been notified of downstream
540 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
541 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900542 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900543
Erik Kline7a4ccc62018-08-27 17:26:47 +0900544 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900545 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900546 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900547 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900548 upstreamState.linkProperties.isIPv6Provisioned()
549 ? ipv6OnlyState.linkProperties
550 : null);
551 }
552 mLooper.dispatchAll();
553 }
554
555 private void runUsbTethering(NetworkState upstreamState) {
556 prepareUsbTethering(upstreamState);
557 sendUsbBroadcast(true, true, true);
558 mLooper.dispatchAll();
559 }
560
561 @Test
562 public void workingMobileUsbTethering_IPv4() throws Exception {
563 NetworkState upstreamState = buildMobileIPv4UpstreamState();
564 runUsbTethering(upstreamState);
565
566 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
567 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
568
569 sendIPv6TetherUpdates(upstreamState);
570 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900571 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900572 }
573
574 @Test
575 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
576 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
577 mTethering = makeTethering();
578 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
579 runUsbTethering(upstreamState);
580 sendIPv6TetherUpdates(upstreamState);
581
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900582 verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900583 }
584
585 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900586 public void workingMobileUsbTethering_IPv6() throws Exception {
587 NetworkState upstreamState = buildMobileIPv6UpstreamState();
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, times(1)).buildNewRa(any(), notNull());
595 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
596 }
597
598 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900599 public void workingMobileUsbTethering_DualStack() throws Exception {
600 NetworkState upstreamState = buildMobileDualStackUpstreamState();
601 runUsbTethering(upstreamState);
602
603 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
604 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
605 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900606 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900607
608 sendIPv6TetherUpdates(upstreamState);
609 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
610 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
611 }
612
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900613 @Test
614 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
615 NetworkState upstreamState = buildMobile464xlatUpstreamState();
616 runUsbTethering(upstreamState);
617
618 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
619 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900620 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900621 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
622 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
623 TEST_XLAT_MOBILE_IFNAME);
624
625 sendIPv6TetherUpdates(upstreamState);
626 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
627 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
628 }
629
630 @Test
631 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
632 // Setup IPv6
633 NetworkState upstreamState = buildMobileIPv6UpstreamState();
634 runUsbTethering(upstreamState);
635
636 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900637 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900638 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
639
640 // Then 464xlat comes up
641 upstreamState = buildMobile464xlatUpstreamState();
642 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
643 .thenReturn(upstreamState);
644
645 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
646 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
647 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
648 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
649 0,
650 upstreamState);
651 mLooper.dispatchAll();
652
653 // Forwarding is added for 464xlat
654 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
655 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
656 TEST_XLAT_MOBILE_IFNAME);
657 // Forwarding was not re-added for v6 (still times(1))
658 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
659 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900660 // DHCP not restarted on downstream (still times(1))
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900661 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900662 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900663
Erik Klineea9cc482017-03-10 19:35:34 +0900664 @Test
Erik Kline72302902018-06-14 17:36:40 +0900665 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
666 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
667 .thenReturn(true);
668 sendConfigurationChanged();
669
670 // Setup IPv6
671 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
672 runUsbTethering(upstreamState);
673
674 // UpstreamNetworkMonitor should choose upstream automatically
675 // (in this specific case: choose the default network).
676 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
677 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
678
679 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
680 }
681
682 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900683 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
684 workingLocalOnlyHotspotEnrichedApBroadcast(true);
685 }
686
687 @Test
688 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
689 workingLocalOnlyHotspotEnrichedApBroadcast(false);
690 }
691
692 // TODO: Test with and without interfaceStatusChanged().
693 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900694 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900695 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900696
697 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900698 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900699 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900700 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900701 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900702 verifyNoMoreInteractions(mNMService);
703
704 // Emulate externally-visible WifiManager effects, causing the
705 // per-interface state machine to start up, and telling us that
706 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900707 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900708 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900709 mLooper.dispatchAll();
710
Erik Kline465ff3a2018-03-09 14:18:02 +0900711 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
712 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900713 verifyNoMoreInteractions(mNMService);
714 verifyNoMoreInteractions(mWifiManager);
715 }
716
Erik Klinea9cde8b2017-06-20 21:18:31 +0900717 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900718 @Test
719 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900720 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
721
722 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900723 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900724 mLooper.dispatchAll();
725 verify(mWifiManager, times(1)).startSoftAp(null);
726 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900727 verifyNoMoreInteractions(mNMService);
728
729 // Emulate externally-visible WifiManager effects, causing the
730 // per-interface state machine to start up, and telling us that
731 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900732 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
733 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900734 mLooper.dispatchAll();
735
736 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900737 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900738 verify(mNMService, times(1)).setIpForwardingEnabled(true);
739 verify(mNMService, times(1)).startTethering(any(String[].class));
740 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900741 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900742 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900743 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900744 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
markchiena6c72872018-11-13 18:34:56 +0900745 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900746 // In tethering mode, in the default configuration, an explicit request
747 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900748 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900749 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900750 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900751
752 /////
753 // We do not currently emulate any upstream being found.
754 //
755 // This is why there are no calls to verify mNMService.enableNat() or
756 // mNMService.startInterfaceForwarding().
757 /////
758
759 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900760 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900761 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900762 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900763 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900764 verifyNoMoreInteractions(mNMService);
765
766 // Emulate externally-visible WifiManager effects, when tethering mode
767 // is being torn down.
768 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900769 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900770 mLooper.dispatchAll();
771
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900772 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900773 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900774 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900775 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900776 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900777 verify(mNMService, times(1)).stopTethering();
778 verify(mNMService, times(1)).setIpForwardingEnabled(false);
779 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900780 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900781 // Asking for the last error after the per-interface state machine
782 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900783 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900784 }
785
Erik Klinea9cde8b2017-06-20 21:18:31 +0900786 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900787 @Test
788 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900789 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
790 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
791
792 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900793 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900794 mLooper.dispatchAll();
795 verify(mWifiManager, times(1)).startSoftAp(null);
796 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900797 verifyNoMoreInteractions(mNMService);
798
799 // Emulate externally-visible WifiManager effects, causing the
800 // per-interface state machine to start up, and telling us that
801 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900802 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
803 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900804 mLooper.dispatchAll();
805
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900806 // We verify get/set called thrice here: twice for setup (on NMService) and once during
807 // teardown (on Netd) because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900808 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900809 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900810 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900811 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900812 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900813 verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900814 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900815 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900816 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900817 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
818 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
819 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900820 // This is called, but will throw.
821 verify(mNMService, times(1)).setIpForwardingEnabled(true);
822 // This never gets called because of the exception thrown above.
823 verify(mNMService, times(0)).startTethering(any(String[].class));
824 // When the master state machine transitions to an error state it tells
825 // downstream interfaces, which causes us to tell Wi-Fi about the error
826 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900827 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900828 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900829 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900830
831 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900832 verifyNoMoreInteractions(mNMService);
833 }
834
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100835 private void userRestrictionsListenerBehaviour(
836 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
837 int expectedInteractionsWithShowNotification) throws Exception {
838 final int userId = 0;
839 final Bundle currRestrictions = new Bundle();
840 final Bundle newRestrictions = new Bundle();
841 Tethering tethering = mock(Tethering.class);
842 Tethering.TetheringUserRestrictionListener turl =
843 new Tethering.TetheringUserRestrictionListener(tethering);
844
845 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
846 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
847 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
848
849 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
850
851 verify(tethering, times(expectedInteractionsWithShowNotification))
852 .showTetheredNotification(anyInt(), eq(false));
853
854 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
855 }
856
857 @Test
858 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
859 final String[] emptyActiveIfacesList = new String[]{};
860 final boolean currDisallow = false;
861 final boolean nextDisallow = true;
862 final int expectedInteractionsWithShowNotification = 0;
863
864 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
865 expectedInteractionsWithShowNotification);
866 }
867
868 @Test
869 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900870 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100871 final boolean currDisallow = false;
872 final boolean nextDisallow = true;
873 final int expectedInteractionsWithShowNotification = 1;
874
875 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
876 expectedInteractionsWithShowNotification);
877 }
878
879 @Test
880 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
881 final String[] nonEmptyActiveIfacesList = new String[]{};
882 final boolean currDisallow = true;
883 final boolean nextDisallow = false;
884 final int expectedInteractionsWithShowNotification = 0;
885
886 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
887 expectedInteractionsWithShowNotification);
888 }
889
890 @Test
891 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900892 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100893 final boolean currDisallow = true;
894 final boolean nextDisallow = false;
895 final int expectedInteractionsWithShowNotification = 0;
896
897 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
898 expectedInteractionsWithShowNotification);
899 }
900
901 @Test
902 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900903 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100904 final int expectedInteractionsWithShowNotification = 0;
905 boolean currDisallow = true;
906 boolean nextDisallow = true;
907
908 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
909 expectedInteractionsWithShowNotification);
910
911 currDisallow = false;
912 nextDisallow = false;
913
914 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
915 expectedInteractionsWithShowNotification);
916 }
917
918
Erik Kline1fdc2e22017-05-08 17:56:35 +0900919 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900920 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700921}