blob: f9a30e9380237ad9c5f69f43c4277e227458ace4 [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;
Erik Klinef3a08b42017-06-07 16:33:19 +090045import android.content.pm.ApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070046import android.content.res.Resources;
Erik Klineea9cc482017-03-10 19:35:34 +090047import android.hardware.usb.UsbManager;
48import android.net.ConnectivityManager;
49import android.net.ConnectivityManager.NetworkCallback;
Christopher Wiley497c1472016-10-11 13:26:03 -070050import android.net.INetworkPolicyManager;
51import android.net.INetworkStatsService;
Erik Klineea9cc482017-03-10 19:35:34 +090052import android.net.InterfaceConfiguration;
53import android.net.NetworkRequest;
Erik Klinef4b6e342017-04-25 19:19:59 +090054import android.net.util.SharedLog;
Erik Klineea9cc482017-03-10 19:35:34 +090055import android.net.wifi.WifiConfiguration;
56import android.net.wifi.WifiManager;
57import android.os.Handler;
Christopher Wiley497c1472016-10-11 13:26:03 -070058import android.os.INetworkManagementService;
59import android.os.PersistableBundle;
Erik Kline1fdc2e22017-05-08 17:56:35 +090060import android.os.RemoteException;
Christopher Wiley497c1472016-10-11 13:26:03 -070061import android.os.test.TestLooper;
Erik Klineea9cc482017-03-10 19:35:34 +090062import android.os.UserHandle;
Erik Kline92c4db02017-05-31 10:21:32 +090063import android.provider.Settings;
Christopher Wiley497c1472016-10-11 13:26:03 -070064import android.support.test.filters.SmallTest;
65import android.support.test.runner.AndroidJUnit4;
66import android.telephony.CarrierConfigManager;
Erik Kline92c4db02017-05-31 10:21:32 +090067import android.test.mock.MockContentResolver;
Christopher Wiley497c1472016-10-11 13:26:03 -070068
Erik Klineea9cc482017-03-10 19:35:34 +090069import com.android.internal.util.test.BroadcastInterceptingContext;
Erik Kline92c4db02017-05-31 10:21:32 +090070import com.android.internal.util.test.FakeSettingsProvider;
Erik Kline5a7c8a02017-04-30 19:36:15 +090071import com.android.server.connectivity.tethering.OffloadHardwareInterface;
72import com.android.server.connectivity.tethering.TetheringDependencies;
Erik Klineea9cc482017-03-10 19:35:34 +090073
Erik Kline8351faa2017-04-17 16:47:23 +090074import org.junit.After;
Christopher Wiley497c1472016-10-11 13:26:03 -070075import org.junit.Before;
76import org.junit.Test;
77import org.junit.runner.RunWith;
78import org.mockito.Mock;
79import org.mockito.MockitoAnnotations;
80
Erik Kline8351faa2017-04-17 16:47:23 +090081import java.util.ArrayList;
82import java.util.Vector;
83
Christopher Wiley497c1472016-10-11 13:26:03 -070084@RunWith(AndroidJUnit4.class)
85@SmallTest
86public class TetheringTest {
87 private static final String[] PROVISIONING_APP_NAME = {"some", "app"};
88
Erik Klinef3a08b42017-06-07 16:33:19 +090089 @Mock private ApplicationInfo mApplicationInfo;
Christopher Wiley497c1472016-10-11 13:26:03 -070090 @Mock private Context mContext;
Erik Klineea9cc482017-03-10 19:35:34 +090091 @Mock private ConnectivityManager mConnectivityManager;
Christopher Wiley497c1472016-10-11 13:26:03 -070092 @Mock private INetworkManagementService mNMService;
93 @Mock private INetworkStatsService mStatsService;
94 @Mock private INetworkPolicyManager mPolicyManager;
95 @Mock private MockableSystemProperties mSystemProperties;
Erik Kline5a7c8a02017-04-30 19:36:15 +090096 @Mock private OffloadHardwareInterface mOffloadHardwareInterface;
Christopher Wiley497c1472016-10-11 13:26:03 -070097 @Mock private Resources mResources;
Erik Kline5a7c8a02017-04-30 19:36:15 +090098 @Mock private TetheringDependencies mTetheringDependencies;
Erik Klineea9cc482017-03-10 19:35:34 +090099 @Mock private UsbManager mUsbManager;
100 @Mock private WifiManager mWifiManager;
Christopher Wiley497c1472016-10-11 13:26:03 -0700101 @Mock private CarrierConfigManager mCarrierConfigManager;
102
103 // Like so many Android system APIs, these cannot be mocked because it is marked final.
104 // We have to use the real versions.
105 private final PersistableBundle mCarrierConfig = new PersistableBundle();
106 private final TestLooper mLooper = new TestLooper();
Erik Klineea9cc482017-03-10 19:35:34 +0900107 private final String mTestIfname = "test_wlan0";
Christopher Wiley497c1472016-10-11 13:26:03 -0700108
Erik Kline8351faa2017-04-17 16:47:23 +0900109 private Vector<Intent> mIntents;
Erik Klineea9cc482017-03-10 19:35:34 +0900110 private BroadcastInterceptingContext mServiceContext;
Erik Kline92c4db02017-05-31 10:21:32 +0900111 private MockContentResolver mContentResolver;
Erik Kline8351faa2017-04-17 16:47:23 +0900112 private BroadcastReceiver mBroadcastReceiver;
Christopher Wiley497c1472016-10-11 13:26:03 -0700113 private Tethering mTethering;
114
Erik Klineea9cc482017-03-10 19:35:34 +0900115 private class MockContext extends BroadcastInterceptingContext {
116 MockContext(Context base) {
117 super(base);
118 }
119
120 @Override
Erik Klinef3a08b42017-06-07 16:33:19 +0900121 public ApplicationInfo getApplicationInfo() { return mApplicationInfo; }
122
123 @Override
Erik Kline92c4db02017-05-31 10:21:32 +0900124 public ContentResolver getContentResolver() { return mContentResolver; }
125
126 @Override
127 public String getPackageName() { return "TetheringTest"; }
128
129 @Override
Erik Klineea9cc482017-03-10 19:35:34 +0900130 public Resources getResources() { return mResources; }
131
132 @Override
133 public Object getSystemService(String name) {
134 if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
135 if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
136 return super.getSystemService(name);
137 }
138 }
139
Erik Kline8351faa2017-04-17 16:47:23 +0900140 @Before
141 public void setUp() throws Exception {
Christopher Wiley497c1472016-10-11 13:26:03 -0700142 MockitoAnnotations.initMocks(this);
Christopher Wiley497c1472016-10-11 13:26:03 -0700143 when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
144 .thenReturn(new String[0]);
145 when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
146 .thenReturn(new String[0]);
147 when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
Erik Klineea9cc482017-03-10 19:35:34 +0900148 .thenReturn(new String[]{ "test_wlan\\d" });
Christopher Wiley497c1472016-10-11 13:26:03 -0700149 when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
150 .thenReturn(new String[0]);
151 when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
152 .thenReturn(new int[0]);
Erik Klineea9cc482017-03-10 19:35:34 +0900153 when(mNMService.listInterfaces())
154 .thenReturn(new String[]{ "test_rmnet_data0", mTestIfname });
155 when(mNMService.getInterfaceConfig(anyString()))
156 .thenReturn(new InterfaceConfiguration());
157
158 mServiceContext = new MockContext(mContext);
Erik Kline92c4db02017-05-31 10:21:32 +0900159 mContentResolver = new MockContentResolver(mServiceContext);
160 mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
Erik Kline8351faa2017-04-17 16:47:23 +0900161 mIntents = new Vector<>();
162 mBroadcastReceiver = new BroadcastReceiver() {
163 @Override
164 public void onReceive(Context context, Intent intent) {
165 mIntents.addElement(intent);
166 }
167 };
168 mServiceContext.registerReceiver(mBroadcastReceiver,
169 new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
Erik Klinef4b6e342017-04-25 19:19:59 +0900170 when(mTetheringDependencies.getOffloadHardwareInterface(
171 any(Handler.class), any(SharedLog.class))).thenReturn(mOffloadHardwareInterface);
Erik Klineea9cc482017-03-10 19:35:34 +0900172 mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
Erik Kline5a7c8a02017-04-30 19:36:15 +0900173 mLooper.getLooper(), mSystemProperties,
174 mTetheringDependencies);
Christopher Wiley497c1472016-10-11 13:26:03 -0700175 }
176
Erik Kline8351faa2017-04-17 16:47:23 +0900177 @After
178 public void tearDown() {
179 mServiceContext.unregisterReceiver(mBroadcastReceiver);
180 }
181
Christopher Wiley497c1472016-10-11 13:26:03 -0700182 private void setupForRequiredProvisioning() {
183 // Produce some acceptable looking provision app setting if requested.
184 when(mResources.getStringArray(
185 com.android.internal.R.array.config_mobile_hotspot_provision_app))
186 .thenReturn(PROVISIONING_APP_NAME);
187 // Don't disable tethering provisioning unless requested.
188 when(mSystemProperties.getBoolean(eq(Tethering.DISABLE_PROVISIONING_SYSPROP_KEY),
189 anyBoolean())).thenReturn(false);
190 // Act like the CarrierConfigManager is present and ready unless told otherwise.
191 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
192 .thenReturn(mCarrierConfigManager);
193 when(mCarrierConfigManager.getConfig()).thenReturn(mCarrierConfig);
194 mCarrierConfig.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
195 }
196
197 @Test
198 public void canRequireProvisioning() {
199 setupForRequiredProvisioning();
200 assertTrue(mTethering.isTetherProvisioningRequired());
201 }
202
203 @Test
204 public void toleratesCarrierConfigManagerMissing() {
205 setupForRequiredProvisioning();
206 when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
207 .thenReturn(null);
208 // Couldn't get the CarrierConfigManager, but still had a declared provisioning app.
209 // We therefore still require provisioning.
210 assertTrue(mTethering.isTetherProvisioningRequired());
211 }
212
213 @Test
214 public void toleratesCarrierConfigMissing() {
215 setupForRequiredProvisioning();
216 when(mCarrierConfigManager.getConfig()).thenReturn(null);
217 // We still have a provisioning app configured, so still require provisioning.
218 assertTrue(mTethering.isTetherProvisioningRequired());
219 }
220
221 @Test
222 public void provisioningNotRequiredWhenAppNotFound() {
223 setupForRequiredProvisioning();
224 when(mResources.getStringArray(
225 com.android.internal.R.array.config_mobile_hotspot_provision_app))
226 .thenReturn(null);
227 assertTrue(!mTethering.isTetherProvisioningRequired());
228 when(mResources.getStringArray(
229 com.android.internal.R.array.config_mobile_hotspot_provision_app))
230 .thenReturn(new String[] {"malformedApp"});
231 assertTrue(!mTethering.isTetherProvisioningRequired());
232 }
Erik Klineea9cc482017-03-10 19:35:34 +0900233
234 private void sendWifiApStateChanged(int state) {
235 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
Erik Kline2efb8272017-05-31 15:53:53 +0900236 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
Erik Klineea9cc482017-03-10 19:35:34 +0900237 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
238 }
239
Erik Kline2efb8272017-05-31 15:53:53 +0900240 private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
241 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
242 intent.putExtra(EXTRA_WIFI_AP_STATE, state);
243 intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
244 intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
245 mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
246 }
247
Erik Kline9e225542017-06-08 17:48:48 +0900248 private void verifyInterfaceServingModeStarted() throws Exception {
Erik Kline8351faa2017-04-17 16:47:23 +0900249 verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
250 verify(mNMService, times(1))
251 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
252 verify(mNMService, times(1)).tetherInterface(mTestIfname);
253 }
254
255 private void verifyTetheringBroadcast(String ifname, String whichExtra) {
256 // Verify that ifname is in the whichExtra array of the tether state changed broadcast.
257 final Intent bcast = mIntents.get(0);
258 assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
259 final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
260 assertTrue(ifnames.contains(ifname));
261 mIntents.remove(bcast);
262 }
263
Erik Kline9e225542017-06-08 17:48:48 +0900264 @Test
265 public void failingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900266 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900267
268 // Emulate externally-visible WifiManager effects, causing the
269 // per-interface state machine to start up, and telling us that
270 // hotspot mode is to be started.
271 mTethering.interfaceStatusChanged(mTestIfname, true);
Erik Kline9e225542017-06-08 17:48:48 +0900272 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900273 mLooper.dispatchAll();
274
Erik Kline9e225542017-06-08 17:48:48 +0900275 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
276 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
277 verifyNoMoreInteractions(mConnectivityManager);
278 verifyNoMoreInteractions(mNMService);
279 verifyNoMoreInteractions(mWifiManager);
280 }
281
282 @Test
283 public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
284 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
285
286 // Emulate externally-visible WifiManager effects, causing the
287 // per-interface state machine to start up, and telling us that
288 // hotspot mode is to be started.
289 mTethering.interfaceStatusChanged(mTestIfname, true);
290 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
291 mLooper.dispatchAll();
292
293 verifyInterfaceServingModeStarted();
Erik Kline8351faa2017-04-17 16:47:23 +0900294 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900295 verify(mNMService, times(1)).setIpForwardingEnabled(true);
296 verify(mNMService, times(1)).startTethering(any(String[].class));
297 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900298 verify(mWifiManager).updateInterfaceIpState(
299 mTestIfname, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
300 verifyNoMoreInteractions(mWifiManager);
Erik Kline8351faa2017-04-17 16:47:23 +0900301 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
Erik Klineea9cc482017-03-10 19:35:34 +0900302 // UpstreamNetworkMonitor will be started, and will register two callbacks:
303 // a "listen all" and a "track default".
304 verify(mConnectivityManager, times(1)).registerNetworkCallback(
305 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
306 verify(mConnectivityManager, times(1)).registerDefaultNetworkCallback(
307 any(NetworkCallback.class), any(Handler.class));
308 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
309 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
310 verifyNoMoreInteractions(mConnectivityManager);
311
312 // Emulate externally-visible WifiManager effects, when hotspot mode
313 // is being torn down.
314 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
315 mTethering.interfaceRemoved(mTestIfname);
316 mLooper.dispatchAll();
317
318 verify(mNMService, times(1)).untetherInterface(mTestIfname);
319 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
320 verify(mNMService, atLeastOnce()).getInterfaceConfig(mTestIfname);
321 verify(mNMService, atLeastOnce())
322 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
323 verify(mNMService, times(1)).stopTethering();
324 verify(mNMService, times(1)).setIpForwardingEnabled(false);
325 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900326 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900327 // Asking for the last error after the per-interface state machine
328 // has been reaped yields an unknown interface error.
329 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
330 mTethering.getLastTetherError(mTestIfname));
331 }
332
333 @Test
Erik Kline9e225542017-06-08 17:48:48 +0900334 public void failingWifiTetheringLegacyApBroadcast() throws Exception {
Erik Klineea9cc482017-03-10 19:35:34 +0900335 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
Erik Klineceb54c62017-04-18 14:22:25 +0900336 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
Erik Klineea9cc482017-03-10 19:35:34 +0900337
338 // Emulate pressing the WiFi tethering button.
339 mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
340 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900341 verify(mWifiManager, times(1)).startSoftAp(null);
Erik Klineea9cc482017-03-10 19:35:34 +0900342 verifyNoMoreInteractions(mWifiManager);
343 verifyNoMoreInteractions(mConnectivityManager);
344 verifyNoMoreInteractions(mNMService);
345
346 // Emulate externally-visible WifiManager effects, causing the
347 // per-interface state machine to start up, and telling us that
348 // tethering mode is to be started.
349 mTethering.interfaceStatusChanged(mTestIfname, true);
Erik Kline9e225542017-06-08 17:48:48 +0900350 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
Erik Klineea9cc482017-03-10 19:35:34 +0900351 mLooper.dispatchAll();
352
Erik Kline9e225542017-06-08 17:48:48 +0900353 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
354 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
355 verifyNoMoreInteractions(mConnectivityManager);
356 verifyNoMoreInteractions(mNMService);
357 verifyNoMoreInteractions(mWifiManager);
358 }
359
360 @Test
361 public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
362 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
363 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
364
365 // Emulate pressing the WiFi tethering button.
366 mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
367 mLooper.dispatchAll();
368 verify(mWifiManager, times(1)).startSoftAp(null);
369 verifyNoMoreInteractions(mWifiManager);
370 verifyNoMoreInteractions(mConnectivityManager);
371 verifyNoMoreInteractions(mNMService);
372
373 // Emulate externally-visible WifiManager effects, causing the
374 // per-interface state machine to start up, and telling us that
375 // tethering mode is to be started.
376 mTethering.interfaceStatusChanged(mTestIfname, true);
377 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
378 mLooper.dispatchAll();
379
380 verifyInterfaceServingModeStarted();
Erik Kline8351faa2017-04-17 16:47:23 +0900381 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900382 verify(mNMService, times(1)).setIpForwardingEnabled(true);
383 verify(mNMService, times(1)).startTethering(any(String[].class));
384 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900385 verify(mWifiManager).updateInterfaceIpState(
386 mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED);
387 verifyNoMoreInteractions(mWifiManager);
Erik Kline8351faa2017-04-17 16:47:23 +0900388 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER);
Erik Klineea9cc482017-03-10 19:35:34 +0900389 // UpstreamNetworkMonitor will be started, and will register two callbacks:
390 // a "listen all" and a "track default".
391 verify(mConnectivityManager, times(1)).registerNetworkCallback(
392 any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
393 verify(mConnectivityManager, times(1)).registerDefaultNetworkCallback(
394 any(NetworkCallback.class), any(Handler.class));
395 // In tethering mode, in the default configuration, an explicit request
396 // for a mobile network is also made.
397 verify(mConnectivityManager, atLeastOnce()).getNetworkInfo(anyInt());
398 verify(mConnectivityManager, times(1)).requestNetwork(
399 any(NetworkRequest.class), any(NetworkCallback.class), eq(0), anyInt(),
400 any(Handler.class));
401 // TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
402 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
403 verifyNoMoreInteractions(mConnectivityManager);
404
405 /////
406 // We do not currently emulate any upstream being found.
407 //
408 // This is why there are no calls to verify mNMService.enableNat() or
409 // mNMService.startInterfaceForwarding().
410 /////
411
412 // Emulate pressing the WiFi tethering button.
413 mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI);
414 mLooper.dispatchAll();
Erik Klineceb54c62017-04-18 14:22:25 +0900415 verify(mWifiManager, times(1)).stopSoftAp();
Erik Klineea9cc482017-03-10 19:35:34 +0900416 verifyNoMoreInteractions(mWifiManager);
417 verifyNoMoreInteractions(mConnectivityManager);
418 verifyNoMoreInteractions(mNMService);
419
420 // Emulate externally-visible WifiManager effects, when tethering mode
421 // is being torn down.
422 sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
423 mTethering.interfaceRemoved(mTestIfname);
424 mLooper.dispatchAll();
425
426 verify(mNMService, times(1)).untetherInterface(mTestIfname);
427 // TODO: Why is {g,s}etInterfaceConfig() called more than once?
428 verify(mNMService, atLeastOnce()).getInterfaceConfig(mTestIfname);
429 verify(mNMService, atLeastOnce())
430 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
431 verify(mNMService, times(1)).stopTethering();
432 verify(mNMService, times(1)).setIpForwardingEnabled(false);
433 verifyNoMoreInteractions(mNMService);
Erik Kline216af6d2017-04-27 20:57:23 +0900434 verifyNoMoreInteractions(mWifiManager);
Erik Klineea9cc482017-03-10 19:35:34 +0900435 // Asking for the last error after the per-interface state machine
436 // has been reaped yields an unknown interface error.
437 assertEquals(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE,
438 mTethering.getLastTetherError(mTestIfname));
439 }
440
Erik Kline1fdc2e22017-05-08 17:56:35 +0900441 @Test
442 public void failureEnablingIpForwarding() throws Exception {
443 when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
444 when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
445 doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
446
447 // Emulate pressing the WiFi tethering button.
448 mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
449 mLooper.dispatchAll();
450 verify(mWifiManager, times(1)).startSoftAp(null);
451 verifyNoMoreInteractions(mWifiManager);
452 verifyNoMoreInteractions(mConnectivityManager);
453 verifyNoMoreInteractions(mNMService);
454
455 // Emulate externally-visible WifiManager effects, causing the
456 // per-interface state machine to start up, and telling us that
457 // tethering mode is to be started.
458 mTethering.interfaceStatusChanged(mTestIfname, true);
Erik Kline9e225542017-06-08 17:48:48 +0900459 sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
Erik Kline1fdc2e22017-05-08 17:56:35 +0900460 mLooper.dispatchAll();
461
Erik Kline1fdc2e22017-05-08 17:56:35 +0900462 // We verify get/set called twice here: once for setup and once during
463 // teardown because all events happen over the course of the single
464 // dispatchAll() above.
465 verify(mNMService, times(2)).getInterfaceConfig(mTestIfname);
466 verify(mNMService, times(2))
467 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
468 verify(mNMService, times(1)).tetherInterface(mTestIfname);
469 verify(mWifiManager).updateInterfaceIpState(
470 mTestIfname, WifiManager.IFACE_IP_MODE_TETHERED);
471 verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
472 verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
473 // This is called, but will throw.
474 verify(mNMService, times(1)).setIpForwardingEnabled(true);
475 // This never gets called because of the exception thrown above.
476 verify(mNMService, times(0)).startTethering(any(String[].class));
477 // When the master state machine transitions to an error state it tells
478 // downstream interfaces, which causes us to tell Wi-Fi about the error
479 // so it can take down AP mode.
480 verify(mNMService, times(1)).untetherInterface(mTestIfname);
481 verify(mWifiManager).updateInterfaceIpState(
482 mTestIfname, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
483
484 verifyNoMoreInteractions(mWifiManager);
485 verifyNoMoreInteractions(mConnectivityManager);
486 verifyNoMoreInteractions(mNMService);
487 }
488
489 // TODO: Test that a request for hotspot mode doesn't interfere with an
Erik Klineea9cc482017-03-10 19:35:34 +0900490 // already operating tethering mode interface.
Christopher Wiley497c1472016-10-11 13:26:03 -0700491}