blob: 80818120fa3c1588dfcffdeb438a1a6a7e7616b3 [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;
Erik Kline72302902018-06-14 17:36:40 +090074import android.net.NetworkRequest;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090075import android.net.NetworkState;
76import android.net.NetworkUtils;
77import android.net.RouteInfo;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090078import android.net.dhcp.DhcpServer;
79import android.net.dhcp.DhcpServingParams;
Erik Kline7a4ccc62018-08-27 17:26:47 +090080import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090081import android.net.ip.RouterAdvertisementDaemon;
82import android.net.util.InterfaceParams;
83import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090084import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090085import android.net.wifi.WifiConfiguration;
86import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010087import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090088import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070089import android.os.INetworkManagementService;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090090import android.os.Looper;
Christopher Wiley497c1472016-10-11 13:26:03 -070091import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090092import android.os.RemoteException;
Erik Klineea9cc482017-03-10 19:35:34 +090093import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010094import android.os.UserManager;
markchienb6eb2c22018-07-18 14:29:20 +080095import android.os.test.TestLooper;
Erik Kline92c4db02017-05-31 10:21:32 +090096import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070097import android.support.test.filters.SmallTest;
98import android.support.test.runner.AndroidJUnit4;
99import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +0900100import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700101
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900102import com.android.internal.util.ArrayUtils;
103import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900104import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900105import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900106import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900107import com.android.server.connectivity.tethering.OffloadHardwareInterface;
108import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900109import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900110
Erik Kline8351faa2017-04-17 16:47:23 +0900111import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700112import org.junit.Before;
113import org.junit.Test;
114import org.junit.runner.RunWith;
115import org.mockito.Mock;
116import org.mockito.MockitoAnnotations;
117
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900118import java.net.Inet4Address;
119import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900120import java.util.ArrayList;
121import java.util.Vector;
122
Christopher Wiley497c1472016-10-11 13:26:03 -0700123@RunWith(AndroidJUnit4.class)
124@SmallTest
125public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900126 private static final int IFINDEX_OFFSET = 100;
127
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900128 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
129 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
130 private static final String TEST_USB_IFNAME = "test_rndis0";
131 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700132
Erik Kline72302902018-06-14 17:36:40 +0900133 // Actual contents of the request don't matter for this test. The lack of
134 // any specific TRANSPORT_* is sufficient to identify this request.
135 private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();
136
Erik Klinef3a08b42017-06-07 16:33:19 +0900137 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700138 @Mock private Context mContext;
139 @Mock private INetworkManagementService mNMService;
140 @Mock private INetworkStatsService mStatsService;
141 @Mock private INetworkPolicyManager mPolicyManager;
142 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900143 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700144 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900145 @Mock private UsbManager mUsbManager;
146 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700147 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900148 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
149 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
150 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900151 @Mock private DhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900152 @Mock private INetd mNetd;
153
154 private final MockTetheringDependencies mTetheringDependencies =
155 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700156
157 // Like so many Android system APIs, these cannot be mocked because it is marked final.
158 // We have to use the real versions.
159 private final PersistableBundle mCarrierConfig = new PersistableBundle();
160 private final TestLooper mLooper = new TestLooper();
161
Erik Kline8351faa2017-04-17 16:47:23 +0900162 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900163 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900164 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900165 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700166 private Tethering mTethering;
167
Erik Klineea9cc482017-03-10 19:35:34 +0900168 private class MockContext extends BroadcastInterceptingContext {
169 MockContext(Context base) {
170 super(base);
171 }
172
173 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900174 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
175
176 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900177 public ContentResolver getContentResolver() { return mContentResolver; }
178
179 @Override
180 public String getPackageName() { return "TetheringTest"; }
181
182 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900183 public Resources getResources() { return mResources; }
184
185 @Override
186 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900187 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900188 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900189 return super.getSystemService(name);
190 }
191 }
192
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900193 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900194 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900195 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900196 int isTetheringSupportedCalls;
197
198 public void reset() {
199 upstreamNetworkMonitorMasterSM = null;
200 ipv6CoordinatorNotifyList = null;
201 isTetheringSupportedCalls = 0;
202 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900203
204 @Override
205 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
206 return mOffloadHardwareInterface;
207 }
208
209 @Override
210 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
211 StateMachine target, SharedLog log, int what) {
212 upstreamNetworkMonitorMasterSM = target;
213 return mUpstreamNetworkMonitor;
214 }
215
216 @Override
217 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900218 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900219 ipv6CoordinatorNotifyList = notifyList;
220 return mIPv6TetheringCoordinator;
221 }
222
223 @Override
Erik Kline7a4ccc62018-08-27 17:26:47 +0900224 public IpServer.Dependencies getIpServerDependencies() {
225 return new IpServer.Dependencies() {
226 @Override
227 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
228 InterfaceParams ifParams) {
229 return mRouterAdvertisementDaemon;
230 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900231
Erik Kline7a4ccc62018-08-27 17:26:47 +0900232 @Override
233 public InterfaceParams getInterfaceParams(String ifName) {
234 final String[] ifaces = new String[] {
235 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
236 final int index = ArrayUtils.indexOf(ifaces, ifName);
237 assertTrue("Non-mocked interface: " + ifName, index >= 0);
238 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
239 MacAddress.ALL_ZEROS_ADDRESS);
240 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900241
Erik Kline7a4ccc62018-08-27 17:26:47 +0900242 @Override
243 public INetd getNetdService() {
244 return mNetd;
245 }
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900246
247 @Override
248 public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
249 DhcpServingParams params, SharedLog log) {
250 return mDhcpServer;
251 }
Erik Kline7a4ccc62018-08-27 17:26:47 +0900252 };
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900253 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900254
255 @Override
256 public boolean isTetheringSupported() {
257 isTetheringSupportedCalls++;
258 return true;
259 }
Erik Kline72302902018-06-14 17:36:40 +0900260
261 @Override
262 public NetworkRequest getDefaultNetworkRequest() {
263 return mDefaultRequest;
264 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900265 }
266
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900267 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
268 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900269 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900270 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
271 final LinkProperties prop = new LinkProperties();
272 prop.setInterfaceName(TEST_MOBILE_IFNAME);
273
274 if (withIPv4) {
275 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
276 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
277 }
278
279 if (withIPv6) {
280 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
281 prop.addLinkAddress(
282 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
283 NetworkConstants.RFC7421_PREFIX_LENGTH));
284 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
285 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
286 }
287
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900288 if (with464xlat) {
289 final LinkProperties stackedLink = new LinkProperties();
290 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
291 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
292 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
293
294 prop.addStackedLink(stackedLink);
295 }
296
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900297
298 final NetworkCapabilities capabilities = new NetworkCapabilities()
299 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
300 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
301 }
302
303 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900304 return buildMobileUpstreamState(true, false, false);
305 }
306
307 private static NetworkState buildMobileIPv6UpstreamState() {
308 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900309 }
310
311 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900312 return buildMobileUpstreamState(true, true, false);
313 }
314
315 private static NetworkState buildMobile464xlatUpstreamState() {
316 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900317 }
318
Erik Kline8351faa2017-04-17 16:47:23 +0900319 @Before
320 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700321 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700322 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
323 .thenReturn(new String[0]);
324 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900325 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700326 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900327 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700328 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
329 .thenReturn(new String[0]);
330 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
331 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900332 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
333 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900334 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900335 .thenReturn(new String[] {
336 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900337 when(mNMService.getInterfaceConfig(anyString()))
338 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900339 when(mRouterAdvertisementDaemon.start())
340 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900341
342 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900343 mContentResolver = new MockContentResolver(mServiceContext);
344 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900345 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900346 mIntents = new Vector<>();
347 mBroadcastReceiver = new BroadcastReceiver() {
348 @Override
349 public void onReceive(Context context, Intent intent) {
350 mIntents.addElement(intent);
351 }
352 };
353 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900354 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
355 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900356 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900357 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700358 }
359
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900360 private Tethering makeTethering() {
361 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
362 mLooper.getLooper(), mSystemProperties,
363 mTetheringDependencies);
364 }
365
Erik Kline8351faa2017-04-17 16:47:23 +0900366 @After
367 public void tearDown() {
368 mServiceContext.unregisterReceiver(mBroadcastReceiver);
369 }
370
Erik Klineea9cc482017-03-10 19:35:34 +0900371 private void sendWifiApStateChanged(int state) {
372 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900373 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900374 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
375 }
376
Erik Kline2efb8272017-05-31 15:53:53 +0900377 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
378 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
379 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
380 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
381 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
382 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
383 }
384
Erik Klinec438e302017-07-04 22:02:49 +0900385 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
386 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
387 intent.putExtra(USB_CONNECTED, connected);
388 intent.putExtra(USB_CONFIGURED, configured);
389 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
390 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
391 }
392
Erik Kline80b7a9f2018-02-28 15:01:35 +0900393 private void sendConfigurationChanged() {
394 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
395 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
396 }
397
Erik Kline9e225542017-06-08 17:48:48 +0900398 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900399 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900400 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900401 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
402 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900403 }
404
405 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
406 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
407 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900408 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900409 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
410 assertTrue(ifnames.contains(ifname));
411 mIntents.remove(bcast);
412 }
413
Erik Klinea9cde8b2017-06-20 21:18:31 +0900414 public void failingLocalOnlyHotspotLegacyApBroadcast(
415 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900416 // Emulate externally-visible WifiManager effects, causing the
417 // per-interface state machine to start up, and telling us that
418 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900419 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900420 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900421 }
Erik Kline9e225542017-06-08 17:48:48 +0900422 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900423 mLooper.dispatchAll();
424
Erik Kline7a4ccc62018-08-27 17:26:47 +0900425 // If, and only if, Tethering received an interface status changed then
426 // it creates a IpServer and sends out a broadcast indicating that the
427 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900428 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900429 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
430 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900431 }
Erik Kline9e225542017-06-08 17:48:48 +0900432 verifyNoMoreInteractions(mNMService);
433 verifyNoMoreInteractions(mWifiManager);
434 }
435
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900436 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900437 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900438 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
439 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900440
441 // Emulate pressing the USB tethering button in Settings UI.
442 mTethering.startTethering(TETHERING_USB, null, false);
443 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800444 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900445
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900446 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
447 }
448
449 @Test
450 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
451 NetworkState upstreamState = buildMobileIPv4UpstreamState();
452 prepareUsbTethering(upstreamState);
453
Erik Klinec438e302017-07-04 22:02:49 +0900454 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900455 verifyNoMoreInteractions(mNMService);
456
457 // Pretend we then receive USB configured broadcast.
458 sendUsbBroadcast(true, true, true);
459 mLooper.dispatchAll();
460 // Now we should see the start of tethering mechanics (in this case:
461 // tetherMatchingInterfaces() which starts by fetching all interfaces).
462 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900463
464 // UpstreamNetworkMonitor should receive selected upstream
465 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
466 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900467 }
468
469 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900470 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
471 failingLocalOnlyHotspotLegacyApBroadcast(true);
472 }
473
474 @Test
475 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
476 failingLocalOnlyHotspotLegacyApBroadcast(false);
477 }
478
479 public void workingLocalOnlyHotspotEnrichedApBroadcast(
480 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900481 // Emulate externally-visible WifiManager effects, causing the
482 // per-interface state machine to start up, and telling us that
483 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900484 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900485 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900486 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900487 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900488 mLooper.dispatchAll();
489
490 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900491 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900492 verify(mNMService, times(1)).setIpForwardingEnabled(true);
493 verify(mNMService, times(1)).startTethering(any(String[].class));
494 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900495 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900496 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900497 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900498 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
Erik Kline72302902018-06-14 17:36:40 +0900499 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900500 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900501 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900502
503 // Emulate externally-visible WifiManager effects, when hotspot mode
504 // is being torn down.
505 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900506 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900507 mLooper.dispatchAll();
508
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900509 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900510 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900511 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900512 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900513 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900514 verify(mNMService, times(1)).stopTethering();
515 verify(mNMService, times(1)).setIpForwardingEnabled(false);
516 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900517 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900518 // Asking for the last error after the per-interface state machine
519 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900520 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900521 }
522
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900524 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900525 */
526 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
527 // IPv6TetheringCoordinator must have been notified of downstream
528 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
529 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900530 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900531
Erik Kline7a4ccc62018-08-27 17:26:47 +0900532 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900533 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900534 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900535 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900536 upstreamState.linkProperties.isIPv6Provisioned()
537 ? ipv6OnlyState.linkProperties
538 : null);
539 }
540 mLooper.dispatchAll();
541 }
542
543 private void runUsbTethering(NetworkState upstreamState) {
544 prepareUsbTethering(upstreamState);
545 sendUsbBroadcast(true, true, true);
546 mLooper.dispatchAll();
547 }
548
549 @Test
550 public void workingMobileUsbTethering_IPv4() throws Exception {
551 NetworkState upstreamState = buildMobileIPv4UpstreamState();
552 runUsbTethering(upstreamState);
553
554 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
555 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
556
557 sendIPv6TetherUpdates(upstreamState);
558 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900559 verify(mDhcpServer, times(1)).start();
560 }
561
562 @Test
563 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
564 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
565 mTethering = makeTethering();
566 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
567 runUsbTethering(upstreamState);
568 sendIPv6TetherUpdates(upstreamState);
569
570 verify(mDhcpServer, never()).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900571 }
572
573 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900574 public void workingMobileUsbTethering_IPv6() throws Exception {
575 NetworkState upstreamState = buildMobileIPv6UpstreamState();
576 runUsbTethering(upstreamState);
577
578 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
579 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
580
581 sendIPv6TetherUpdates(upstreamState);
582 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
583 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
584 }
585
586 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900587 public void workingMobileUsbTethering_DualStack() throws Exception {
588 NetworkState upstreamState = buildMobileDualStackUpstreamState();
589 runUsbTethering(upstreamState);
590
591 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
592 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
593 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900594 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900595
596 sendIPv6TetherUpdates(upstreamState);
597 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
598 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
599 }
600
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900601 @Test
602 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
603 NetworkState upstreamState = buildMobile464xlatUpstreamState();
604 runUsbTethering(upstreamState);
605
606 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
607 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900608 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900609 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
610 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
611 TEST_XLAT_MOBILE_IFNAME);
612
613 sendIPv6TetherUpdates(upstreamState);
614 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
615 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
616 }
617
618 @Test
619 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
620 // Setup IPv6
621 NetworkState upstreamState = buildMobileIPv6UpstreamState();
622 runUsbTethering(upstreamState);
623
624 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900625 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900626 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
627
628 // Then 464xlat comes up
629 upstreamState = buildMobile464xlatUpstreamState();
630 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
631 .thenReturn(upstreamState);
632
633 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
634 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
635 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
636 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
637 0,
638 upstreamState);
639 mLooper.dispatchAll();
640
641 // Forwarding is added for 464xlat
642 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
643 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
644 TEST_XLAT_MOBILE_IFNAME);
645 // Forwarding was not re-added for v6 (still times(1))
646 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
647 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900648 // DHCP not restarted on downstream (still times(1))
649 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900650 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900651
Erik Klineea9cc482017-03-10 19:35:34 +0900652 @Test
Erik Kline72302902018-06-14 17:36:40 +0900653 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
654 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
655 .thenReturn(true);
656 sendConfigurationChanged();
657
658 // Setup IPv6
659 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
660 runUsbTethering(upstreamState);
661
662 // UpstreamNetworkMonitor should choose upstream automatically
663 // (in this specific case: choose the default network).
664 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
665 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
666
667 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
668 }
669
670 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900671 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
672 workingLocalOnlyHotspotEnrichedApBroadcast(true);
673 }
674
675 @Test
676 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
677 workingLocalOnlyHotspotEnrichedApBroadcast(false);
678 }
679
680 // TODO: Test with and without interfaceStatusChanged().
681 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900682 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900683 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900684
685 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900686 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900687 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900688 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900689 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900690 verifyNoMoreInteractions(mNMService);
691
692 // Emulate externally-visible WifiManager effects, causing the
693 // per-interface state machine to start up, and telling us that
694 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900695 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900696 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900697 mLooper.dispatchAll();
698
Erik Kline465ff3a2018-03-09 14:18:02 +0900699 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
700 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900701 verifyNoMoreInteractions(mNMService);
702 verifyNoMoreInteractions(mWifiManager);
703 }
704
Erik Klinea9cde8b2017-06-20 21:18:31 +0900705 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900706 @Test
707 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900708 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
709
710 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900711 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900712 mLooper.dispatchAll();
713 verify(mWifiManager, times(1)).startSoftAp(null);
714 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900715 verifyNoMoreInteractions(mNMService);
716
717 // Emulate externally-visible WifiManager effects, causing the
718 // per-interface state machine to start up, and telling us that
719 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900720 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
721 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900722 mLooper.dispatchAll();
723
724 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900725 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900726 verify(mNMService, times(1)).setIpForwardingEnabled(true);
727 verify(mNMService, times(1)).startTethering(any(String[].class));
728 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900729 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900730 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900731 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900732 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
Erik Kline72302902018-06-14 17:36:40 +0900733 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900734 // In tethering mode, in the default configuration, an explicit request
735 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900736 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900737 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900738 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900739
740 /////
741 // We do not currently emulate any upstream being found.
742 //
743 // This is why there are no calls to verify mNMService.enableNat() or
744 // mNMService.startInterfaceForwarding().
745 /////
746
747 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900748 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900749 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900750 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900751 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900752 verifyNoMoreInteractions(mNMService);
753
754 // Emulate externally-visible WifiManager effects, when tethering mode
755 // is being torn down.
756 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900757 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900758 mLooper.dispatchAll();
759
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900760 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900761 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900762 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900763 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900764 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900765 verify(mNMService, times(1)).stopTethering();
766 verify(mNMService, times(1)).setIpForwardingEnabled(false);
767 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900768 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900769 // Asking for the last error after the per-interface state machine
770 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900771 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900772 }
773
Erik Klinea9cde8b2017-06-20 21:18:31 +0900774 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900775 @Test
776 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900777 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
778 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
779
780 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900781 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900782 mLooper.dispatchAll();
783 verify(mWifiManager, times(1)).startSoftAp(null);
784 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900785 verifyNoMoreInteractions(mNMService);
786
787 // Emulate externally-visible WifiManager effects, causing the
788 // per-interface state machine to start up, and telling us that
789 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900790 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
791 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900792 mLooper.dispatchAll();
793
Erik Kline472276a2018-05-18 16:09:24 +0900794 // We verify get/set called thrice here: once for setup and twice during
Erik Kline1fdc2e22017-05-08 17:56:35 +0900795 // teardown because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900796 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900797 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900798 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline472276a2018-05-18 16:09:24 +0900799 verify(mNMService, times(3))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900800 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
801 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900802 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900803 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900804 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
805 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
806 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900807 // This is called, but will throw.
808 verify(mNMService, times(1)).setIpForwardingEnabled(true);
809 // This never gets called because of the exception thrown above.
810 verify(mNMService, times(0)).startTethering(any(String[].class));
811 // When the master state machine transitions to an error state it tells
812 // downstream interfaces, which causes us to tell Wi-Fi about the error
813 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900814 verify(mNMService, times(1)).untetherInterface(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_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900817
818 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900819 verifyNoMoreInteractions(mNMService);
820 }
821
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100822 private void userRestrictionsListenerBehaviour(
823 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
824 int expectedInteractionsWithShowNotification) throws Exception {
825 final int userId = 0;
826 final Bundle currRestrictions = new Bundle();
827 final Bundle newRestrictions = new Bundle();
828 Tethering tethering = mock(Tethering.class);
829 Tethering.TetheringUserRestrictionListener turl =
830 new Tethering.TetheringUserRestrictionListener(tethering);
831
832 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
833 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
834 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
835
836 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
837
838 verify(tethering, times(expectedInteractionsWithShowNotification))
839 .showTetheredNotification(anyInt(), eq(false));
840
841 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
842 }
843
844 @Test
845 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
846 final String[] emptyActiveIfacesList = new String[]{};
847 final boolean currDisallow = false;
848 final boolean nextDisallow = true;
849 final int expectedInteractionsWithShowNotification = 0;
850
851 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
852 expectedInteractionsWithShowNotification);
853 }
854
855 @Test
856 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900857 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100858 final boolean currDisallow = false;
859 final boolean nextDisallow = true;
860 final int expectedInteractionsWithShowNotification = 1;
861
862 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
863 expectedInteractionsWithShowNotification);
864 }
865
866 @Test
867 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
868 final String[] nonEmptyActiveIfacesList = new String[]{};
869 final boolean currDisallow = true;
870 final boolean nextDisallow = false;
871 final int expectedInteractionsWithShowNotification = 0;
872
873 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
874 expectedInteractionsWithShowNotification);
875 }
876
877 @Test
878 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900879 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100880 final boolean currDisallow = true;
881 final boolean nextDisallow = false;
882 final int expectedInteractionsWithShowNotification = 0;
883
884 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
885 expectedInteractionsWithShowNotification);
886 }
887
888 @Test
889 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900890 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100891 final int expectedInteractionsWithShowNotification = 0;
892 boolean currDisallow = true;
893 boolean nextDisallow = true;
894
895 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
896 expectedInteractionsWithShowNotification);
897
898 currDisallow = false;
899 nextDisallow = false;
900
901 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
902 expectedInteractionsWithShowNotification);
903 }
904
905
Erik Kline1fdc2e22017-05-08 17:56:35 +0900906 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900907 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700908}