blob: 6c42ac398b47c358db83fb67142a40e27486a378 [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;
markchien0b595072019-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;
markchien26299ed2019-02-27 14:56:11 +080071import android.net.ITetheringEventCallback;
Erik Klineea9cc482017-03-10 19:35:34 +090072import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090073import android.net.IpPrefix;
74import android.net.LinkAddress;
75import android.net.LinkProperties;
76import android.net.MacAddress;
77import android.net.Network;
78import android.net.NetworkCapabilities;
79import android.net.NetworkInfo;
80import android.net.NetworkState;
81import android.net.NetworkUtils;
82import android.net.RouteInfo;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +090083import android.net.dhcp.DhcpServerCallbacks;
84import android.net.dhcp.DhcpServingParamsParcel;
85import android.net.dhcp.IDhcpServer;
Erik Kline7a4ccc62018-08-27 17:26:47 +090086import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090087import android.net.ip.RouterAdvertisementDaemon;
88import android.net.util.InterfaceParams;
89import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090090import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090091import android.net.wifi.WifiConfiguration;
92import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010093import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090094import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070095import android.os.INetworkManagementService;
96import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090097import android.os.RemoteException;
Erik Klineea9cc482017-03-10 19:35:34 +090098import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010099import android.os.UserManager;
markchienb6eb2c22018-07-18 14:29:20 +0800100import android.os.test.TestLooper;
Erik Kline92c4db02017-05-31 10:21:32 +0900101import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -0700102import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +0900103import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700104
Brett Chabot1ae2aa62019-03-04 14:14:56 -0800105import androidx.test.filters.SmallTest;
106import androidx.test.runner.AndroidJUnit4;
107
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900108import com.android.internal.util.ArrayUtils;
109import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900110import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900111import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900112import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900113import com.android.server.connectivity.tethering.OffloadHardwareInterface;
114import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900115import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900116
Erik Kline8351faa2017-04-17 16:47:23 +0900117import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700118import org.junit.Before;
119import org.junit.Test;
120import org.junit.runner.RunWith;
121import org.mockito.Mock;
122import org.mockito.MockitoAnnotations;
123
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900124import java.net.Inet4Address;
125import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900126import java.util.ArrayList;
markchien26299ed2019-02-27 14:56:11 +0800127import java.util.Arrays;
Erik Kline8351faa2017-04-17 16:47:23 +0900128import java.util.Vector;
129
Christopher Wiley497c1472016-10-11 13:26:03 -0700130@RunWith(AndroidJUnit4.class)
131@SmallTest
132public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900133 private static final int IFINDEX_OFFSET = 100;
134
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900135 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
136 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
137 private static final String TEST_USB_IFNAME = "test_rndis0";
138 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700139
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900140 private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
141
Erik Klinef3a08b42017-06-07 16:33:19 +0900142 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -0700143 @Mock private Context mContext;
144 @Mock private INetworkManagementService mNMService;
145 @Mock private INetworkStatsService mStatsService;
146 @Mock private INetworkPolicyManager mPolicyManager;
147 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900148 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -0700149 @Mock private Resources mResources;
Erik Klineea9cc482017-03-10 19:35:34 +0900150 @Mock private UsbManager mUsbManager;
151 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700152 @Mock private CarrierConfigManager mCarrierConfigManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900153 @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
154 @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
155 @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900156 @Mock private IDhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900157 @Mock private INetd mNetd;
158
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900159 private final MockIpServerDependencies mIpServerDependencies =
160 spy(new MockIpServerDependencies());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900161 private final MockTetheringDependencies mTetheringDependencies =
162 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700163
164 // Like so many Android system APIs, these cannot be mocked because it is marked final.
165 // We have to use the real versions.
166 private final PersistableBundle mCarrierConfig = new PersistableBundle();
167 private final TestLooper mLooper = new TestLooper();
168
Erik Kline8351faa2017-04-17 16:47:23 +0900169 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900170 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900171 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900172 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700173 private Tethering mTethering;
174
Erik Klineea9cc482017-03-10 19:35:34 +0900175 private class MockContext extends BroadcastInterceptingContext {
176 MockContext(Context base) {
177 super(base);
178 }
179
180 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900181 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
182
183 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900184 public ContentResolver getContentResolver() { return mContentResolver; }
185
186 @Override
187 public String getPackageName() { return "TetheringTest"; }
188
189 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900190 public Resources getResources() { return mResources; }
191
192 @Override
193 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900194 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900195 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900196 return super.getSystemService(name);
197 }
198 }
199
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900200 public class MockIpServerDependencies extends IpServer.Dependencies {
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900201 @Override
202 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
203 InterfaceParams ifParams) {
204 return mRouterAdvertisementDaemon;
205 }
206
207 @Override
208 public InterfaceParams getInterfaceParams(String ifName) {
209 assertTrue("Non-mocked interface " + ifName,
210 ifName.equals(TEST_USB_IFNAME)
211 || ifName.equals(TEST_WLAN_IFNAME)
212 || ifName.equals(TEST_MOBILE_IFNAME));
213 final String[] ifaces = new String[] {
214 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
215 return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
216 MacAddress.ALL_ZEROS_ADDRESS);
217 }
218
219 @Override
220 public INetd getNetdService() {
221 return mNetd;
222 }
223
224 @Override
225 public void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
226 DhcpServerCallbacks cb) {
227 new Thread(() -> {
228 try {
229 cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
230 } catch (RemoteException e) {
231 fail(e.getMessage());
232 }
233 }).run();
234 }
235 }
236
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900237 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900238 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900239 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900240 int isTetheringSupportedCalls;
241
242 public void reset() {
243 upstreamNetworkMonitorMasterSM = null;
244 ipv6CoordinatorNotifyList = null;
245 isTetheringSupportedCalls = 0;
246 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900247
248 @Override
249 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
250 return mOffloadHardwareInterface;
251 }
252
253 @Override
254 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
255 StateMachine target, SharedLog log, int what) {
256 upstreamNetworkMonitorMasterSM = target;
257 return mUpstreamNetworkMonitor;
258 }
259
260 @Override
261 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900262 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900263 ipv6CoordinatorNotifyList = notifyList;
264 return mIPv6TetheringCoordinator;
265 }
266
267 @Override
Remi NGUYEN VAN5db454c2019-02-14 18:04:20 +0900268 public IpServer.Dependencies getIpServerDependencies() {
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900269 return mIpServerDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900270 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900271
272 @Override
273 public boolean isTetheringSupported() {
274 isTetheringSupportedCalls++;
275 return true;
276 }
markchien0b595072019-01-08 23:52:21 +0800277
278 @Override
279 public int getDefaultDataSubscriptionId() {
280 return INVALID_SUBSCRIPTION_ID;
281 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900282 }
283
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900284 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
285 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900286 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900287 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
288 final LinkProperties prop = new LinkProperties();
289 prop.setInterfaceName(TEST_MOBILE_IFNAME);
290
291 if (withIPv4) {
292 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
293 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
294 }
295
296 if (withIPv6) {
297 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
298 prop.addLinkAddress(
299 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
300 NetworkConstants.RFC7421_PREFIX_LENGTH));
301 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
302 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
303 }
304
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900305 if (with464xlat) {
306 final LinkProperties stackedLink = new LinkProperties();
307 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
308 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
309 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
310
311 prop.addStackedLink(stackedLink);
312 }
313
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900314
315 final NetworkCapabilities capabilities = new NetworkCapabilities()
316 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
317 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
318 }
319
320 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900321 return buildMobileUpstreamState(true, false, false);
322 }
323
324 private static NetworkState buildMobileIPv6UpstreamState() {
325 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900326 }
327
328 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900329 return buildMobileUpstreamState(true, true, false);
330 }
331
332 private static NetworkState buildMobile464xlatUpstreamState() {
333 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900334 }
335
Erik Kline8351faa2017-04-17 16:47:23 +0900336 @Before
337 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700338 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700339 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
340 .thenReturn(new String[0]);
341 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900342 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700343 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900344 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700345 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
346 .thenReturn(new String[0]);
347 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
348 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900349 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
350 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900351 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900352 .thenReturn(new String[] {
353 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900354 when(mNMService.getInterfaceConfig(anyString()))
355 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900356 when(mRouterAdvertisementDaemon.start())
357 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900358
359 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900360 mContentResolver = new MockContentResolver(mServiceContext);
361 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900362 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900363 mIntents = new Vector<>();
364 mBroadcastReceiver = new BroadcastReceiver() {
365 @Override
366 public void onReceive(Context context, Intent intent) {
367 mIntents.addElement(intent);
368 }
369 };
370 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900371 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
372 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900373 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900374 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700375 }
376
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900377 private Tethering makeTethering() {
378 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
379 mLooper.getLooper(), mSystemProperties,
380 mTetheringDependencies);
381 }
382
Erik Kline8351faa2017-04-17 16:47:23 +0900383 @After
384 public void tearDown() {
385 mServiceContext.unregisterReceiver(mBroadcastReceiver);
386 }
387
Erik Klineea9cc482017-03-10 19:35:34 +0900388 private void sendWifiApStateChanged(int state) {
389 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900390 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900391 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
392 }
393
Erik Kline2efb8272017-05-31 15:53:53 +0900394 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
395 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
396 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
397 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
398 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
399 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
400 }
401
Erik Klinec438e302017-07-04 22:02:49 +0900402 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
403 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
404 intent.putExtra(USB_CONNECTED, connected);
405 intent.putExtra(USB_CONFIGURED, configured);
406 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
407 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
408 }
409
Erik Kline80b7a9f2018-02-28 15:01:35 +0900410 private void sendConfigurationChanged() {
411 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
412 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
413 }
414
Erik Kline9e225542017-06-08 17:48:48 +0900415 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900416 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900417 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900418 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
419 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900420 }
421
422 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
423 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
424 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900425 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900426 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
427 assertTrue(ifnames.contains(ifname));
428 mIntents.remove(bcast);
429 }
430
Erik Klinea9cde8b2017-06-20 21:18:31 +0900431 public void failingLocalOnlyHotspotLegacyApBroadcast(
432 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900433 // Emulate externally-visible WifiManager effects, causing the
434 // per-interface state machine to start up, and telling us that
435 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900436 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900437 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900438 }
Erik Kline9e225542017-06-08 17:48:48 +0900439 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900440 mLooper.dispatchAll();
441
Erik Kline7a4ccc62018-08-27 17:26:47 +0900442 // If, and only if, Tethering received an interface status changed then
443 // it creates a IpServer and sends out a broadcast indicating that the
444 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900445 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900446 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
447 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900448 }
Erik Kline9e225542017-06-08 17:48:48 +0900449 verifyNoMoreInteractions(mNMService);
450 verifyNoMoreInteractions(mWifiManager);
451 }
452
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900453 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900454 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900455 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
456 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900457
458 // Emulate pressing the USB tethering button in Settings UI.
459 mTethering.startTethering(TETHERING_USB, null, false);
460 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800461 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900462
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900463 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
464 }
465
466 @Test
467 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
468 NetworkState upstreamState = buildMobileIPv4UpstreamState();
469 prepareUsbTethering(upstreamState);
470
Erik Klinec438e302017-07-04 22:02:49 +0900471 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900472 verifyNoMoreInteractions(mNMService);
473
474 // Pretend we then receive USB configured broadcast.
475 sendUsbBroadcast(true, true, true);
476 mLooper.dispatchAll();
477 // Now we should see the start of tethering mechanics (in this case:
478 // tetherMatchingInterfaces() which starts by fetching all interfaces).
479 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900480
481 // UpstreamNetworkMonitor should receive selected upstream
482 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
483 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900484 }
485
486 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900487 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
488 failingLocalOnlyHotspotLegacyApBroadcast(true);
489 }
490
491 @Test
492 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
493 failingLocalOnlyHotspotLegacyApBroadcast(false);
494 }
495
496 public void workingLocalOnlyHotspotEnrichedApBroadcast(
497 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900498 // Emulate externally-visible WifiManager effects, causing the
499 // per-interface state machine to start up, and telling us that
500 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900501 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900502 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900503 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900504 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900505 mLooper.dispatchAll();
506
507 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900508 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900509 verify(mNMService, times(1)).setIpForwardingEnabled(true);
510 verify(mNMService, times(1)).startTethering(any(String[].class));
511 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900512 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900513 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900514 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900515 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
markchiena6c72872018-11-13 18:34:56 +0900516 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900517 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900518 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900519
520 // Emulate externally-visible WifiManager effects, when hotspot mode
521 // is being torn down.
522 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900523 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900524 mLooper.dispatchAll();
525
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900526 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900527 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900528 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900529 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900530 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900531 verify(mNMService, times(1)).stopTethering();
532 verify(mNMService, times(1)).setIpForwardingEnabled(false);
533 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900534 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900535 // Asking for the last error after the per-interface state machine
536 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900537 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900538 }
539
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900540 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900541 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900542 */
543 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
544 // IPv6TetheringCoordinator must have been notified of downstream
545 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
546 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900547 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900548
Erik Kline7a4ccc62018-08-27 17:26:47 +0900549 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900550 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900551 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900552 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
paulhud9736de2019-03-08 16:35:20 +0800553 upstreamState.linkProperties.isIpv6Provisioned()
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900554 ? ipv6OnlyState.linkProperties
555 : null);
556 }
557 mLooper.dispatchAll();
558 }
559
560 private void runUsbTethering(NetworkState upstreamState) {
561 prepareUsbTethering(upstreamState);
562 sendUsbBroadcast(true, true, true);
563 mLooper.dispatchAll();
564 }
565
566 @Test
567 public void workingMobileUsbTethering_IPv4() throws Exception {
568 NetworkState upstreamState = buildMobileIPv4UpstreamState();
569 runUsbTethering(upstreamState);
570
571 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
572 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
573
574 sendIPv6TetherUpdates(upstreamState);
575 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900576 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900577 }
578
579 @Test
580 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
581 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
582 mTethering = makeTethering();
583 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
584 runUsbTethering(upstreamState);
585 sendIPv6TetherUpdates(upstreamState);
586
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900587 verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900588 }
589
590 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900591 public void workingMobileUsbTethering_IPv6() throws Exception {
592 NetworkState upstreamState = buildMobileIPv6UpstreamState();
593 runUsbTethering(upstreamState);
594
595 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
596 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
597
598 sendIPv6TetherUpdates(upstreamState);
599 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
600 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
601 }
602
603 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900604 public void workingMobileUsbTethering_DualStack() throws Exception {
605 NetworkState upstreamState = buildMobileDualStackUpstreamState();
606 runUsbTethering(upstreamState);
607
608 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
609 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
610 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900611 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900612
613 sendIPv6TetherUpdates(upstreamState);
614 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
615 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
616 }
617
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900618 @Test
619 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
620 NetworkState upstreamState = buildMobile464xlatUpstreamState();
621 runUsbTethering(upstreamState);
622
623 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
624 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900625 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900626 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
627 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
628 TEST_XLAT_MOBILE_IFNAME);
629
630 sendIPv6TetherUpdates(upstreamState);
631 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
632 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
633 }
634
635 @Test
636 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
637 // Setup IPv6
638 NetworkState upstreamState = buildMobileIPv6UpstreamState();
639 runUsbTethering(upstreamState);
640
641 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900642 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900643 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
644
645 // Then 464xlat comes up
646 upstreamState = buildMobile464xlatUpstreamState();
647 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
648 .thenReturn(upstreamState);
649
650 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
651 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
652 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
653 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
654 0,
655 upstreamState);
656 mLooper.dispatchAll();
657
658 // Forwarding is added for 464xlat
659 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
660 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
661 TEST_XLAT_MOBILE_IFNAME);
662 // Forwarding was not re-added for v6 (still times(1))
663 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
664 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900665 // DHCP not restarted on downstream (still times(1))
Remi NGUYEN VAN0e3d09232018-12-04 12:13:09 +0900666 verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900667 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900668
Erik Klineea9cc482017-03-10 19:35:34 +0900669 @Test
Erik Kline72302902018-06-14 17:36:40 +0900670 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
671 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
672 .thenReturn(true);
673 sendConfigurationChanged();
674
675 // Setup IPv6
676 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
677 runUsbTethering(upstreamState);
678
679 // UpstreamNetworkMonitor should choose upstream automatically
680 // (in this specific case: choose the default network).
681 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
682 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
683
684 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
685 }
686
687 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900688 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
689 workingLocalOnlyHotspotEnrichedApBroadcast(true);
690 }
691
692 @Test
693 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
694 workingLocalOnlyHotspotEnrichedApBroadcast(false);
695 }
696
697 // TODO: Test with and without interfaceStatusChanged().
698 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900699 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900700 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900701
702 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900703 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900704 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900705 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900706 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900707 verifyNoMoreInteractions(mNMService);
708
709 // Emulate externally-visible WifiManager effects, causing the
710 // per-interface state machine to start up, and telling us that
711 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900712 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900713 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900714 mLooper.dispatchAll();
715
Erik Kline465ff3a2018-03-09 14:18:02 +0900716 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
717 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900718 verifyNoMoreInteractions(mNMService);
719 verifyNoMoreInteractions(mWifiManager);
720 }
721
Erik Klinea9cde8b2017-06-20 21:18:31 +0900722 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900723 @Test
724 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900725 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
726
727 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900728 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900729 mLooper.dispatchAll();
730 verify(mWifiManager, times(1)).startSoftAp(null);
731 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900732 verifyNoMoreInteractions(mNMService);
733
734 // Emulate externally-visible WifiManager effects, causing the
735 // per-interface state machine to start up, and telling us that
736 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900737 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
738 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900739 mLooper.dispatchAll();
740
741 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900742 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900743 verify(mNMService, times(1)).setIpForwardingEnabled(true);
744 verify(mNMService, times(1)).startTethering(any(String[].class));
745 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900746 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900747 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900748 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900749 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
markchiena6c72872018-11-13 18:34:56 +0900750 verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
Erik Klineea9cc482017-03-10 19:35:34 +0900751 // In tethering mode, in the default configuration, an explicit request
752 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900753 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900754 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900755 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900756
757 /////
758 // We do not currently emulate any upstream being found.
759 //
760 // This is why there are no calls to verify mNMService.enableNat() or
761 // mNMService.startInterfaceForwarding().
762 /////
763
764 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900765 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900766 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900767 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900768 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900769 verifyNoMoreInteractions(mNMService);
770
771 // Emulate externally-visible WifiManager effects, when tethering mode
772 // is being torn down.
773 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900774 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900775 mLooper.dispatchAll();
776
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900777 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900778 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900779 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900780 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900781 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900782 verify(mNMService, times(1)).stopTethering();
783 verify(mNMService, times(1)).setIpForwardingEnabled(false);
784 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900785 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900786 // Asking for the last error after the per-interface state machine
787 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900788 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900789 }
790
Erik Klinea9cde8b2017-06-20 21:18:31 +0900791 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900792 @Test
793 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900794 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
795 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
796
797 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900798 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900799 mLooper.dispatchAll();
800 verify(mWifiManager, times(1)).startSoftAp(null);
801 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900802 verifyNoMoreInteractions(mNMService);
803
804 // Emulate externally-visible WifiManager effects, causing the
805 // per-interface state machine to start up, and telling us that
806 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900807 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
808 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900809 mLooper.dispatchAll();
810
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900811 // We verify get/set called thrice here: twice for setup (on NMService) and once during
812 // teardown (on Netd) because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900813 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900814 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900815 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900816 verify(mNMService, times(2))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900817 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Remi NGUYEN VANd1b51a32019-01-22 16:13:57 +0900818 verify(mNetd, times(1)).interfaceSetCfg(argThat(p -> TEST_WLAN_IFNAME.equals(p.ifName)));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900819 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900820 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900821 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900822 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
823 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
824 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900825 // This is called, but will throw.
826 verify(mNMService, times(1)).setIpForwardingEnabled(true);
827 // This never gets called because of the exception thrown above.
828 verify(mNMService, times(0)).startTethering(any(String[].class));
829 // When the master state machine transitions to an error state it tells
830 // downstream interfaces, which causes us to tell Wi-Fi about the error
831 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900832 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900833 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900834 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900835
836 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900837 verifyNoMoreInteractions(mNMService);
838 }
839
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100840 private void userRestrictionsListenerBehaviour(
841 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
842 int expectedInteractionsWithShowNotification) throws Exception {
843 final int userId = 0;
844 final Bundle currRestrictions = new Bundle();
845 final Bundle newRestrictions = new Bundle();
846 Tethering tethering = mock(Tethering.class);
847 Tethering.TetheringUserRestrictionListener turl =
848 new Tethering.TetheringUserRestrictionListener(tethering);
849
850 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
851 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
852 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
853
854 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
855
856 verify(tethering, times(expectedInteractionsWithShowNotification))
857 .showTetheredNotification(anyInt(), eq(false));
858
859 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
860 }
861
862 @Test
863 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
864 final String[] emptyActiveIfacesList = new String[]{};
865 final boolean currDisallow = false;
866 final boolean nextDisallow = true;
867 final int expectedInteractionsWithShowNotification = 0;
868
869 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
870 expectedInteractionsWithShowNotification);
871 }
872
873 @Test
874 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900875 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100876 final boolean currDisallow = false;
877 final boolean nextDisallow = true;
878 final int expectedInteractionsWithShowNotification = 1;
879
880 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
881 expectedInteractionsWithShowNotification);
882 }
883
884 @Test
885 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
886 final String[] nonEmptyActiveIfacesList = new String[]{};
887 final boolean currDisallow = true;
888 final boolean nextDisallow = false;
889 final int expectedInteractionsWithShowNotification = 0;
890
891 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
892 expectedInteractionsWithShowNotification);
893 }
894
895 @Test
896 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900897 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100898 final boolean currDisallow = true;
899 final boolean nextDisallow = false;
900 final int expectedInteractionsWithShowNotification = 0;
901
902 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
903 expectedInteractionsWithShowNotification);
904 }
905
906 @Test
907 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900908 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100909 final int expectedInteractionsWithShowNotification = 0;
910 boolean currDisallow = true;
911 boolean nextDisallow = true;
912
913 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
914 expectedInteractionsWithShowNotification);
915
916 currDisallow = false;
917 nextDisallow = false;
918
919 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
920 expectedInteractionsWithShowNotification);
921 }
922
markchien26299ed2019-02-27 14:56:11 +0800923 private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
924 private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
925
926 public void expectUpstreamChanged(Network... networks) {
927 final ArrayList<Network> expectedUpstreams =
928 new ArrayList<Network>(Arrays.asList(networks));
929 for (Network upstream : expectedUpstreams) {
930 // throws OOB if no expectations
931 assertEquals(mActualUpstreams.remove(0), upstream);
932 }
933 assertNoCallback();
934 }
935
936 @Override
937 public void onUpstreamChanged(Network network) {
938 mActualUpstreams.add(network);
939 }
940
941 public void assertNoCallback() {
942 assertTrue(mActualUpstreams.isEmpty());
943 }
944 }
945
946 @Test
947 public void testRegisterTetheringEventCallback() throws Exception {
948 TestTetheringEventCallback callback1 = new TestTetheringEventCallback();
949 TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
950
951 // 1. Register one callback and run usb tethering.
952 mTethering.registerTetheringEventCallback(callback1);
953 mLooper.dispatchAll();
954 callback1.expectUpstreamChanged(new Network[] {null});
955 NetworkState upstreamState = buildMobileDualStackUpstreamState();
956 runUsbTethering(upstreamState);
957 callback1.expectUpstreamChanged(upstreamState.network);
958 // 2. Register second callback.
959 mTethering.registerTetheringEventCallback(callback2);
960 mLooper.dispatchAll();
961 callback2.expectUpstreamChanged(upstreamState.network);
962 // 3. Disable usb tethering.
963 mTethering.stopTethering(TETHERING_USB);
964 mLooper.dispatchAll();
965 sendUsbBroadcast(false, false, false);
966 mLooper.dispatchAll();
967 callback1.expectUpstreamChanged(new Network[] {null});
968 callback2.expectUpstreamChanged(new Network[] {null});
969 // 4. Unregister first callback and run hotspot.
970 mTethering.unregisterTetheringEventCallback(callback1);
971 mLooper.dispatchAll();
972 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
973 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
974 .thenReturn(upstreamState);
975 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
976 mTethering.startTethering(TETHERING_WIFI, null, false);
977 mLooper.dispatchAll();
978 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
979 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
980 mLooper.dispatchAll();
981 callback1.assertNoCallback();
982 callback2.expectUpstreamChanged(upstreamState.network);
983 }
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100984
Erik Kline1fdc2e22017-05-08 17:56:35 +0900985 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900986 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700987}