Home | History | Annotate | Download | only in wifi
      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 
     17 package com.android.server.wifi;
     18 
     19 import static org.mockito.Mockito.any;
     20 import static org.mockito.Mockito.anyBoolean;
     21 import static org.mockito.Mockito.anyInt;
     22 import static org.mockito.Mockito.eq;
     23 import static org.mockito.Mockito.inOrder;
     24 import static org.mockito.Mockito.never;
     25 import static org.mockito.Mockito.verify;
     26 import static org.mockito.Mockito.when;
     27 
     28 import android.net.InterfaceConfiguration;
     29 import android.net.wifi.IApInterface;
     30 import android.net.wifi.WifiConfiguration;
     31 import android.net.wifi.WifiManager;
     32 import android.os.IBinder;
     33 import android.os.IBinder.DeathRecipient;
     34 import android.os.INetworkManagementService;
     35 import android.os.test.TestLooper;
     36 import android.test.suitebuilder.annotation.SmallTest;
     37 
     38 import com.android.server.net.BaseNetworkObserver;
     39 
     40 import org.junit.Before;
     41 import org.junit.Test;
     42 import org.mockito.ArgumentCaptor;
     43 import org.mockito.InOrder;
     44 import org.mockito.Mock;
     45 import org.mockito.MockitoAnnotations;
     46 
     47 import java.nio.charset.StandardCharsets;
     48 import java.util.ArrayList;
     49 import java.util.Arrays;
     50 import java.util.Locale;
     51 
     52 /** Unit tests for {@link SoftApManager}. */
     53 @SmallTest
     54 public class SoftApManagerTest {
     55 
     56     private static final String TAG = "SoftApManagerTest";
     57 
     58     private static final String DEFAULT_SSID = "DefaultTestSSID";
     59     private static final String TEST_SSID = "TestSSID";
     60     private static final String TEST_COUNTRY_CODE = "TestCountry";
     61     private static final Integer[] ALLOWED_2G_CHANNELS = {1, 2, 3, 4};
     62     private static final String TEST_INTERFACE_NAME = "testif0";
     63 
     64     private final ArrayList<Integer> mAllowed2GChannels =
     65             new ArrayList<>(Arrays.asList(ALLOWED_2G_CHANNELS));
     66 
     67     private final WifiConfiguration mDefaultApConfig = createDefaultApConfig();
     68 
     69     TestLooper mLooper;
     70     @Mock WifiNative mWifiNative;
     71     @Mock SoftApManager.Listener mListener;
     72     @Mock InterfaceConfiguration mInterfaceConfiguration;
     73     @Mock IBinder mApInterfaceBinder;
     74     @Mock IApInterface mApInterface;
     75     @Mock INetworkManagementService mNmService;
     76     @Mock WifiApConfigStore mWifiApConfigStore;
     77     @Mock WifiMetrics mWifiMetrics;
     78     final ArgumentCaptor<DeathRecipient> mDeathListenerCaptor =
     79             ArgumentCaptor.forClass(DeathRecipient.class);
     80     final ArgumentCaptor<BaseNetworkObserver> mNetworkObserverCaptor =
     81             ArgumentCaptor.forClass(BaseNetworkObserver.class);
     82 
     83     SoftApManager mSoftApManager;
     84 
     85     /** Sets up test. */
     86     @Before
     87     public void setUp() throws Exception {
     88         MockitoAnnotations.initMocks(this);
     89         mLooper = new TestLooper();
     90 
     91         when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
     92         when(mApInterface.startHostapd()).thenReturn(true);
     93         when(mApInterface.stopHostapd()).thenReturn(true);
     94         when(mApInterface.writeHostapdConfig(
     95                 any(), anyBoolean(), anyInt(), anyInt(), any())).thenReturn(true);
     96         when(mApInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
     97     }
     98 
     99     private WifiConfiguration createDefaultApConfig() {
    100         WifiConfiguration defaultConfig = new WifiConfiguration();
    101         defaultConfig.SSID = DEFAULT_SSID;
    102         return defaultConfig;
    103     }
    104 
    105     private SoftApManager createSoftApManager(WifiConfiguration config) throws Exception {
    106         when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
    107         when(mApInterface.startHostapd()).thenReturn(true);
    108         when(mApInterface.stopHostapd()).thenReturn(true);
    109         if (config == null) {
    110             when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig);
    111         }
    112         SoftApManager newSoftApManager = new SoftApManager(mLooper.getLooper(),
    113                                                            mWifiNative,
    114                                                            TEST_COUNTRY_CODE,
    115                                                            mListener,
    116                                                            mApInterface,
    117                                                            mNmService,
    118                                                            mWifiApConfigStore,
    119                                                            config,
    120                                                            mWifiMetrics);
    121         mLooper.dispatchAll();
    122         return newSoftApManager;
    123     }
    124 
    125     /** Verifies startSoftAp will use default config if AP configuration is not provided. */
    126     @Test
    127     public void startSoftApWithoutConfig() throws Exception {
    128         startSoftApAndVerifyEnabled(null);
    129     }
    130 
    131     /** Verifies startSoftAp will use provided config and start AP. */
    132     @Test
    133     public void startSoftApWithConfig() throws Exception {
    134         WifiConfiguration config = new WifiConfiguration();
    135         config.apBand = WifiConfiguration.AP_BAND_2GHZ;
    136         config.SSID = TEST_SSID;
    137         startSoftApAndVerifyEnabled(config);
    138     }
    139 
    140     /** Tests softap startup if default config fails to load. **/
    141     @Test
    142     public void startSoftApDefaultConfigFailedToLoad() throws Exception {
    143         when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
    144         when(mApInterface.startHostapd()).thenReturn(true);
    145         when(mApInterface.stopHostapd()).thenReturn(true);
    146         when(mWifiApConfigStore.getApConfiguration()).thenReturn(null);
    147         SoftApManager newSoftApManager = new SoftApManager(mLooper.getLooper(),
    148                                                            mWifiNative,
    149                                                            TEST_COUNTRY_CODE,
    150                                                            mListener,
    151                                                            mApInterface,
    152                                                            mNmService,
    153                                                            mWifiApConfigStore,
    154                                                            null,
    155                                                            mWifiMetrics);
    156         mLooper.dispatchAll();
    157         newSoftApManager.start();
    158         mLooper.dispatchAll();
    159         verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
    160                 WifiManager.SAP_START_FAILURE_GENERAL);
    161     }
    162 
    163     /** Tests the handling of stop command when soft AP is not started. */
    164     @Test
    165     public void stopWhenNotStarted() throws Exception {
    166         mSoftApManager = createSoftApManager(null);
    167         mSoftApManager.stop();
    168         mLooper.dispatchAll();
    169         /* Verify no state changes. */
    170         verify(mListener, never()).onStateChanged(anyInt(), anyInt());
    171     }
    172 
    173     /** Tests the handling of stop command when soft AP is started. */
    174     @Test
    175     public void stopWhenStarted() throws Exception {
    176         startSoftApAndVerifyEnabled(null);
    177 
    178         InOrder order = inOrder(mListener);
    179 
    180         mSoftApManager.stop();
    181         mLooper.dispatchAll();
    182 
    183         verify(mApInterface).stopHostapd();
    184         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
    185         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
    186     }
    187 
    188     @Test
    189     public void handlesWificondInterfaceDeath() throws Exception {
    190         startSoftApAndVerifyEnabled(null);
    191 
    192         mDeathListenerCaptor.getValue().binderDied();
    193         mLooper.dispatchAll();
    194         InOrder order = inOrder(mListener);
    195         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
    196         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
    197                 WifiManager.SAP_START_FAILURE_GENERAL);
    198     }
    199 
    200     /** Starts soft AP and verifies that it is enabled successfully. */
    201     protected void startSoftApAndVerifyEnabled(WifiConfiguration config) throws Exception {
    202         String expectedSSID;
    203         InOrder order = inOrder(mListener, mApInterfaceBinder, mApInterface, mNmService);
    204 
    205         when(mWifiNative.isHalStarted()).thenReturn(false);
    206         when(mWifiNative.setCountryCodeHal(TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT)))
    207                 .thenReturn(true);
    208 
    209         mSoftApManager = createSoftApManager(config);
    210         if (config == null) {
    211             when(mWifiApConfigStore.getApConfiguration()).thenReturn(mDefaultApConfig);
    212             expectedSSID = mDefaultApConfig.SSID;
    213         } else {
    214             expectedSSID = config.SSID;
    215         }
    216         mSoftApManager.start();
    217         mLooper.dispatchAll();
    218         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0);
    219         order.verify(mApInterfaceBinder).linkToDeath(mDeathListenerCaptor.capture(), eq(0));
    220         order.verify(mNmService).registerObserver(mNetworkObserverCaptor.capture());
    221         order.verify(mApInterface).writeHostapdConfig(
    222                 eq(expectedSSID.getBytes(StandardCharsets.UTF_8)), anyBoolean(),
    223                 anyInt(), anyInt(), any());
    224         order.verify(mApInterface).startHostapd();
    225         mNetworkObserverCaptor.getValue().interfaceLinkStateChanged(TEST_INTERFACE_NAME, true);
    226         mLooper.dispatchAll();
    227         order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0);
    228     }
    229 
    230     /** Verifies that soft AP was not disabled. */
    231     protected void verifySoftApNotDisabled() throws Exception {
    232         verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
    233         verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
    234     }
    235 }
    236