SoftApManagerTest.java revision f4267b6840dbc7f430638c35c5448187b6e83846
1/* 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.wifi; 18 19import static org.mockito.Mockito.any; 20import static org.mockito.Mockito.anyInt; 21import static org.mockito.Mockito.eq; 22import static org.mockito.Mockito.inOrder; 23import static org.mockito.Mockito.mock; 24import static org.mockito.Mockito.never; 25import static org.mockito.Mockito.verify; 26import static org.mockito.Mockito.when; 27 28import android.content.BroadcastReceiver; 29import android.content.Context; 30import android.content.IntentFilter; 31import android.net.ConnectivityManager; 32import android.net.InterfaceConfiguration; 33import android.net.LinkAddress; 34import android.net.wifi.WifiConfiguration; 35import android.net.wifi.WifiManager; 36import android.os.INetworkManagementService; 37import android.os.test.TestLooper; 38import android.test.suitebuilder.annotation.SmallTest; 39 40import org.junit.Before; 41import org.junit.Test; 42import org.mockito.ArgumentCaptor; 43import org.mockito.InOrder; 44import org.mockito.Mock; 45import org.mockito.MockitoAnnotations; 46 47import java.util.ArrayList; 48import java.util.Arrays; 49import java.util.Locale; 50 51/** Unit tests for {@link SoftApManager}. */ 52@SmallTest 53public class SoftApManagerTest { 54 55 private static final String TAG = "SoftApManagerTest"; 56 57 private static final String TEST_INTERFACE_NAME = "TestInterface"; 58 private static final String TEST_COUNTRY_CODE = "TestCountry"; 59 private static final Integer[] ALLOWED_2G_CHANNELS = {1, 2, 3, 4}; 60 private static final String[] AVAILABLE_DEVICES = { TEST_INTERFACE_NAME }; 61 62 private final ArrayList<Integer> mAllowed2GChannels = 63 new ArrayList<Integer>(Arrays.asList(ALLOWED_2G_CHANNELS)); 64 65 TestLooper mLooper; 66 @Mock Context mContext; 67 @Mock WifiNative mWifiNative; 68 @Mock INetworkManagementService mNmService; 69 @Mock ConnectivityManager mConnectivityManager; 70 @Mock SoftApManager.Listener mListener; 71 @Mock InterfaceConfiguration mInterfaceConfiguration; 72 73 /** 74 * Internal BroadcastReceiver that SoftApManager uses to listen for tethering 75 * events from ConnectivityManager. 76 */ 77 BroadcastReceiver mBroadcastReceiver; 78 79 SoftApManager mSoftApManager; 80 81 /** Sets up test. */ 82 @Before 83 public void setUp() throws Exception { 84 MockitoAnnotations.initMocks(this); 85 mLooper = new TestLooper(); 86 87 when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME); 88 when(mNmService.getInterfaceConfig(TEST_INTERFACE_NAME)) 89 .thenReturn(mInterfaceConfiguration); 90 when(mConnectivityManager.getTetherableWifiRegexs()) 91 .thenReturn(AVAILABLE_DEVICES); 92 93 mSoftApManager = new SoftApManager(mContext, 94 mLooper.getLooper(), 95 mWifiNative, 96 mNmService, 97 mConnectivityManager, 98 TEST_COUNTRY_CODE, 99 mAllowed2GChannels, 100 mListener); 101 ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = 102 ArgumentCaptor.forClass(BroadcastReceiver.class); 103 verify(mContext).registerReceiver( 104 broadcastReceiverCaptor.capture(), any(IntentFilter.class)); 105 mBroadcastReceiver = broadcastReceiverCaptor.getValue(); 106 107 mLooper.dispatchAll(); 108 } 109 110 /** Verifies startSoftAp will fail if AP configuration is not provided. */ 111 @Test 112 public void startSoftApWithoutConfig() throws Exception { 113 InOrder order = inOrder(mListener); 114 115 mSoftApManager.start(null); 116 mLooper.dispatchAll(); 117 118 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); 119 order.verify(mListener).onStateChanged( 120 WifiManager.WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 121 } 122 123 /** Tests the handling of timeout after tethering is started. */ 124 @Test 125 public void tetheringTimedOut() throws Exception { 126 startSoftApAndVerifyEnabled(); 127 announceAvailableForTethering(); 128 verifyTetheringRequested(); 129 130 InOrder order = inOrder(mListener); 131 132 /* Move the time forward to simulate notification timeout. */ 133 mLooper.moveTimeForward(5000); 134 mLooper.dispatchAll(); 135 136 /* Verify soft ap is disabled. */ 137 verify(mNmService).stopAccessPoint(eq(TEST_INTERFACE_NAME)); 138 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); 139 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 140 } 141 142 /** Tests the handling of tethered notification after tethering is started. */ 143 @Test 144 public void tetherCompleted() throws Exception { 145 startSoftApAndVerifyEnabled(); 146 announceAvailableForTethering(); 147 verifyTetheringRequested(); 148 announceTethered(); 149 verifySoftApNotDisabled(); 150 } 151 152 /** Tests the handling of stop command when soft AP is not started. */ 153 @Test 154 public void stopWhenNotStarted() throws Exception { 155 mSoftApManager.stop(); 156 mLooper.dispatchAll(); 157 /* Verify no state changes. */ 158 verify(mListener, never()).onStateChanged(anyInt(), anyInt()); 159 } 160 161 /** Tests the handling of stop command when soft AP is started. */ 162 @Test 163 public void stopWhenStarted() throws Exception { 164 startSoftApAndVerifyEnabled(); 165 166 InOrder order = inOrder(mListener); 167 168 mSoftApManager.stop(); 169 mLooper.dispatchAll(); 170 171 verify(mNmService).stopAccessPoint(TEST_INTERFACE_NAME); 172 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); 173 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 174 } 175 176 /** Starts soft AP and verifies that it is enabled successfully. */ 177 protected void startSoftApAndVerifyEnabled() throws Exception { 178 InOrder order = inOrder(mListener); 179 180 /** 181 * Only test the default configuration. Testing for different configurations 182 * are taken care of by ApConfigUtilTest. 183 */ 184 WifiConfiguration config = new WifiConfiguration(); 185 config.apBand = WifiConfiguration.AP_BAND_2GHZ; 186 when(mWifiNative.isHalStarted()).thenReturn(false); 187 when(mWifiNative.setCountryCodeHal(TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT))) 188 .thenReturn(true); 189 mSoftApManager.start(config); 190 mLooper.dispatchAll(); 191 verify(mNmService).startAccessPoint( 192 any(WifiConfiguration.class), eq(TEST_INTERFACE_NAME)); 193 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0); 194 order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); 195 } 196 197 /** Verifies that soft AP was not disabled. */ 198 protected void verifySoftApNotDisabled() throws Exception { 199 verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0); 200 verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 201 } 202 203 /** Sends a broadcast intent indicating that the interface is available for tethering. */ 204 protected void announceAvailableForTethering() throws Exception { 205 when(mConnectivityManager.tether(TEST_INTERFACE_NAME)) 206 .thenReturn(ConnectivityManager.TETHER_ERROR_NO_ERROR); 207 ArrayList<String> availableList = 208 new ArrayList<String>(Arrays.asList(AVAILABLE_DEVICES)); 209 TestUtil.sendTetherStateChanged( 210 mBroadcastReceiver, mContext, availableList, new ArrayList<String>()); 211 mLooper.dispatchAll(); 212 } 213 214 /** Verifies that tethering was requested. */ 215 protected void verifyTetheringRequested() throws Exception { 216 verify(mInterfaceConfiguration).setLinkAddress(any(LinkAddress.class)); 217 verify(mInterfaceConfiguration).setInterfaceUp(); 218 verify(mNmService).setInterfaceConfig(eq(TEST_INTERFACE_NAME), eq(mInterfaceConfiguration)); 219 } 220 221 /** Sends a broadcast intent indicating that the interface is tethered. */ 222 protected void announceTethered() throws Exception { 223 ArrayList<String> deviceList = 224 new ArrayList<String>(Arrays.asList(AVAILABLE_DEVICES)); 225 TestUtil.sendTetherStateChanged( 226 mBroadcastReceiver, mContext, deviceList, deviceList); 227 mLooper.dispatchAll(); 228 } 229} 230