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 com.android.server.wifi.WifiController.CMD_AP_STOPPED; 20import static com.android.server.wifi.WifiController.CMD_EMERGENCY_CALL_STATE_CHANGED; 21import static com.android.server.wifi.WifiController.CMD_EMERGENCY_MODE_CHANGED; 22import static com.android.server.wifi.WifiController.CMD_SET_AP; 23import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 24 25import static org.junit.Assert.assertEquals; 26import static org.mockito.Matchers.*; 27import static org.mockito.Mockito.*; 28 29import android.content.ContentResolver; 30import android.content.Context; 31import android.test.suitebuilder.annotation.SmallTest; 32import android.util.Log; 33 34import com.android.internal.util.IState; 35import com.android.internal.util.StateMachine; 36 37import org.junit.After; 38import org.junit.Before; 39import org.junit.Test; 40import org.mockito.InOrder; 41import org.mockito.Mock; 42import org.mockito.MockitoAnnotations; 43 44import java.io.ByteArrayOutputStream; 45import java.io.PrintWriter; 46import java.lang.reflect.Method; 47 48/** 49 * Test WifiController for changes in and out of ECM and SoftAP modes. 50 */ 51@SmallTest 52public class WifiControllerTest { 53 54 private static final String TAG = "WifiControllerTest"; 55 56 private void dumpState() { 57 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 58 PrintWriter writer = new PrintWriter(stream); 59 mWifiController.dump(null, writer, null); 60 writer.flush(); 61 Log.d(TAG, "WifiStateMachine state -" + stream.toString()); 62 } 63 64 private IState getCurrentState() throws Exception { 65 Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); 66 method.setAccessible(true); 67 return (IState) method.invoke(mWifiController); 68 } 69 70 private void initializeSettingsStore() throws Exception { 71 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 72 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 73 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 74 } 75 76 MockLooper mLooper; 77 @Mock Context mContext; 78 @Mock WifiServiceImpl mService; 79 @Mock FrameworkFacade mFacade; 80 @Mock WifiSettingsStore mSettingsStore; 81 @Mock WifiStateMachine mWifiStateMachine; 82 @Mock WifiServiceImpl.LockList mLockList; 83 84 WifiController mWifiController; 85 86 @Before 87 public void setUp() throws Exception { 88 MockitoAnnotations.initMocks(this); 89 90 mLooper = new MockLooper(); 91 92 initializeSettingsStore(); 93 94 when(mContext.getContentResolver()).thenReturn(mock(ContentResolver.class)); 95 96 mWifiController = new WifiController(mContext, mWifiStateMachine, 97 mSettingsStore, mLockList, mLooper.getLooper(), mFacade); 98 99 mWifiController.start(); 100 mLooper.dispatchAll(); 101 } 102 103 @After 104 public void cleanUp() { 105 mLooper.dispatchAll(); 106 } 107 108 @Test 109 public void enableWifi() throws Exception { 110 assertEquals("StaDisabledWithScanState", getCurrentState().getName()); 111 112 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 113 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 114 mLooper.dispatchAll(); 115 assertEquals("DeviceActiveState", getCurrentState().getName()); 116 117 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 118 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 119 mLooper.dispatchAll(); 120 assertEquals("StaDisabledWithScanState", getCurrentState().getName()); 121 122 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 123 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 124 mLooper.dispatchAll(); 125 assertEquals("DeviceActiveState", getCurrentState().getName()); 126 } 127 128 @Test 129 public void testEcmOn() throws Exception { 130 enableWifi(); 131 132 // Test with WifiDisableInECBM turned on: 133 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 134 doTestEcm(true); 135 } 136 137 @Test 138 public void testEcmOff() throws Exception { 139 enableWifi(); 140 141 // Test with WifiDisableInECBM turned off 142 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 143 doTestEcm(false); 144 } 145 146 private void assertInEcm(boolean ecmEnabled) throws Exception { 147 if (ecmEnabled) { 148 assertEquals("EcmState", getCurrentState().getName()); 149 } else { 150 assertEquals("DeviceActiveState", getCurrentState().getName()); 151 } 152 } 153 154 155 private void doTestEcm(boolean ecmEnabled) throws Exception { 156 157 // test ecm changed 158 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 1); 159 mLooper.dispatchAll(); 160 assertInEcm(ecmEnabled); 161 162 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 0); 163 mLooper.dispatchAll(); 164 assertEquals("DeviceActiveState", getCurrentState().getName()); 165 166 // test call state changed 167 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 1); 168 mLooper.dispatchAll(); 169 assertInEcm(ecmEnabled); 170 171 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 0); 172 mLooper.dispatchAll(); 173 assertEquals("DeviceActiveState", getCurrentState().getName()); 174 175 176 // test both changed (variation 1 - the good case) 177 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 1); 178 mLooper.dispatchAll(); 179 assertInEcm(ecmEnabled); 180 181 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 1); 182 mLooper.dispatchAll(); 183 assertInEcm(ecmEnabled); 184 185 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 0); 186 mLooper.dispatchAll(); 187 assertInEcm(ecmEnabled); 188 189 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 0); 190 mLooper.dispatchAll(); 191 assertEquals("DeviceActiveState", getCurrentState().getName()); 192 193 // test both changed (variation 2 - emergency call in ecm) 194 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 1); 195 mLooper.dispatchAll(); 196 assertInEcm(ecmEnabled); 197 198 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 1); 199 mLooper.dispatchAll(); 200 assertInEcm(ecmEnabled); 201 202 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 0); 203 mLooper.dispatchAll(); 204 assertInEcm(ecmEnabled); 205 206 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 0); 207 mLooper.dispatchAll(); 208 assertEquals("DeviceActiveState", getCurrentState().getName()); 209 210 // test both changed (variation 3 - not so good order of events) 211 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 1); 212 mLooper.dispatchAll(); 213 assertInEcm(ecmEnabled); 214 215 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 1); 216 mLooper.dispatchAll(); 217 assertInEcm(ecmEnabled); 218 219 mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, 0); 220 mLooper.dispatchAll(); 221 assertInEcm(ecmEnabled); 222 223 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 0); 224 mLooper.dispatchAll(); 225 assertEquals("DeviceActiveState", getCurrentState().getName()); 226 227 // test that Wifi toggle doesn't exit Ecm 228 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 1); 229 mLooper.dispatchAll(); 230 assertInEcm(ecmEnabled); 231 232 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 233 mWifiController.sendMessage(CMD_WIFI_TOGGLED); 234 mLooper.dispatchAll(); 235 assertInEcm(ecmEnabled); 236 237 mWifiController.sendMessage(CMD_EMERGENCY_CALL_STATE_CHANGED, 0); 238 mLooper.dispatchAll(); 239 assertEquals("DeviceActiveState", getCurrentState().getName()); 240 } 241 242 /** 243 * When AP mode is enabled and wifi was previously in AP mode, we should return to 244 * DeviceActiveState after the AP is disabled. 245 * Enter DeviceActiveState, activate AP mode, disable AP mode. 246 * <p> 247 * Expected: AP should successfully start and exit, then return to DeviceActiveState. 248 */ 249 @Test 250 public void testReturnToDeviceActiveStateAfterAPModeShutdown() throws Exception { 251 enableWifi(); 252 assertEquals("DeviceActiveState", getCurrentState().getName()); 253 254 mWifiController.obtainMessage(CMD_SET_AP, 1, 0).sendToTarget(); 255 mLooper.dispatchAll(); 256 assertEquals("ApEnabledState", getCurrentState().getName()); 257 258 when(mSettingsStore.getWifiSavedState()).thenReturn(1); 259 mWifiController.obtainMessage(CMD_AP_STOPPED).sendToTarget(); 260 mLooper.dispatchAll(); 261 262 InOrder inOrder = inOrder(mWifiStateMachine); 263 inOrder.verify(mWifiStateMachine).setSupplicantRunning(true); 264 inOrder.verify(mWifiStateMachine).setOperationalMode(WifiStateMachine.CONNECT_MODE); 265 inOrder.verify(mWifiStateMachine).setDriverStart(true); 266 assertEquals("DeviceActiveState", getCurrentState().getName()); 267 } 268} 269