blob: b6922d4be6ff70b2d822908773c50a57c15a1cad [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 Kline2efb8272017-05-31 15:53:53 +090019import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
20import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
21import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
22import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
23import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
24import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
Erik Klineea9cc482017-03-10 19:35:34 +090025import static org.junit.Assert.assertEquals;
Christopher Wiley497c1472016-10-11 13:26:03 -070026import static org.junit.Assert.assertTrue;
27import static org.mockito.Matchers.anyBoolean;
Erik Klineea9cc482017-03-10 19:35:34 +090028import static org.mockito.Matchers.anyInt;
29import static org.mockito.Matchers.anyString;
Christopher Wiley497c1472016-10-11 13:26:03 -070030import static org.mockito.Matchers.eq;
Erik Kline1fdc2e22017-05-08 17:56:35 +090031import static org.mockito.Mockito.any;
Erik Klineea9cc482017-03-10 19:35:34 +090032import static org.mockito.Mockito.atLeastOnce;
Erik Kline1fdc2e22017-05-08 17:56:35 +090033import static org.mockito.Mockito.doThrow;
Erik Klineea9cc482017-03-10 19:35:34 +090034import static org.mockito.Mockito.times;
35import static org.mockito.Mockito.verify;
36import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley497c1472016-10-11 13:26:03 -070037import static org.mockito.Mockito.when;
38
Erik Kline8351faa2017-04-17 16:47:23 +090039import android.content.BroadcastReceiver;
Erik Kline92c4db02017-05-31 10:21:32 +090040import android.content.ContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070041import android.content.Context;
Erik Klineea9cc482017-03-10 19:35:34 +090042import android.content.ContextWrapper;
43import android.content.Intent;
Erik Kline8351faa2017-04-17 16:47:23 +090044import android.content.IntentFilter;
Christopher Wiley497c1472016-10-11 13:26:03 -070045import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090046import android.hardware.usb.UsbManager;
47import android.net.ConnectivityManager;
48import android.net.ConnectivityManager.NetworkCallback;
Christopher Wiley497c1472016-10-11 13:26:03 -070049import android.net.INetworkPolicyManager;
50import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090051import android.net.InterfaceConfiguration;
52import android.net.NetworkRequest;
Erik Klinef4b6e342017-04-25 19:19:59 +090053import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090054import android.net.wifi.WifiConfiguration;
55import android.net.wifi.WifiManager;
56import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070057import android.os.INetworkManagementService;
58import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090059import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070060import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090061import android.os.UserHandle;
Erik Kline92c4db02017-05-31 10:21:32 +090062import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070063import android.support.test.filters.SmallTest;
64import android.support.test.runner.AndroidJUnit4;
65import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090066import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070067
Erik Klineea9cc482017-03-10 19:35:34 +090068import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +090069import com.android.internal.util.test.FakeSettingsProvider;
Erik Kline5a7c8a02017-04-30 19:36:15 +090070import com.android.server.connectivity.tethering.OffloadHardwareInterface;
71import com.android.server.connectivity.tethering.TetheringDependencies;
Erik Klineea9cc482017-03-10 19:35:34 +090072
Erik Kline8351faa2017-04-17 16:47:23 +090073import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -070074import org.junit.Before;
75import org.junit.Test;
76import org.junit.runner.RunWith;
77import org.mockito.Mock;
78import org.mockito.MockitoAnnotations;
79
Erik Kline8351faa2017-04-17 16:47:23 +090080import java.util.ArrayList;
81import java.util.Vector;
82
Christopher Wiley497c1472016-10-11 13:26:03 -070083@RunWith(AndroidJUnit4.class)
84@SmallTest
85public class TetheringTest {
86 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
87
88 @Mock private Context mContext;
Erik Klineea9cc482017-03-10 19:35:34 +090089 @Mock private ConnectivityManager mConnectivityManager;
Christopher Wiley497c1472016-10-11 13:26:03 -070090 @Mock private INetworkManagementService mNMService;
91 @Mock private INetworkStatsService mStatsService;
92 @Mock private INetworkPolicyManager mPolicyManager;
93 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +090094 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -070095 @Mock private Resources mResources;
Erik Kline5a7c8a02017-04-30 19:36:15 +090096 @Mock private TetheringDependencies mTetheringDependencies;
Erik Klineea9cc482017-03-10 19:35:34 +090097 @Mock private UsbManager mUsbManager;
98 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -070099 @Mock private CarrierConfigManager mCarrierConfigManager;
100
101 // Like so many Android system APIs, these cannot be mocked because it is marked final.
102 // We have to use the real versions.
103 private final PersistableBundle mCarrierConfig = new PersistableBundle();
104 private final TestLooper mLooper = new TestLooper();
Erik Klineea9cc482017-03-10 19:35:34 +0900105 private final String mTestIfname = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700106
Erik Kline8351faa2017-04-17 16:47:23 +0900107 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900108 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900109 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900110 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700111 private Tethering mTethering;
112
Erik Klineea9cc482017-03-10 19:35:34 +0900113 private class MockContext extends BroadcastInterceptingContext {
114 MockContext(Context base) {
115 super(base);
116 }
117
118 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900119 public ContentResolver getContentResolver() { return mContentResolver; }
120
121 @Override
122 public String getPackageName() { return "TetheringTest"; }
123
124 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900125 public Resources getResources() { return mResources; }
126
127 @Override
128 public Object getSystemService(String name) {
129 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
130 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
131 return super.getSystemService(name);
132 }
133 }
134
Erik Kline8351faa2017-04-17 16:47:23 +0900135 @Before
136 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700137 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700138 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
139 .thenReturn(new String[0]);
140 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
141 .thenReturn(new String[0]);
142 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Erik Klineea9cc482017-03-10 19:35:34 +0900143 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700144 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
145 .thenReturn(new String[0]);
146 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
147 .thenReturn(new int[0]);
Erik Klineea9cc482017-03-10 19:35:34 +0900148 when(mNMService.listInterfaces())
149 .thenReturn(new String[]{ "test_rmnet_data0", mTestIfname });
150 when(mNMService.getInterfaceConfig(anyString()))
151 .thenReturn(new InterfaceConfiguration());
152
153 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900154 mContentResolver = new MockContentResolver(mServiceContext);
155 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900156 mIntents = new Vector<>();
157 mBroadcastReceiver = new BroadcastReceiver() {
158 @Override
159 public void onReceive(Context context, Intent intent) {
160 mIntents.addElement(intent);
161 }
162 };
163 mServiceContext.registerReceiver(mBroadcastReceiver,
164 new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
Erik Klinef4b6e342017-04-25 19:19:59 +0900165 when(mTetheringDependencies.getOffloadHardwareInterface(
166 any(Handler.class), any(SharedLog.class))).thenReturn(mOffloadHardwareInterface);
Erik Klineea9cc482017-03-10 19:35:34 +0900167 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900168 mLooper.getLooper(), mSystemProperties,
169 mTetheringDependencies);
Christopher Wiley497c1472016-10-11 13:26:03 -0700170 }
171
Erik Kline8351faa2017-04-17 16:47:23 +0900172 @After
173 public void tearDown() {
174 mServiceContext.unregisterReceiver(mBroadcastReceiver);
175 }
176
Christopher Wiley497c1472016-10-11 13:26:03 -0700177 private void setupForRequiredProvisioning() {
178 // Produce some acceptable looking provision app setting if requested.
179 when(mResources.getStringArray(
180 com.android.internal.R.array.config_mobile_hotspot_provision_app))
181 .thenReturn(PROVISIONING_APP_NAME);
182 // Don't disable tethering provisioning unless requested.
183 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
184 anyBoolean())).thenReturn(false);
185 // Act like the CarrierConfigManager is present and ready unless told otherwise.
186 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
187 .thenReturn(mCarrierConfigManager);
188 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
189 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
190 }
191
192 @Test
193 public void canRequireProvisioning() {
194 setupForRequiredProvisioning();
195 assertTrue(mTethering.isTetherProvisioningRequired());
196 }
197
198 @Test
199 public void toleratesCarrierConfigManagerMissing() {
200 setupForRequiredProvisioning();
201 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
202 .thenReturn(null);
203 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
204 // We therefore still require provisioning.
205 assertTrue(mTethering.isTetherProvisioningRequired());
206 }
207
208 @Test
209 public void toleratesCarrierConfigMissing() {
210 setupForRequiredProvisioning();
211 when(mCarrierConfigManager.getConfig()).thenReturn(null);
212 // We still have a provisioning app configured, so still require provisioning.
213 assertTrue(mTethering.isTetherProvisioningRequired());
214 }
215
216 @Test
217 public void provisioningNotRequiredWhenAppNotFound() {
218 setupForRequiredProvisioning();
219 when(mResources.getStringArray(
220 com.android.internal.R.array.config_mobile_hotspot_provision_app))
221 .thenReturn(null);
222 assertTrue(!mTethering.isTetherProvisioningRequired());
223 when(mResources.getStringArray(
224 com.android.internal.R.array.config_mobile_hotspot_provision_app))
225 .thenReturn(new String[] {"malformedApp"});
226 assertTrue(!mTethering.isTetherProvisioningRequired());
227 }
Erik Klineea9cc482017-03-10 19:35:34 +0900228
229 private void sendWifiApStateChanged(int state) {
230 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900231 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900232 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
233 }
234
Erik Kline2efb8272017-05-31 15:53:53 +0900235 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
236 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
237 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
238 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
239 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
240 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
241 }
242
243 private void verifyInterfaceServingModeStarted(boolean ifnameKnown) throws Exception {
244 if (!ifnameKnown) {
245 verify(mNMService, times(1)).listInterfaces();
246 }
Erik Kline8351faa2017-04-17 16:47:23 +0900247 verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
248 verify(mNMService, times(1))
249 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
250 verify(mNMService, times(1)).tetherInterface(mTestIfname);
251 }
252
253 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
254 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
255 final Intent bcast = mIntents.get(0);
256 assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
257 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
258 assertTrue(ifnames.contains(ifname));
259 mIntents.remove(bcast);
260 }
261
Erik Kline2efb8272017-05-31 15:53:53 +0900262 public void workingLocalOnlyHotspot(boolean enrichedApBroadcast) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900263 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900264
265 // Emulate externally-visible WifiManager effects, causing the
266 // per-interface state machine to start up, and telling us that
267 // hotspot mode is to be started.
268 mTethering.interfaceStatusChanged(mTestIfname, true);
Erik Kline2efb8272017-05-31 15:53:53 +0900269 if (enrichedApBroadcast) {
270 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
271 } else {
272 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
273 }
Erik Klineea9cc482017-03-10 19:35:34 +0900274 mLooper.dispatchAll();
275
Erik Kline2efb8272017-05-31 15:53:53 +0900276 verifyInterfaceServingModeStarted(enrichedApBroadcast);
Erik Kline8351faa2017-04-17 16:47:23 +0900277 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900278 verify(mNMService, times(1)).setIpForwardingEnabled(true);
279 verify(mNMService, times(1)).startTethering(any(String[].class));
280 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900281 verify(mWifiManager).updateInterfaceIpState(
282 mTestIfname, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
283 verifyNoMoreInteractions(mWifiManager);
Erik Kline8351faa2017-04-17 16:47:23 +0900284 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
Erik Klineea9cc482017-03-10 19:35:34 +0900285 // UpstreamNetworkMonitor will be started, and will register two callbacks:
286 // a "listen all" and a "track default".
287 verify(mConnectivityManager, times(1)).registerNetworkCallback(
288 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
289 verify(mConnectivityManager, times(1)).registerDefaultNetworkCallback(
290 any(NetworkCallback.class), any(Handler.class));
291 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
292 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
293 verifyNoMoreInteractions(mConnectivityManager);
294
295 // Emulate externally-visible WifiManager effects, when hotspot mode
296 // is being torn down.
297 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
298 mTethering.interfaceRemoved(mTestIfname);
299 mLooper.dispatchAll();
300
301 verify(mNMService, times(1)).untetherInterface(mTestIfname);
302 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
303 verify(mNMService, atLeastOnce()).getInterfaceConfig(mTestIfname);
304 verify(mNMService, atLeastOnce())
305 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
306 verify(mNMService, times(1)).stopTethering();
307 verify(mNMService, times(1)).setIpForwardingEnabled(false);
308 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900309 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900310 // Asking for the last error after the per-interface state machine
311 // has been reaped yields an unknown interface error.
312 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
313 mTethering.getLastTetherError(mTestIfname));
314 }
315
316 @Test
Erik Kline2efb8272017-05-31 15:53:53 +0900317 public void workingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
318 workingLocalOnlyHotspot(false);
319 }
320
321 @Test
322 public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
323 workingLocalOnlyHotspot(true);
324 }
325
326 public void workingWifiTethering(boolean enrichedApBroadcast) throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900327 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineceb54c62017-04-18 14:22:25 +0900328 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900329
330 // Emulate pressing the WiFi tethering button.
331 mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
332 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900333 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900334 verifyNoMoreInteractions(mWifiManager);
335 verifyNoMoreInteractions(mConnectivityManager);
336 verifyNoMoreInteractions(mNMService);
337
338 // Emulate externally-visible WifiManager effects, causing the
339 // per-interface state machine to start up, and telling us that
340 // tethering mode is to be started.
341 mTethering.interfaceStatusChanged(mTestIfname, true);
Erik Kline2efb8272017-05-31 15:53:53 +0900342 if (enrichedApBroadcast) {
343 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
344 } else {
345 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
346 }
Erik Klineea9cc482017-03-10 19:35:34 +0900347 mLooper.dispatchAll();
348
Erik Kline2efb8272017-05-31 15:53:53 +0900349 verifyInterfaceServingModeStarted(enrichedApBroadcast);
Erik Kline8351faa2017-04-17 16:47:23 +0900350 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900351 verify(mNMService, times(1)).setIpForwardingEnabled(true);
352 verify(mNMService, times(1)).startTethering(any(String[].class));
353 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900354 verify(mWifiManager).updateInterfaceIpState(
355 mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED);
356 verifyNoMoreInteractions(mWifiManager);
Erik Kline8351faa2017-04-17 16:47:23 +0900357 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900358 // UpstreamNetworkMonitor will be started, and will register two callbacks:
359 // a "listen all" and a "track default".
360 verify(mConnectivityManager, times(1)).registerNetworkCallback(
361 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
362 verify(mConnectivityManager, times(1)).registerDefaultNetworkCallback(
363 any(NetworkCallback.class), any(Handler.class));
364 // In tethering mode, in the default configuration, an explicit request
365 // for a mobile network is also made.
366 verify(mConnectivityManager, atLeastOnce()).getNetworkInfo(anyInt());
367 verify(mConnectivityManager, times(1)).requestNetwork(
368 any(NetworkRequest.class), any(NetworkCallback.class), eq(0), anyInt(),
369 any(Handler.class));
370 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
371 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
372 verifyNoMoreInteractions(mConnectivityManager);
373
374 /////
375 // We do not currently emulate any upstream being found.
376 //
377 // This is why there are no calls to verify mNMService.enableNat() or
378 // mNMService.startInterfaceForwarding().
379 /////
380
381 // Emulate pressing the WiFi tethering button.
382 mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI);
383 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900384 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900385 verifyNoMoreInteractions(mWifiManager);
386 verifyNoMoreInteractions(mConnectivityManager);
387 verifyNoMoreInteractions(mNMService);
388
389 // Emulate externally-visible WifiManager effects, when tethering mode
390 // is being torn down.
391 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
392 mTethering.interfaceRemoved(mTestIfname);
393 mLooper.dispatchAll();
394
395 verify(mNMService, times(1)).untetherInterface(mTestIfname);
396 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
397 verify(mNMService, atLeastOnce()).getInterfaceConfig(mTestIfname);
398 verify(mNMService, atLeastOnce())
399 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
400 verify(mNMService, times(1)).stopTethering();
401 verify(mNMService, times(1)).setIpForwardingEnabled(false);
402 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900403 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900404 // Asking for the last error after the per-interface state machine
405 // has been reaped yields an unknown interface error.
406 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
407 mTethering.getLastTetherError(mTestIfname));
408 }
409
Erik Kline1fdc2e22017-05-08 17:56:35 +0900410 @Test
Erik Kline2efb8272017-05-31 15:53:53 +0900411 public void workingWifiTetheringLegacyApBroadcast() throws Exception {
412 workingWifiTethering(false);
413 }
414
415 @Test
416 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
417 workingWifiTethering(true);
418 }
419
420 @Test
Erik Kline1fdc2e22017-05-08 17:56:35 +0900421 public void failureEnablingIpForwarding() throws Exception {
422 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
423 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
424 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
425
426 // Emulate pressing the WiFi tethering button.
427 mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
428 mLooper.dispatchAll();
429 verify(mWifiManager, times(1)).startSoftAp(null);
430 verifyNoMoreInteractions(mWifiManager);
431 verifyNoMoreInteractions(mConnectivityManager);
432 verifyNoMoreInteractions(mNMService);
433
434 // Emulate externally-visible WifiManager effects, causing the
435 // per-interface state machine to start up, and telling us that
436 // tethering mode is to be started.
437 mTethering.interfaceStatusChanged(mTestIfname, true);
438 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
439 mLooper.dispatchAll();
440
441 // Activity caused by test_wlan0 becoming available.
442 verify(mNMService, times(1)).listInterfaces();
443 // We verify get/set called twice here: once for setup and once during
444 // teardown because all events happen over the course of the single
445 // dispatchAll() above.
446 verify(mNMService, times(2)).getInterfaceConfig(mTestIfname);
447 verify(mNMService, times(2))
448 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
449 verify(mNMService, times(1)).tetherInterface(mTestIfname);
450 verify(mWifiManager).updateInterfaceIpState(
451 mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED);
452 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
453 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
454 // This is called, but will throw.
455 verify(mNMService, times(1)).setIpForwardingEnabled(true);
456 // This never gets called because of the exception thrown above.
457 verify(mNMService, times(0)).startTethering(any(String[].class));
458 // When the master state machine transitions to an error state it tells
459 // downstream interfaces, which causes us to tell Wi-Fi about the error
460 // so it can take down AP mode.
461 verify(mNMService, times(1)).untetherInterface(mTestIfname);
462 verify(mWifiManager).updateInterfaceIpState(
463 mTestIfname, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
464
465 verifyNoMoreInteractions(mWifiManager);
466 verifyNoMoreInteractions(mConnectivityManager);
467 verifyNoMoreInteractions(mNMService);
468 }
469
470 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900471 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700472}