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