blob: a6ed9f252008dd0add748c0fc915bc1df5db2824 [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;
26import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
Erik Klinec438e302017-07-04 22:02:49 +090027import static android.net.ConnectivityManager.TETHERING_WIFI;
28import static android.net.ConnectivityManager.TETHERING_USB;
Erik Kline465ff3a2018-03-09 14:18:02 +090029import static android.net.ConnectivityManager.TYPE_MOBILE;
Erik Kline2efb8272017-05-31 15:53:53 +090030import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
31import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
32import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
33import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
34import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
35import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090036import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090037
Erik Klineea9cc482017-03-10 19:35:34 +090038import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070039import static org.junit.Assert.assertTrue;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090040import static org.mockito.ArgumentMatchers.argThat;
41import static org.mockito.ArgumentMatchers.notNull;
Christopher Wiley497c1472016-10-11 13:26:03 -070042import static org.mockito.Matchers.anyBoolean;
Erik Klineea9cc482017-03-10 19:35:34 +090043import static org.mockito.Matchers.anyInt;
44import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070045import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090046import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090047import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090048import static org.mockito.Mockito.doThrow;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090049import static org.mockito.Mockito.never;
Erik Klineea9cc482017-03-10 19:35:34 +090050import static org.mockito.Mockito.times;
51import static org.mockito.Mockito.verify;
52import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070053import static org.mockito.Mockito.when;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010054import static org.mockito.Mockito.mock;
Christopher Wiley497c1472016-10-11 13:26:03 -070055
Erik Kline8351faa2017-04-17 16:47:23 +090056import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090057import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070058import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090059import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090060import android.content.IntentFilter;
Erik Klinef3a08b42017-06-07 16:33:19 +090061import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070062import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090063import android.hardware.usb.UsbManager;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090064import android.net.INetd;
Christopher Wiley497c1472016-10-11 13:26:03 -070065import android.net.INetworkPolicyManager;
66import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090067import android.net.InterfaceConfiguration;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090068import android.net.IpPrefix;
69import android.net.LinkAddress;
70import android.net.LinkProperties;
71import android.net.MacAddress;
72import android.net.Network;
73import android.net.NetworkCapabilities;
74import android.net.NetworkInfo;
Erik Kline72302902018-06-14 17:36:40 +090075import android.net.NetworkRequest;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090076import android.net.NetworkState;
77import android.net.NetworkUtils;
78import android.net.RouteInfo;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090079import android.net.dhcp.DhcpServer;
80import android.net.dhcp.DhcpServingParams;
Erik Kline7a4ccc62018-08-27 17:26:47 +090081import android.net.ip.IpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +090082import android.net.ip.RouterAdvertisementDaemon;
83import android.net.util.InterfaceParams;
84import android.net.util.NetworkConstants;
Erik Klinef4b6e342017-04-25 19:19:59 +090085import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090086import android.net.wifi.WifiConfiguration;
87import android.net.wifi.WifiManager;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010088import android.os.Bundle;
Erik Klineea9cc482017-03-10 19:35:34 +090089import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070090import android.os.INetworkManagementService;
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +090091import android.os.Looper;
Christopher Wiley497c1472016-10-11 13:26:03 -070092import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090093import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070094import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090095import android.os.UserHandle;
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +010096import android.os.UserManager;
Erik Kline92c4db02017-05-31 10:21:32 +090097import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070098import android.support.test.filters.SmallTest;
99import android.support.test.runner.AndroidJUnit4;
100import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +0900101import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700102
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900103import com.android.internal.util.ArrayUtils;
104import com.android.internal.util.StateMachine;
Erik Klineea9cc482017-03-10 19:35:34 +0900105import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900106import com.android.internal.util.test.FakeSettingsProvider;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900107import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
Erik Kline5a7c8a02017-04-30 19:36:15 +0900108import com.android.server.connectivity.tethering.OffloadHardwareInterface;
109import com.android.server.connectivity.tethering.TetheringDependencies;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900110import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
Erik Klineea9cc482017-03-10 19:35:34 +0900111
Erik Kline8351faa2017-04-17 16:47:23 +0900112import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -0700113import org.junit.Before;
114import org.junit.Test;
115import org.junit.runner.RunWith;
116import org.mockito.Mock;
117import org.mockito.MockitoAnnotations;
118
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900119import java.net.Inet4Address;
120import java.net.Inet6Address;
Erik Kline8351faa2017-04-17 16:47:23 +0900121import java.util.ArrayList;
122import java.util.Vector;
123
Christopher Wiley497c1472016-10-11 13:26:03 -0700124@RunWith(AndroidJUnit4.class)
125@SmallTest
126public class TetheringTest {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900127 private static final int IFINDEX_OFFSET = 100;
128
Christopher Wiley497c1472016-10-11 13:26:03 -0700129 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900130 private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
131 private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
132 private static final String TEST_USB_IFNAME = "test_rndis0";
133 private static final String TEST_WLAN_IFNAME = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700134
Erik Kline72302902018-06-14 17:36:40 +0900135 // Actual contents of the request don't matter for this test. The lack of
136 // any specific TRANSPORT_* is sufficient to identify this request.
137 private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();
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 VANf5581f82018-09-28 11:34:15 +0900153 @Mock private DhcpServer mDhcpServer;
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900154 @Mock private INetd mNetd;
155
156 private final MockTetheringDependencies mTetheringDependencies =
157 new MockTetheringDependencies();
Christopher Wiley497c1472016-10-11 13:26:03 -0700158
159 // Like so many Android system APIs, these cannot be mocked because it is marked final.
160 // We have to use the real versions.
161 private final PersistableBundle mCarrierConfig = new PersistableBundle();
162 private final TestLooper mLooper = new TestLooper();
163
Erik Kline8351faa2017-04-17 16:47:23 +0900164 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900165 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900166 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900167 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700168 private Tethering mTethering;
169
Erik Klineea9cc482017-03-10 19:35:34 +0900170 private class MockContext extends BroadcastInterceptingContext {
171 MockContext(Context base) {
172 super(base);
173 }
174
175 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900176 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
177
178 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900179 public ContentResolver getContentResolver() { return mContentResolver; }
180
181 @Override
182 public String getPackageName() { return "TetheringTest"; }
183
184 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900185 public Resources getResources() { return mResources; }
186
187 @Override
188 public Object getSystemService(String name) {
Erik Klineea9cc482017-03-10 19:35:34 +0900189 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
Erik Klinec438e302017-07-04 22:02:49 +0900190 if (Context.USB_SERVICE.equals(name)) return mUsbManager;
Erik Klineea9cc482017-03-10 19:35:34 +0900191 return super.getSystemService(name);
192 }
193 }
194
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900195 public class MockTetheringDependencies extends TetheringDependencies {
Erik Kline465ff3a2018-03-09 14:18:02 +0900196 StateMachine upstreamNetworkMonitorMasterSM;
Erik Kline7a4ccc62018-08-27 17:26:47 +0900197 ArrayList<IpServer> ipv6CoordinatorNotifyList;
Erik Kline465ff3a2018-03-09 14:18:02 +0900198 int isTetheringSupportedCalls;
199
200 public void reset() {
201 upstreamNetworkMonitorMasterSM = null;
202 ipv6CoordinatorNotifyList = null;
203 isTetheringSupportedCalls = 0;
204 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900205
206 @Override
207 public OffloadHardwareInterface getOffloadHardwareInterface(Handler h, SharedLog log) {
208 return mOffloadHardwareInterface;
209 }
210
211 @Override
212 public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
213 StateMachine target, SharedLog log, int what) {
214 upstreamNetworkMonitorMasterSM = target;
215 return mUpstreamNetworkMonitor;
216 }
217
218 @Override
219 public IPv6TetheringCoordinator getIPv6TetheringCoordinator(
Erik Kline7a4ccc62018-08-27 17:26:47 +0900220 ArrayList<IpServer> notifyList, SharedLog log) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900221 ipv6CoordinatorNotifyList = notifyList;
222 return mIPv6TetheringCoordinator;
223 }
224
225 @Override
Erik Kline7a4ccc62018-08-27 17:26:47 +0900226 public IpServer.Dependencies getIpServerDependencies() {
227 return new IpServer.Dependencies() {
228 @Override
229 public RouterAdvertisementDaemon getRouterAdvertisementDaemon(
230 InterfaceParams ifParams) {
231 return mRouterAdvertisementDaemon;
232 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900233
Erik Kline7a4ccc62018-08-27 17:26:47 +0900234 @Override
235 public InterfaceParams getInterfaceParams(String ifName) {
236 final String[] ifaces = new String[] {
237 TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
238 final int index = ArrayUtils.indexOf(ifaces, ifName);
239 assertTrue("Non-mocked interface: " + ifName, index >= 0);
240 return new InterfaceParams(ifName, index + IFINDEX_OFFSET,
241 MacAddress.ALL_ZEROS_ADDRESS);
242 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900243
Erik Kline7a4ccc62018-08-27 17:26:47 +0900244 @Override
245 public INetd getNetdService() {
246 return mNetd;
247 }
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900248
249 @Override
250 public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
251 DhcpServingParams params, SharedLog log) {
252 return mDhcpServer;
253 }
Erik Kline7a4ccc62018-08-27 17:26:47 +0900254 };
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900255 }
Erik Kline465ff3a2018-03-09 14:18:02 +0900256
257 @Override
258 public boolean isTetheringSupported() {
259 isTetheringSupportedCalls++;
260 return true;
261 }
Erik Kline72302902018-06-14 17:36:40 +0900262
263 @Override
264 public NetworkRequest getDefaultNetworkRequest() {
265 return mDefaultRequest;
266 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900267 }
268
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900269 private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
270 boolean with464xlat) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900271 final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, 0, null, null);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900272 info.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
273 final LinkProperties prop = new LinkProperties();
274 prop.setInterfaceName(TEST_MOBILE_IFNAME);
275
276 if (withIPv4) {
277 prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
278 NetworkUtils.numericToInetAddress("10.0.0.1"), TEST_MOBILE_IFNAME));
279 }
280
281 if (withIPv6) {
282 prop.addDnsServer(NetworkUtils.numericToInetAddress("2001:db8::2"));
283 prop.addLinkAddress(
284 new LinkAddress(NetworkUtils.numericToInetAddress("2001:db8::"),
285 NetworkConstants.RFC7421_PREFIX_LENGTH));
286 prop.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
287 NetworkUtils.numericToInetAddress("2001:db8::1"), TEST_MOBILE_IFNAME));
288 }
289
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900290 if (with464xlat) {
291 final LinkProperties stackedLink = new LinkProperties();
292 stackedLink.setInterfaceName(TEST_XLAT_MOBILE_IFNAME);
293 stackedLink.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
294 NetworkUtils.numericToInetAddress("192.0.0.1"), TEST_XLAT_MOBILE_IFNAME));
295
296 prop.addStackedLink(stackedLink);
297 }
298
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900299
300 final NetworkCapabilities capabilities = new NetworkCapabilities()
301 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);;
302 return new NetworkState(info, prop, capabilities, new Network(100), null, "netid");
303 }
304
305 private static NetworkState buildMobileIPv4UpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900306 return buildMobileUpstreamState(true, false, false);
307 }
308
309 private static NetworkState buildMobileIPv6UpstreamState() {
310 return buildMobileUpstreamState(false, true, false);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900311 }
312
313 private static NetworkState buildMobileDualStackUpstreamState() {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900314 return buildMobileUpstreamState(true, true, false);
315 }
316
317 private static NetworkState buildMobile464xlatUpstreamState() {
318 return buildMobileUpstreamState(false, true, true);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900319 }
320
Erik Kline8351faa2017-04-17 16:47:23 +0900321 @Before
322 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700323 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700324 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
325 .thenReturn(new String[0]);
326 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900327 .thenReturn(new String[] { "test_rndis\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700328 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900329 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700330 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
331 .thenReturn(new String[0]);
332 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
333 .thenReturn(new int[0]);
Erik Kline72302902018-06-14 17:36:40 +0900334 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
335 .thenReturn(false);
Erik Klineea9cc482017-03-10 19:35:34 +0900336 when(mNMService.listInterfaces())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900337 .thenReturn(new String[] {
338 TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
Erik Klineea9cc482017-03-10 19:35:34 +0900339 when(mNMService.getInterfaceConfig(anyString()))
340 .thenReturn(new InterfaceConfiguration());
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900341 when(mRouterAdvertisementDaemon.start())
342 .thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900343
344 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900345 mContentResolver = new MockContentResolver(mServiceContext);
346 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900347 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
Erik Kline8351faa2017-04-17 16:47:23 +0900348 mIntents = new Vector<>();
349 mBroadcastReceiver = new BroadcastReceiver() {
350 @Override
351 public void onReceive(Context context, Intent intent) {
352 mIntents.addElement(intent);
353 }
354 };
355 mServiceContext.registerReceiver(mBroadcastReceiver,
Erik Kline465ff3a2018-03-09 14:18:02 +0900356 new IntentFilter(ACTION_TETHER_STATE_CHANGED));
357 mTetheringDependencies.reset();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900358 mTethering = makeTethering();
Lorenzo Colitti5a7dea12017-07-12 15:48:07 +0900359 verify(mNMService).registerTetheringStatsProvider(any(), anyString());
Christopher Wiley497c1472016-10-11 13:26:03 -0700360 }
361
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900362 private Tethering makeTethering() {
363 return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
364 mLooper.getLooper(), mSystemProperties,
365 mTetheringDependencies);
366 }
367
Erik Kline8351faa2017-04-17 16:47:23 +0900368 @After
369 public void tearDown() {
370 mServiceContext.unregisterReceiver(mBroadcastReceiver);
371 }
372
Christopher Wiley497c1472016-10-11 13:26:03 -0700373 private void setupForRequiredProvisioning() {
374 // Produce some acceptable looking provision app setting if requested.
375 when(mResources.getStringArray(
376 com.android.internal.R.array.config_mobile_hotspot_provision_app))
377 .thenReturn(PROVISIONING_APP_NAME);
378 // Don't disable tethering provisioning unless requested.
379 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
380 anyBoolean())).thenReturn(false);
381 // Act like the CarrierConfigManager is present and ready unless told otherwise.
382 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
383 .thenReturn(mCarrierConfigManager);
384 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
385 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
386 }
387
388 @Test
389 public void canRequireProvisioning() {
390 setupForRequiredProvisioning();
Erik Kline80b7a9f2018-02-28 15:01:35 +0900391 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700392 assertTrue(mTethering.isTetherProvisioningRequired());
393 }
394
395 @Test
396 public void toleratesCarrierConfigManagerMissing() {
397 setupForRequiredProvisioning();
398 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
399 .thenReturn(null);
Erik Kline80b7a9f2018-02-28 15:01:35 +0900400 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700401 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
402 // We therefore still require provisioning.
403 assertTrue(mTethering.isTetherProvisioningRequired());
404 }
405
406 @Test
407 public void toleratesCarrierConfigMissing() {
408 setupForRequiredProvisioning();
409 when(mCarrierConfigManager.getConfig()).thenReturn(null);
Erik Kline80b7a9f2018-02-28 15:01:35 +0900410 sendConfigurationChanged();
Christopher Wiley497c1472016-10-11 13:26:03 -0700411 // We still have a provisioning app configured, so still require provisioning.
412 assertTrue(mTethering.isTetherProvisioningRequired());
413 }
414
415 @Test
416 public void provisioningNotRequiredWhenAppNotFound() {
417 setupForRequiredProvisioning();
418 when(mResources.getStringArray(
419 com.android.internal.R.array.config_mobile_hotspot_provision_app))
420 .thenReturn(null);
421 assertTrue(!mTethering.isTetherProvisioningRequired());
422 when(mResources.getStringArray(
423 com.android.internal.R.array.config_mobile_hotspot_provision_app))
424 .thenReturn(new String[] {"malformedApp"});
425 assertTrue(!mTethering.isTetherProvisioningRequired());
426 }
Erik Klineea9cc482017-03-10 19:35:34 +0900427
428 private void sendWifiApStateChanged(int state) {
429 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900430 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900431 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
432 }
433
Erik Kline2efb8272017-05-31 15:53:53 +0900434 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
435 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
436 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
437 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
438 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
439 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
440 }
441
Erik Klinec438e302017-07-04 22:02:49 +0900442 private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
443 final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
444 intent.putExtra(USB_CONNECTED, connected);
445 intent.putExtra(USB_CONFIGURED, configured);
446 intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
447 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
448 }
449
Erik Kline80b7a9f2018-02-28 15:01:35 +0900450 private void sendConfigurationChanged() {
451 final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
452 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
453 }
454
Erik Kline9e225542017-06-08 17:48:48 +0900455 private void verifyInterfaceServingModeStarted() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900456 verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900457 verify(mNMService, times(1))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900458 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
459 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline8351faa2017-04-17 16:47:23 +0900460 }
461
462 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
463 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
464 final Intent bcast = mIntents.get(0);
Erik Kline465ff3a2018-03-09 14:18:02 +0900465 assertEquals(ACTION_TETHER_STATE_CHANGED, bcast.getAction());
Erik Kline8351faa2017-04-17 16:47:23 +0900466 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
467 assertTrue(ifnames.contains(ifname));
468 mIntents.remove(bcast);
469 }
470
Erik Klinea9cde8b2017-06-20 21:18:31 +0900471 public void failingLocalOnlyHotspotLegacyApBroadcast(
472 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900473 // Emulate externally-visible WifiManager effects, causing the
474 // per-interface state machine to start up, and telling us that
475 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900476 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900477 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900478 }
Erik Kline9e225542017-06-08 17:48:48 +0900479 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900480 mLooper.dispatchAll();
481
Erik Kline7a4ccc62018-08-27 17:26:47 +0900482 // If, and only if, Tethering received an interface status changed then
483 // it creates a IpServer and sends out a broadcast indicating that the
484 // interface is "available".
Erik Klinea9cde8b2017-06-20 21:18:31 +0900485 if (emulateInterfaceStatusChanged) {
Erik Kline465ff3a2018-03-09 14:18:02 +0900486 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
487 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900488 }
Erik Kline9e225542017-06-08 17:48:48 +0900489 verifyNoMoreInteractions(mNMService);
490 verifyNoMoreInteractions(mWifiManager);
491 }
492
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900493 private void prepareUsbTethering(NetworkState upstreamState) {
Erik Kline72302902018-06-14 17:36:40 +0900494 when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900495 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
496 .thenReturn(upstreamState);
Erik Klinec438e302017-07-04 22:02:49 +0900497
498 // Emulate pressing the USB tethering button in Settings UI.
499 mTethering.startTethering(TETHERING_USB, null, false);
500 mLooper.dispatchAll();
Jerry Zhang327b8092018-01-09 17:53:04 -0800501 verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
Erik Klinec438e302017-07-04 22:02:49 +0900502
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900503 mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
504 }
505
506 @Test
507 public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
508 NetworkState upstreamState = buildMobileIPv4UpstreamState();
509 prepareUsbTethering(upstreamState);
510
Erik Klinec438e302017-07-04 22:02:49 +0900511 // This should produce no activity of any kind.
Erik Klinec438e302017-07-04 22:02:49 +0900512 verifyNoMoreInteractions(mNMService);
513
514 // Pretend we then receive USB configured broadcast.
515 sendUsbBroadcast(true, true, true);
516 mLooper.dispatchAll();
517 // Now we should see the start of tethering mechanics (in this case:
518 // tetherMatchingInterfaces() which starts by fetching all interfaces).
519 verify(mNMService, times(1)).listInterfaces();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900520
521 // UpstreamNetworkMonitor should receive selected upstream
522 verify(mUpstreamNetworkMonitor, times(1)).selectPreferredUpstreamType(any());
523 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
Erik Klinec438e302017-07-04 22:02:49 +0900524 }
525
526 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900527 public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
528 failingLocalOnlyHotspotLegacyApBroadcast(true);
529 }
530
531 @Test
532 public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
533 failingLocalOnlyHotspotLegacyApBroadcast(false);
534 }
535
536 public void workingLocalOnlyHotspotEnrichedApBroadcast(
537 boolean emulateInterfaceStatusChanged) throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900538 // Emulate externally-visible WifiManager effects, causing the
539 // per-interface state machine to start up, and telling us that
540 // hotspot mode is to be started.
Erik Klinea9cde8b2017-06-20 21:18:31 +0900541 if (emulateInterfaceStatusChanged) {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900542 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Klinea9cde8b2017-06-20 21:18:31 +0900543 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900544 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline9e225542017-06-08 17:48:48 +0900545 mLooper.dispatchAll();
546
547 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900548 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900549 verify(mNMService, times(1)).setIpForwardingEnabled(true);
550 verify(mNMService, times(1)).startTethering(any(String[].class));
551 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900552 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900553 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
Erik Kline216af6d2017-04-27 20:57:23 +0900554 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900555 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
Erik Kline72302902018-06-14 17:36:40 +0900556 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900557 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900558 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900559
560 // Emulate externally-visible WifiManager effects, when hotspot mode
561 // is being torn down.
562 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900563 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900564 mLooper.dispatchAll();
565
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900566 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900567 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900568 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900569 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900570 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900571 verify(mNMService, times(1)).stopTethering();
572 verify(mNMService, times(1)).setIpForwardingEnabled(false);
573 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900574 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900575 // Asking for the last error after the per-interface state machine
576 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900577 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900578 }
579
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900580 /**
Erik Kline7a4ccc62018-08-27 17:26:47 +0900581 * Send CMD_IPV6_TETHER_UPDATE to IpServers as would be done by IPv6TetheringCoordinator.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900582 */
583 private void sendIPv6TetherUpdates(NetworkState upstreamState) {
584 // IPv6TetheringCoordinator must have been notified of downstream
585 verify(mIPv6TetheringCoordinator, times(1)).addActiveDownstream(
586 argThat(sm -> sm.linkProperties().getInterfaceName().equals(TEST_USB_IFNAME)),
Erik Kline7a4ccc62018-08-27 17:26:47 +0900587 eq(IpServer.STATE_TETHERED));
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900588
Erik Kline7a4ccc62018-08-27 17:26:47 +0900589 for (IpServer ipSrv :
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900590 mTetheringDependencies.ipv6CoordinatorNotifyList) {
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900591 NetworkState ipv6OnlyState = buildMobileUpstreamState(false, true, false);
Erik Kline7a4ccc62018-08-27 17:26:47 +0900592 ipSrv.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0,
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900593 upstreamState.linkProperties.isIPv6Provisioned()
594 ? ipv6OnlyState.linkProperties
595 : null);
596 }
597 mLooper.dispatchAll();
598 }
599
600 private void runUsbTethering(NetworkState upstreamState) {
601 prepareUsbTethering(upstreamState);
602 sendUsbBroadcast(true, true, true);
603 mLooper.dispatchAll();
604 }
605
606 @Test
607 public void workingMobileUsbTethering_IPv4() throws Exception {
608 NetworkState upstreamState = buildMobileIPv4UpstreamState();
609 runUsbTethering(upstreamState);
610
611 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
612 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
613
614 sendIPv6TetherUpdates(upstreamState);
615 verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900616 verify(mDhcpServer, times(1)).start();
617 }
618
619 @Test
620 public void workingMobileUsbTethering_IPv4LegacyDhcp() {
621 Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
622 mTethering = makeTethering();
623 final NetworkState upstreamState = buildMobileIPv4UpstreamState();
624 runUsbTethering(upstreamState);
625 sendIPv6TetherUpdates(upstreamState);
626
627 verify(mDhcpServer, never()).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900628 }
629
630 @Test
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900631 public void workingMobileUsbTethering_IPv6() throws Exception {
632 NetworkState upstreamState = buildMobileIPv6UpstreamState();
633 runUsbTethering(upstreamState);
634
635 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
636 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
637
638 sendIPv6TetherUpdates(upstreamState);
639 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
640 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
641 }
642
643 @Test
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900644 public void workingMobileUsbTethering_DualStack() throws Exception {
645 NetworkState upstreamState = buildMobileDualStackUpstreamState();
646 runUsbTethering(upstreamState);
647
648 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
649 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
650 verify(mRouterAdvertisementDaemon, times(1)).start();
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900651 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900652
653 sendIPv6TetherUpdates(upstreamState);
654 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
655 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
656 }
657
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900658 @Test
659 public void workingMobileUsbTethering_MultipleUpstreams() throws Exception {
660 NetworkState upstreamState = buildMobile464xlatUpstreamState();
661 runUsbTethering(upstreamState);
662
663 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
664 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900665 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900666 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
667 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
668 TEST_XLAT_MOBILE_IFNAME);
669
670 sendIPv6TetherUpdates(upstreamState);
671 verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
672 verify(mNetd, times(1)).tetherApplyDnsInterfaces();
673 }
674
675 @Test
676 public void workingMobileUsbTethering_v6Then464xlat() throws Exception {
677 // Setup IPv6
678 NetworkState upstreamState = buildMobileIPv6UpstreamState();
679 runUsbTethering(upstreamState);
680
681 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900682 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900683 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
684
685 // Then 464xlat comes up
686 upstreamState = buildMobile464xlatUpstreamState();
687 when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
688 .thenReturn(upstreamState);
689
690 // Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
691 mTetheringDependencies.upstreamNetworkMonitorMasterSM.sendMessage(
692 Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
693 UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
694 0,
695 upstreamState);
696 mLooper.dispatchAll();
697
698 // Forwarding is added for 464xlat
699 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
700 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
701 TEST_XLAT_MOBILE_IFNAME);
702 // Forwarding was not re-added for v6 (still times(1))
703 verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
704 verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
Remi NGUYEN VANf5581f82018-09-28 11:34:15 +0900705 // DHCP not restarted on downstream (still times(1))
706 verify(mDhcpServer, times(1)).start();
Remi NGUYEN VAN25a7e4f2018-03-09 14:07:18 +0900707 }
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900708
Erik Klineea9cc482017-03-10 19:35:34 +0900709 @Test
Erik Kline72302902018-06-14 17:36:40 +0900710 public void configTetherUpstreamAutomaticIgnoresConfigTetherUpstreamTypes() throws Exception {
711 when(mResources.getBoolean(com.android.internal.R.bool.config_tether_upstream_automatic))
712 .thenReturn(true);
713 sendConfigurationChanged();
714
715 // Setup IPv6
716 final NetworkState upstreamState = buildMobileIPv6UpstreamState();
717 runUsbTethering(upstreamState);
718
719 // UpstreamNetworkMonitor should choose upstream automatically
720 // (in this specific case: choose the default network).
721 verify(mUpstreamNetworkMonitor, times(1)).getCurrentPreferredUpstream();
722 verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
723
724 verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
725 }
726
727 @Test
Erik Klinea9cde8b2017-06-20 21:18:31 +0900728 public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
729 workingLocalOnlyHotspotEnrichedApBroadcast(true);
730 }
731
732 @Test
733 public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
734 workingLocalOnlyHotspotEnrichedApBroadcast(false);
735 }
736
737 // TODO: Test with and without interfaceStatusChanged().
738 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900739 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineceb54c62017-04-18 14:22:25 +0900740 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900741
742 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900743 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Klineea9cc482017-03-10 19:35:34 +0900744 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900745 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900746 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900747 verifyNoMoreInteractions(mNMService);
748
749 // Emulate externally-visible WifiManager effects, causing the
750 // per-interface state machine to start up, and telling us that
751 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900752 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
Erik Kline9e225542017-06-08 17:48:48 +0900753 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900754 mLooper.dispatchAll();
755
Erik Kline465ff3a2018-03-09 14:18:02 +0900756 assertEquals(1, mTetheringDependencies.isTetheringSupportedCalls);
757 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline9e225542017-06-08 17:48:48 +0900758 verifyNoMoreInteractions(mNMService);
759 verifyNoMoreInteractions(mWifiManager);
760 }
761
Erik Klinea9cde8b2017-06-20 21:18:31 +0900762 // TODO: Test with and without interfaceStatusChanged().
Erik Kline9e225542017-06-08 17:48:48 +0900763 @Test
764 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
Erik Kline9e225542017-06-08 17:48:48 +0900765 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
766
767 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900768 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline9e225542017-06-08 17:48:48 +0900769 mLooper.dispatchAll();
770 verify(mWifiManager, times(1)).startSoftAp(null);
771 verifyNoMoreInteractions(mWifiManager);
Erik Kline9e225542017-06-08 17:48:48 +0900772 verifyNoMoreInteractions(mNMService);
773
774 // Emulate externally-visible WifiManager effects, causing the
775 // per-interface state machine to start up, and telling us that
776 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900777 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
778 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline9e225542017-06-08 17:48:48 +0900779 mLooper.dispatchAll();
780
781 verifyInterfaceServingModeStarted();
Erik Kline465ff3a2018-03-09 14:18:02 +0900782 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900783 verify(mNMService, times(1)).setIpForwardingEnabled(true);
784 verify(mNMService, times(1)).startTethering(any(String[].class));
785 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900786 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900787 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline216af6d2017-04-27 20:57:23 +0900788 verifyNoMoreInteractions(mWifiManager);
Erik Kline465ff3a2018-03-09 14:18:02 +0900789 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
Erik Kline72302902018-06-14 17:36:40 +0900790 verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900791 // In tethering mode, in the default configuration, an explicit request
792 // for a mobile network is also made.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900793 verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
Erik Klineea9cc482017-03-10 19:35:34 +0900794 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
Erik Kline465ff3a2018-03-09 14:18:02 +0900795 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
Erik Klineea9cc482017-03-10 19:35:34 +0900796
797 /////
798 // We do not currently emulate any upstream being found.
799 //
800 // This is why there are no calls to verify mNMService.enableNat() or
801 // mNMService.startInterfaceForwarding().
802 /////
803
804 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900805 mTethering.stopTethering(TETHERING_WIFI);
Erik Klineea9cc482017-03-10 19:35:34 +0900806 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900807 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900808 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900809 verifyNoMoreInteractions(mNMService);
810
811 // Emulate externally-visible WifiManager effects, when tethering mode
812 // is being torn down.
813 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900814 mTethering.interfaceRemoved(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900815 mLooper.dispatchAll();
816
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900817 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900818 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900819 verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900820 verify(mNMService, atLeastOnce())
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900821 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
Erik Klineea9cc482017-03-10 19:35:34 +0900822 verify(mNMService, times(1)).stopTethering();
823 verify(mNMService, times(1)).setIpForwardingEnabled(false);
824 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900825 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900826 // Asking for the last error after the per-interface state machine
827 // has been reaped yields an unknown interface error.
Erik Kline465ff3a2018-03-09 14:18:02 +0900828 assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_WLAN_IFNAME));
Erik Klineea9cc482017-03-10 19:35:34 +0900829 }
830
Erik Klinea9cde8b2017-06-20 21:18:31 +0900831 // TODO: Test with and without interfaceStatusChanged().
Erik Kline1fdc2e22017-05-08 17:56:35 +0900832 @Test
833 public void failureEnablingIpForwarding() throws Exception {
Erik Kline1fdc2e22017-05-08 17:56:35 +0900834 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
835 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
836
837 // Emulate pressing the WiFi tethering button.
Erik Klinec438e302017-07-04 22:02:49 +0900838 mTethering.startTethering(TETHERING_WIFI, null, false);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900839 mLooper.dispatchAll();
840 verify(mWifiManager, times(1)).startSoftAp(null);
841 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900842 verifyNoMoreInteractions(mNMService);
843
844 // Emulate externally-visible WifiManager effects, causing the
845 // per-interface state machine to start up, and telling us that
846 // tethering mode is to be started.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900847 mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
848 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900849 mLooper.dispatchAll();
850
Erik Kline472276a2018-05-18 16:09:24 +0900851 // We verify get/set called thrice here: once for setup and twice during
Erik Kline1fdc2e22017-05-08 17:56:35 +0900852 // teardown because all events happen over the course of the single
Erik Kline7a4ccc62018-08-27 17:26:47 +0900853 // dispatchAll() above. Note that once the IpServer IPv4 address config
Erik Kline472276a2018-05-18 16:09:24 +0900854 // code is refactored the two calls during shutdown will revert to one.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900855 verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
Erik Kline472276a2018-05-18 16:09:24 +0900856 verify(mNMService, times(3))
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900857 .setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
858 verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900859 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900860 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
Erik Kline465ff3a2018-03-09 14:18:02 +0900861 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
862 assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
863 verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900864 // This is called, but will throw.
865 verify(mNMService, times(1)).setIpForwardingEnabled(true);
866 // This never gets called because of the exception thrown above.
867 verify(mNMService, times(0)).startTethering(any(String[].class));
868 // When the master state machine transitions to an error state it tells
869 // downstream interfaces, which causes us to tell Wi-Fi about the error
870 // so it can take down AP mode.
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900871 verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900872 verify(mWifiManager).updateInterfaceIpState(
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900873 TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900874
875 verifyNoMoreInteractions(mWifiManager);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900876 verifyNoMoreInteractions(mNMService);
877 }
878
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100879 private void userRestrictionsListenerBehaviour(
880 boolean currentDisallow, boolean nextDisallow, String[] activeTetheringIfacesList,
881 int expectedInteractionsWithShowNotification) throws Exception {
882 final int userId = 0;
883 final Bundle currRestrictions = new Bundle();
884 final Bundle newRestrictions = new Bundle();
885 Tethering tethering = mock(Tethering.class);
886 Tethering.TetheringUserRestrictionListener turl =
887 new Tethering.TetheringUserRestrictionListener(tethering);
888
889 currRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, currentDisallow);
890 newRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_TETHERING, nextDisallow);
891 when(tethering.getTetheredIfaces()).thenReturn(activeTetheringIfacesList);
892
893 turl.onUserRestrictionsChanged(userId, newRestrictions, currRestrictions);
894
895 verify(tethering, times(expectedInteractionsWithShowNotification))
896 .showTetheredNotification(anyInt(), eq(false));
897
898 verify(tethering, times(expectedInteractionsWithShowNotification)).untetherAll();
899 }
900
901 @Test
902 public void testDisallowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
903 final String[] emptyActiveIfacesList = new String[]{};
904 final boolean currDisallow = false;
905 final boolean nextDisallow = true;
906 final int expectedInteractionsWithShowNotification = 0;
907
908 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, emptyActiveIfacesList,
909 expectedInteractionsWithShowNotification);
910 }
911
912 @Test
913 public void testDisallowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900914 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100915 final boolean currDisallow = false;
916 final boolean nextDisallow = true;
917 final int expectedInteractionsWithShowNotification = 1;
918
919 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
920 expectedInteractionsWithShowNotification);
921 }
922
923 @Test
924 public void testAllowTetheringWhenNoTetheringInterfaceIsActive() throws Exception {
925 final String[] nonEmptyActiveIfacesList = new String[]{};
926 final boolean currDisallow = true;
927 final boolean nextDisallow = false;
928 final int expectedInteractionsWithShowNotification = 0;
929
930 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
931 expectedInteractionsWithShowNotification);
932 }
933
934 @Test
935 public void testAllowTetheringWhenAtLeastOneTetheringInterfaceIsActive() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900936 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100937 final boolean currDisallow = true;
938 final boolean nextDisallow = false;
939 final int expectedInteractionsWithShowNotification = 0;
940
941 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
942 expectedInteractionsWithShowNotification);
943 }
944
945 @Test
946 public void testDisallowTetheringUnchanged() throws Exception {
Remi NGUYEN VANa911e842018-03-15 11:57:14 +0900947 final String[] nonEmptyActiveIfacesList = new String[]{TEST_WLAN_IFNAME};
Alexandru-Andrei Rotarufa6d5c52017-07-18 16:49:22 +0100948 final int expectedInteractionsWithShowNotification = 0;
949 boolean currDisallow = true;
950 boolean nextDisallow = true;
951
952 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
953 expectedInteractionsWithShowNotification);
954
955 currDisallow = false;
956 nextDisallow = false;
957
958 userRestrictionsListenerBehaviour(currDisallow, nextDisallow, nonEmptyActiveIfacesList,
959 expectedInteractionsWithShowNotification);
960 }
961
962
Erik Kline1fdc2e22017-05-08 17:56:35 +0900963 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900964 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700965}