blob: cd63d3fe7d1abc9fae367ffdb56736d28dbc8cf4 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.INetworkManagementService;
import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
/** Unit tests for {@link SoftApManager}. */
@SmallTest
public class SoftApManagerTest {
private static final String TAG = "SoftApManagerTest";
private static final String TEST_INTERFACE_NAME = "TestInterface";
private static final String TEST_COUNTRY_CODE = "TestCountry";
private static final Integer[] ALLOWED_2G_CHANNELS = {1, 2, 3, 4};
private static final String[] AVAILABLE_DEVICES = { TEST_INTERFACE_NAME };
private final ArrayList<Integer> mAllowed2GChannels =
new ArrayList<Integer>(Arrays.asList(ALLOWED_2G_CHANNELS));
TestLooper mLooper;
@Mock Context mContext;
@Mock WifiNative mWifiNative;
@Mock INetworkManagementService mNmService;
@Mock ConnectivityManager mConnectivityManager;
@Mock SoftApManager.Listener mListener;
@Mock InterfaceConfiguration mInterfaceConfiguration;
/**
* Internal BroadcastReceiver that SoftApManager uses to listen for tethering
* events from ConnectivityManager.
*/
BroadcastReceiver mBroadcastReceiver;
SoftApManager mSoftApManager;
/** Sets up test. */
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mLooper = new TestLooper();
when(mWifiNative.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
when(mNmService.getInterfaceConfig(TEST_INTERFACE_NAME))
.thenReturn(mInterfaceConfiguration);
when(mConnectivityManager.getTetherableWifiRegexs())
.thenReturn(AVAILABLE_DEVICES);
mSoftApManager = new SoftApManager(mContext,
mLooper.getLooper(),
mWifiNative,
mNmService,
mConnectivityManager,
TEST_COUNTRY_CODE,
mAllowed2GChannels,
mListener);
ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mContext).registerReceiver(
broadcastReceiverCaptor.capture(), any(IntentFilter.class));
mBroadcastReceiver = broadcastReceiverCaptor.getValue();
mLooper.dispatchAll();
}
/** Verifies startSoftAp will fail if AP configuration is not provided. */
@Test
public void startSoftApWithoutConfig() throws Exception {
InOrder order = inOrder(mListener);
mSoftApManager.start(null);
mLooper.dispatchAll();
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0);
order.verify(mListener).onStateChanged(
WifiManager.WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL);
}
/** Tests the handling of timeout after tethering is started. */
@Test
public void tetheringTimedOut() throws Exception {
startSoftApAndVerifyEnabled();
announceAvailableForTethering();
verifyTetheringRequested();
InOrder order = inOrder(mListener);
/* Move the time forward to simulate notification timeout. */
mLooper.moveTimeForward(5000);
mLooper.dispatchAll();
/* Verify soft ap is disabled. */
verify(mNmService).stopAccessPoint(eq(TEST_INTERFACE_NAME));
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
}
/** Tests the handling of tethered notification after tethering is started. */
@Test
public void tetherCompleted() throws Exception {
startSoftApAndVerifyEnabled();
announceAvailableForTethering();
verifyTetheringRequested();
announceTethered();
verifySoftApNotDisabled();
}
/** Tests the handling of stop command when soft AP is not started. */
@Test
public void stopWhenNotStarted() throws Exception {
mSoftApManager.stop();
mLooper.dispatchAll();
/* Verify no state changes. */
verify(mListener, never()).onStateChanged(anyInt(), anyInt());
}
/** Tests the handling of stop command when soft AP is started. */
@Test
public void stopWhenStarted() throws Exception {
startSoftApAndVerifyEnabled();
InOrder order = inOrder(mListener);
mSoftApManager.stop();
mLooper.dispatchAll();
verify(mNmService).stopAccessPoint(TEST_INTERFACE_NAME);
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
}
/** Starts soft AP and verifies that it is enabled successfully. */
protected void startSoftApAndVerifyEnabled() throws Exception {
InOrder order = inOrder(mListener);
/**
* Only test the default configuration. Testing for different configurations
* are taken care of by ApConfigUtilTest.
*/
WifiConfiguration config = new WifiConfiguration();
config.apBand = WifiConfiguration.AP_BAND_2GHZ;
when(mWifiNative.isHalStarted()).thenReturn(false);
when(mWifiNative.setCountryCodeHal(TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT)))
.thenReturn(true);
mSoftApManager.start(config);
mLooper.dispatchAll();
verify(mNmService).startAccessPoint(
any(WifiConfiguration.class), eq(TEST_INTERFACE_NAME));
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLING, 0);
order.verify(mListener).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0);
}
/** Verifies that soft AP was not disabled. */
protected void verifySoftApNotDisabled() throws Exception {
verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLING, 0);
verify(mListener, never()).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0);
}
/** Sends a broadcast intent indicating that the interface is available for tethering. */
protected void announceAvailableForTethering() throws Exception {
when(mConnectivityManager.tether(TEST_INTERFACE_NAME))
.thenReturn(ConnectivityManager.TETHER_ERROR_NO_ERROR);
ArrayList<String> availableList =
new ArrayList<String>(Arrays.asList(AVAILABLE_DEVICES));
TestUtil.sendTetherStateChanged(
mBroadcastReceiver, mContext, availableList, new ArrayList<String>());
mLooper.dispatchAll();
}
/** Verifies that tethering was requested. */
protected void verifyTetheringRequested() throws Exception {
verify(mInterfaceConfiguration).setLinkAddress(any(LinkAddress.class));
verify(mInterfaceConfiguration).setInterfaceUp();
verify(mNmService).setInterfaceConfig(eq(TEST_INTERFACE_NAME), eq(mInterfaceConfiguration));
}
/** Sends a broadcast intent indicating that the interface is tethered. */
protected void announceTethered() throws Exception {
ArrayList<String> deviceList =
new ArrayList<String>(Arrays.asList(AVAILABLE_DEVICES));
TestUtil.sendTetherStateChanged(
mBroadcastReceiver, mContext, deviceList, deviceList);
mLooper.dispatchAll();
}
}