blob: 533d7ad2a472c26eef2a6212ab704a594561f51f [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;
markchien293422f2019-01-08 23:52:21 +080038import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090039
Erik Klineea9cc482017-03-10 19:35:34 +090040import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070041import static org.junit.Assert.assertTrue;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090042import static org.junit.Assert.fail;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090043import static org.mockito.ArgumentMatchers.argThat;
44import static org.mockito.ArgumentMatchers.notNull;
Erik Klineea9cc482017-03-10 19:35:34 +090045import static org.mockito.Matchers.anyInt;
46import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070047import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090048import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090049import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090050import static org.mockito.Mockito.doThrow;
markchienb6eb2c22018-07-18 14:29:20 +080051import static org.mockito.Mockito.mock;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090052import static org.mockito.Mockito.never;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090053import static org.mockito.Mockito.spy;
54import static org.mockito.Mockito.timeout;
Erik Klineea9cc482017-03-10 19:35:34 +090055import static org.mockito.Mockito.times;
56import static org.mockito.Mockito.verify;
57import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070058import static org.mockito.Mockito.when;
59
Erik Kline8351faa2017-04-17 16:47:23 +090060import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090061import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070062import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090063import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090064import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090065import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070066import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090067import android.hardware.usb.UsbManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090068import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070069import android.net.INetworkPolicyManager;
70import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090071import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090072import android.net.IpPrefix;
73import android.net.LinkAddress;
74import android.net.LinkProperties;
75import android.net.MacAddress;
76import android.net.Network;
77import android.net.NetworkCapabilities;
78import android.net.NetworkInfo;
79import android.net.NetworkState;
80import android.net.NetworkUtils;
81import android.net.RouteInfo;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090082import android.net.dhcp.DhcpServerCallbacks;
83import android.net.dhcp.DhcpServingParamsParcel;
84import android.net.dhcp.IDhcpServer;
Erik Kline7a4ccc62018-08-27 17:26:47 +090085import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090086import android.net.ip.RouterAdvertisementDaemon;
87import android.net.util.InterfaceParams;
88import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090089import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090090import android.net.wifi.WifiConfiguration;
91import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010092import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090093import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070094import android.os.INetworkManagementService;
95import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090096import android.os.RemoteException;
Erik Klineea9cc482017-03-10 19:35:34 +090097import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010098import android.os.UserManager;
markchienb6eb2c22018-07-18 14:29:20 +080099import android.os.test.TestLooper;
Erik Kline92c4db02017-05-31 10:21:32 +0900100import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -0700101import android.support.test.filters.SmallTest;
102import android.support.test.runner.AndroidJUnit4;
103import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +0900104import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700105
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900106import com.android.internal.util.ArrayUtils;
107import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900108import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900109import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900110import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900111import com.android.server.connectivity.tethering.OffloadHardwareInterface;
112import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900113import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900114
Erik Kline8351faa2017-04-17 16:47:23 +0900115import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700116import org.junit.Before;
117import org.junit.Test;
118import org.junit.runner.RunWith;
119import org.mockito.Mock;
120import org.mockito.MockitoAnnotations;
121
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900122import java.net.Inet4Address;
123import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900124import java.util.ArrayList;
125import java.util.Vector;
126
Christopher Wiley497c1472016-10-11 13:26:03 -0700127@RunWith(AndroidJUnit4.class)
128@SmallTest
129public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900130 private static final int IFINDEX_OFFSET = 100;
131
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900132 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
133 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
134 private static final String TEST_USB_IFNAME = "test_rndis0";
135 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700136
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900137 private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
138
Erik Klinef3a08b42017-06-07 16:33:19 +0900139 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700140 @Mock private Context mContext;
141 @Mock private INetworkManagementService mNMService;
142 @Mock private INetworkStatsService mStatsService;
143 @Mock private INetworkPolicyManager mPolicyManager;
144 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900145 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700146 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900147 @Mock private UsbManager mUsbManager;
148 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700149 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900150 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
151 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
152 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900153 @Mock private IDhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900154 @Mock private INetd mNetd;
155
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900156 private final MockIpServerDependencies mIpServerDependencies =
157 spy(new MockIpServerDependencies());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900158 private final MockTetheringDependencies mTetheringDependencies =
159 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700160
161 // Like so many Android system APIs, these cannot be mocked because it is marked final.
162 // We have to use the real versions.
163 private final PersistableBundle mCarrierConfig = new PersistableBundle();
164 private final TestLooper mLooper = new TestLooper();
165
Erik Kline8351faa2017-04-17 16:47:23 +0900166 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900167 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900168 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900169 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700170 private Tethering mTethering;
171
Erik Klineea9cc482017-03-10 19:35:34 +0900172 private class MockContext extends BroadcastInterceptingContext {
173 MockContext(Context base) {
174 super(base);
175 }
176
177 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900178 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
179
180 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900181 public ContentResolver getContentResolver() { return mContentResolver; }
182
183 @Override
184 public String getPackageName() { return "TetheringTest"; }
185
186 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900187 public Resources getResources() { return mResources; }
188
189 @Override
190 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900191 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900192 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900193 return super.getSystemService(name);
194 }
195 }
196
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900197 public class MockIpServerDependencies extends IpServer.Dependencies {
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900198 @Override
199 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
200 InterfaceParams ifParams) {
201 return mRouterAdvertisementDaemon;
202 }
203
204 @Override
205 public InterfaceParams getInterfaceParams(String ifName) {
206 assertTrue("Non-mocked interface " + ifName,
207 ifName.equals(TEST_USB_IFNAME)
208 || ifName.equals(TEST_WLAN_IFNAME)
209 || ifName.equals(TEST_MOBILE_IFNAME));
210 final String[] ifaces = new String[] {
211 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
212 return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
213 MacAddress.ALL_ZEROS_ADDRESS);
214 }
215
216 @Override
217 public INetd getNetdService() {
218 return mNetd;
219 }
220
221 @Override
222 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
223 DhcpServerCallbacks cb) {
224 new Thread(() -> {
225 try {
226 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
227 } catch (RemoteException e) {
228 fail(e.getMessage());
229 }
230 }).run();
231 }
232 }
233
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900234 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900235 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900236 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900237 int isTetheringSupportedCalls;
238
239 public void reset() {
240 upstreamNetworkMonitorMasterSM = null;
241 ipv6CoordinatorNotifyList = null;
242 isTetheringSupportedCalls = 0;
243 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900244
245 @Override
246 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
247 return mOffloadHardwareInterface;
248 }
249
250 @Override
251 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
252 StateMachine target, SharedLog log, int what) {
253 upstreamNetworkMonitorMasterSM = target;
254 return mUpstreamNetworkMonitor;
255 }
256
257 @Override
258 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900259 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900260 ipv6CoordinatorNotifyList = notifyList;
261 return mIPv6TetheringCoordinator;
262 }
263
264 @Override
Remi NGUYEN VAN310da6f2019-02-14 18:04:20 +0900265 public IpServer.Dependencies getIpServerDependencies() {
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900266 return mIpServerDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900267 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900268
269 @Override
270 public boolean isTetheringSupported() {
271 isTetheringSupportedCalls++;
272 return true;
273 }
markchien293422f2019-01-08 23:52:21 +0800274
275 @Override
276 public int getDefaultDataSubscriptionId() {
277 return INVALID_SUBSCRIPTION_ID;
278 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900279 }
280
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900281 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
282 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900283 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900284 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
285 final LinkProperties prop = new LinkProperties();
286 prop.setInterfaceName(TEST_MOBILE_IFNAME);
287
288 if (withIPv4) {
289 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
290 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
291 }
292
293 if (withIPv6) {
294 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
295 prop.addLinkAddress(
296 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
297 NetworkConstants.RFC7421_PREFIX_LENGTH));
298 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
299 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
300 }
301
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900302 if (with464xlat) {
303 final LinkProperties stackedLink = new LinkProperties();
304 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
305 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
306 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
307
308 prop.addStackedLink(stackedLink);
309 }
310
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900311
312 final NetworkCapabilities capabilities = new NetworkCapabilities()
313 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
314 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
315 }
316
317 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900318 return buildMobileUpstreamState(true, false, false);
319 }
320
321 private static NetworkState buildMobileIPv6UpstreamState() {
322 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900323 }
324
325 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900326 return buildMobileUpstreamState(true, true, false);
327 }
328
329 private static NetworkState buildMobile464xlatUpstreamState() {
330 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900331 }
332
Erik Kline8351faa2017-04-17 16:47:23 +0900333 @Before
334 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700335 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700336 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
337 .thenReturn(new String[0]);
338 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900339 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700340 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900341 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700342 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
343 .thenReturn(new String[0]);
344 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
345 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900346 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
347 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900348 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900349 .thenReturn(new String[] {
350 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900351 when(mNMService.getInterfaceConfig(anyString()))
352 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900353 when(mRouterAdvertisementDaemon.start())
354 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900355
356 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900357 mContentResolver = new MockContentResolver(mServiceContext);
358 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900359 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900360 mIntents = new Vector<>();
361 mBroadcastReceiver = new BroadcastReceiver() {
362 @Override
363 public void onReceive(Context context, Intent intent) {
364 mIntents.addElement(intent);
365 }
366 };
367 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900368 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
369 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900370 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900371 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700372 }
373
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900374 private Tethering makeTethering() {
375 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
376 mLooper.getLooper(), mSystemProperties,
377 mTetheringDependencies);
378 }
379
Erik Kline8351faa2017-04-17 16:47:23 +0900380 @After
381 public void tearDown() {
382 mServiceContext.unregisterReceiver(mBroadcastReceiver);
383 }
384
Erik Klineea9cc482017-03-10 19:35:34 +0900385 private void sendWifiApStateChanged(int state) {
386 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900387 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900388 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
389 }
390
Erik Kline2efb8272017-05-31 15:53:53 +0900391 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
392 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
393 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
394 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
395 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
396 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
397 }
398
Erik Klinec438e302017-07-04 22:02:49 +0900399 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
400 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
401 intent.putExtra(USB_CONNECTED, connected);
402 intent.putExtra(USB_CONFIGURED, configured);
403 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
404 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
405 }
406
Erik Kline80b7a9f2018-02-28 15:01:35 +0900407 private void sendConfigurationChanged() {
408 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
409 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
410 }
411
Erik Kline9e225542017-06-08 17:48:48 +0900412 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900413 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900414 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900415 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
416 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900417 }
418
419 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
420 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
421 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900422 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900423 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
424 assertTrue(ifnames.contains(ifname));
425 mIntents.remove(bcast);
426 }
427
Erik Klinea9cde8b2017-06-20 21:18:31 +0900428 public void failingLocalOnlyHotspotLegacyApBroadcast(
429 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900430 // Emulate externally-visible WifiManager effects, causing the
431 // per-interface state machine to start up, and telling us that
432 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900433 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900434 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900435 }
Erik Kline9e225542017-06-08 17:48:48 +0900436 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900437 mLooper.dispatchAll();
438
Erik Kline7a4ccc62018-08-27 17:26:47 +0900439 // If, and only if, Tethering received an interface status changed then
440 // it creates a IpServer and sends out a broadcast indicating that the
441 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900442 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900443 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
444 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900445 }
Erik Kline9e225542017-06-08 17:48:48 +0900446 verifyNoMoreInteractions(mNMService);
447 verifyNoMoreInteractions(mWifiManager);
448 }
449
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900450 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900451 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900452 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
453 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900454
455 // Emulate pressing the USB tethering button in Settings UI.
456 mTethering.startTethering(TETHERING_USB, null, false);
457 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800458 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900459
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900460 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
461 }
462
463 @Test
464 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
465 NetworkState upstreamState = buildMobileIPv4UpstreamState();
466 prepareUsbTethering(upstreamState);
467
Erik Klinec438e302017-07-04 22:02:49 +0900468 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900469 verifyNoMoreInteractions(mNMService);
470
471 // Pretend we then receive USB configured broadcast.
472 sendUsbBroadcast(true, true, true);
473 mLooper.dispatchAll();
474 // Now we should see the start of tethering mechanics (in this case:
475 // tetherMatchingInterfaces() which starts by fetching all interfaces).
476 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900477
478 // UpstreamNetworkMonitor should receive selected upstream
479 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
480 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900481 }
482
483 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900484 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
485 failingLocalOnlyHotspotLegacyApBroadcast(true);
486 }
487
488 @Test
489 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
490 failingLocalOnlyHotspotLegacyApBroadcast(false);
491 }
492
493 public void workingLocalOnlyHotspotEnrichedApBroadcast(
494 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900495 // Emulate externally-visible WifiManager effects, causing the
496 // per-interface state machine to start up, and telling us that
497 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900498 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900499 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900500 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900501 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900502 mLooper.dispatchAll();
503
504 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900505 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900506 verify(mNMService, times(1)).setIpForwardingEnabled(true);
507 verify(mNMService, times(1)).startTethering(any(String[].class));
508 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900509 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900510 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900511 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900512 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
markchiena6c72872018-11-13 18:34:56 +0900513 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900514 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900515 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900516
517 // Emulate externally-visible WifiManager effects, when hotspot mode
518 // is being torn down.
519 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900520 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900521 mLooper.dispatchAll();
522
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900524 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900525 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900526 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900527 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900528 verify(mNMService, times(1)).stopTethering();
529 verify(mNMService, times(1)).setIpForwardingEnabled(false);
530 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900531 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900532 // Asking for the last error after the per-interface state machine
533 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900534 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900535 }
536
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900537 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900538 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900539 */
540 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
541 // IPv6TetheringCoordinator must have been notified of downstream
542 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
543 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900544 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900545
Erik Kline7a4ccc62018-08-27 17:26:47 +0900546 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900547 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900548 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900549 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900550 upstreamState.linkProperties.isIPv6Provisioned()
551 ? ipv6OnlyState.linkProperties
552 : null);
553 }
554 mLooper.dispatchAll();
555 }
556
557 private void runUsbTethering(NetworkState upstreamState) {
558 prepareUsbTethering(upstreamState);
559 sendUsbBroadcast(true, true, true);
560 mLooper.dispatchAll();
561 }
562
563 @Test
564 public void workingMobileUsbTethering_IPv4() throws Exception {
565 NetworkState upstreamState = buildMobileIPv4UpstreamState();
566 runUsbTethering(upstreamState);
567
568 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
569 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
570
571 sendIPv6TetherUpdates(upstreamState);
572 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900573 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900574 }
575
576 @Test
577 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
578 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
579 mTethering = makeTethering();
580 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
581 runUsbTethering(upstreamState);
582 sendIPv6TetherUpdates(upstreamState);
583
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900584 verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900585 }
586
587 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900588 public void workingMobileUsbTethering_IPv6() throws Exception {
589 NetworkState upstreamState = buildMobileIPv6UpstreamState();
590 runUsbTethering(upstreamState);
591
592 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
593 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
594
595 sendIPv6TetherUpdates(upstreamState);
596 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
597 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
598 }
599
600 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900601 public void workingMobileUsbTethering_DualStack() throws Exception {
602 NetworkState upstreamState = buildMobileDualStackUpstreamState();
603 runUsbTethering(upstreamState);
604
605 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
606 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
607 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900608 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900609
610 sendIPv6TetherUpdates(upstreamState);
611 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
612 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
613 }
614
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900615 @Test
616 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
617 NetworkState upstreamState = buildMobile464xlatUpstreamState();
618 runUsbTethering(upstreamState);
619
620 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
621 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900622 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900623 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
624 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
625 TEST_XLAT_MOBILE_IFNAME);
626
627 sendIPv6TetherUpdates(upstreamState);
628 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
629 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
630 }
631
632 @Test
633 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
634 // Setup IPv6
635 NetworkState upstreamState = buildMobileIPv6UpstreamState();
636 runUsbTethering(upstreamState);
637
638 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900639 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900640 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
641
642 // Then 464xlat comes up
643 upstreamState = buildMobile464xlatUpstreamState();
644 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
645 .thenReturn(upstreamState);
646
647 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
648 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
649 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
650 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
651 0,
652 upstreamState);
653 mLooper.dispatchAll();
654
655 // Forwarding is added for 464xlat
656 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
657 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
658 TEST_XLAT_MOBILE_IFNAME);
659 // Forwarding was not re-added for v6 (still times(1))
660 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
661 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900662 // DHCP not restarted on downstream (still times(1))
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900663 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900664 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900665
Erik Klineea9cc482017-03-10 19:35:34 +0900666 @Test
Erik Kline72302902018-06-14 17:36:40 +0900667 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
668 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
669 .thenReturn(true);
670 sendConfigurationChanged();
671
672 // Setup IPv6
673 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
674 runUsbTethering(upstreamState);
675
676 // UpstreamNetworkMonitor should choose upstream automatically
677 // (in this specific case: choose the default network).
678 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
679 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
680
681 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
682 }
683
684 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900685 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
686 workingLocalOnlyHotspotEnrichedApBroadcast(true);
687 }
688
689 @Test
690 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
691 workingLocalOnlyHotspotEnrichedApBroadcast(false);
692 }
693
694 // TODO: Test with and without interfaceStatusChanged().
695 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900696 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900697 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900698
699 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900700 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900701 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900702 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900703 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900704 verifyNoMoreInteractions(mNMService);
705
706 // Emulate externally-visible WifiManager effects, causing the
707 // per-interface state machine to start up, and telling us that
708 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900709 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900710 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900711 mLooper.dispatchAll();
712
Erik Kline465ff3a2018-03-09 14:18:02 +0900713 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
714 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900715 verifyNoMoreInteractions(mNMService);
716 verifyNoMoreInteractions(mWifiManager);
717 }
718
Erik Klinea9cde8b2017-06-20 21:18:31 +0900719 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900720 @Test
721 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900722 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
723
724 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900725 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900726 mLooper.dispatchAll();
727 verify(mWifiManager, times(1)).startSoftAp(null);
728 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900729 verifyNoMoreInteractions(mNMService);
730
731 // Emulate externally-visible WifiManager effects, causing the
732 // per-interface state machine to start up, and telling us that
733 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900734 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
735 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900736 mLooper.dispatchAll();
737
738 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900739 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900740 verify(mNMService, times(1)).setIpForwardingEnabled(true);
741 verify(mNMService, times(1)).startTethering(any(String[].class));
742 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900743 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900744 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900745 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900746 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
markchiena6c72872018-11-13 18:34:56 +0900747 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900748 // In tethering mode, in the default configuration, an explicit request
749 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900750 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900751 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900752 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900753
754 /////
755 // We do not currently emulate any upstream being found.
756 //
757 // This is why there are no calls to verify mNMService.enableNat() or
758 // mNMService.startInterfaceForwarding().
759 /////
760
761 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900762 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900763 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900764 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900765 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900766 verifyNoMoreInteractions(mNMService);
767
768 // Emulate externally-visible WifiManager effects, when tethering mode
769 // is being torn down.
770 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900771 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900772 mLooper.dispatchAll();
773
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900774 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900775 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900776 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900777 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900778 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900779 verify(mNMService, times(1)).stopTethering();
780 verify(mNMService, times(1)).setIpForwardingEnabled(false);
781 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900782 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900783 // Asking for the last error after the per-interface state machine
784 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900785 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900786 }
787
Erik Klinea9cde8b2017-06-20 21:18:31 +0900788 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900789 @Test
790 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900791 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
792 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
793
794 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900795 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900796 mLooper.dispatchAll();
797 verify(mWifiManager, times(1)).startSoftAp(null);
798 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900799 verifyNoMoreInteractions(mNMService);
800
801 // Emulate externally-visible WifiManager effects, causing the
802 // per-interface state machine to start up, and telling us that
803 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900804 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
805 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900806 mLooper.dispatchAll();
807
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900808 // We verify get/set called thrice here: twice for setup (on NMService) and once during
809 // teardown (on Netd) because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900810 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900811 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900812 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900813 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900814 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900815 verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900816 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900817 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900818 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900819 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
820 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
821 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900822 // This is called, but will throw.
823 verify(mNMService, times(1)).setIpForwardingEnabled(true);
824 // This never gets called because of the exception thrown above.
825 verify(mNMService, times(0)).startTethering(any(String[].class));
826 // When the master state machine transitions to an error state it tells
827 // downstream interfaces, which causes us to tell Wi-Fi about the error
828 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900829 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900830 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900831 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900832
833 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900834 verifyNoMoreInteractions(mNMService);
835 }
836
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100837 private void userRestrictionsListenerBehaviour(
838 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
839 int expectedInteractionsWithShowNotification) throws Exception {
840 final int userId = 0;
841 final Bundle currRestrictions = new Bundle();
842 final Bundle newRestrictions = new Bundle();
843 Tethering tethering = mock(Tethering.class);
844 Tethering.TetheringUserRestrictionListener turl =
845 new Tethering.TetheringUserRestrictionListener(tethering);
846
847 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
848 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
849 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
850
851 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
852
853 verify(tethering, times(expectedInteractionsWithShowNotification))
854 .showTetheredNotification(anyInt(), eq(false));
855
856 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
857 }
858
859 @Test
860 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
861 final String[] emptyActiveIfacesList = new String[]{};
862 final boolean currDisallow = false;
863 final boolean nextDisallow = true;
864 final int expectedInteractionsWithShowNotification = 0;
865
866 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
867 expectedInteractionsWithShowNotification);
868 }
869
870 @Test
871 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900872 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100873 final boolean currDisallow = false;
874 final boolean nextDisallow = true;
875 final int expectedInteractionsWithShowNotification = 1;
876
877 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
878 expectedInteractionsWithShowNotification);
879 }
880
881 @Test
882 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
883 final String[] nonEmptyActiveIfacesList = new String[]{};
884 final boolean currDisallow = true;
885 final boolean nextDisallow = false;
886 final int expectedInteractionsWithShowNotification = 0;
887
888 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
889 expectedInteractionsWithShowNotification);
890 }
891
892 @Test
893 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900894 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100895 final boolean currDisallow = true;
896 final boolean nextDisallow = false;
897 final int expectedInteractionsWithShowNotification = 0;
898
899 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
900 expectedInteractionsWithShowNotification);
901 }
902
903 @Test
904 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900905 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100906 final int expectedInteractionsWithShowNotification = 0;
907 boolean currDisallow = true;
908 boolean nextDisallow = true;
909
910 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
911 expectedInteractionsWithShowNotification);
912
913 currDisallow = false;
914 nextDisallow = false;
915
916 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
917 expectedInteractionsWithShowNotification);
918 }
919
920
Erik Kline1fdc2e22017-05-08 17:56:35 +0900921 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900922 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700923}