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