| /* |
| * Copyright (C) 2017 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.aware; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNull; |
| import static org.mockito.ArgumentMatchers.any; |
| import static org.mockito.ArgumentMatchers.eq; |
| import static org.mockito.Mockito.inOrder; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.verifyNoMoreInteractions; |
| import static org.mockito.Mockito.when; |
| |
| import android.hardware.wifi.V1_0.IWifiNanIface; |
| import android.hardware.wifi.V1_0.IfaceType; |
| import android.hardware.wifi.V1_0.WifiStatus; |
| import android.hardware.wifi.V1_0.WifiStatusCode; |
| import android.os.Handler; |
| |
| import com.android.server.wifi.HalDeviceManager; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.ErrorCollector; |
| import org.mockito.ArgumentCaptor; |
| import org.mockito.InOrder; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| |
| /** |
| * Unit test harness for WifiAwareNativeManager. |
| */ |
| public class WifiAwareNativeManagerTest { |
| private WifiAwareNativeManager mDut; |
| @Mock private WifiAwareStateManager mWifiAwareStateManagerMock; |
| @Mock private HalDeviceManager mHalDeviceManager; |
| @Mock private WifiAwareNativeCallback mWifiAwareNativeCallback; |
| @Mock private IWifiNanIface mWifiNanIfaceMock; |
| @Mock android.hardware.wifi.V1_2.IWifiNanIface mIWifiNanIface12Mock; |
| @Mock private Handler mHandlerMock; |
| private ArgumentCaptor<HalDeviceManager.ManagerStatusListener> mManagerStatusListenerCaptor = |
| ArgumentCaptor.forClass(HalDeviceManager.ManagerStatusListener.class); |
| private ArgumentCaptor<HalDeviceManager.InterfaceDestroyedListener> |
| mDestroyedListenerCaptor = ArgumentCaptor.forClass( |
| HalDeviceManager.InterfaceDestroyedListener.class); |
| private ArgumentCaptor<HalDeviceManager.InterfaceAvailableForRequestListener> |
| mAvailListenerCaptor = ArgumentCaptor.forClass( |
| HalDeviceManager.InterfaceAvailableForRequestListener.class); |
| private InOrder mInOrder; |
| @Rule public ErrorCollector collector = new ErrorCollector(); |
| |
| private WifiStatus mStatusOk; |
| |
| private class MockableWifiAwareNativeManager extends WifiAwareNativeManager { |
| MockableWifiAwareNativeManager(WifiAwareStateManager awareStateManager, |
| HalDeviceManager halDeviceManager, |
| WifiAwareNativeCallback wifiAwareNativeCallback) { |
| super(awareStateManager, halDeviceManager, wifiAwareNativeCallback); |
| } |
| |
| @Override |
| public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { |
| return (iface == mIWifiNanIface12Mock) ? mIWifiNanIface12Mock : null; |
| } |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| |
| mStatusOk = new WifiStatus(); |
| mStatusOk.code = WifiStatusCode.SUCCESS; |
| |
| when(mWifiNanIfaceMock.registerEventCallback(any())).thenReturn(mStatusOk); |
| when(mIWifiNanIface12Mock.registerEventCallback_1_2(any())).thenReturn(mStatusOk); |
| |
| mDut = new MockableWifiAwareNativeManager(mWifiAwareStateManagerMock, |
| mHalDeviceManager, mWifiAwareNativeCallback); |
| mDut.start(mHandlerMock); |
| |
| mInOrder = inOrder(mWifiAwareStateManagerMock, mHalDeviceManager, mWifiNanIfaceMock, |
| mIWifiNanIface12Mock); |
| |
| // validate (and capture) that register manage status callback |
| mInOrder.verify(mHalDeviceManager).initialize(); |
| mInOrder.verify(mHalDeviceManager).registerStatusListener( |
| mManagerStatusListenerCaptor.capture(), any()); |
| } |
| |
| /** |
| * Test the control flow of the manager when Aware isn't being actively used: |
| * |
| * 1. onStatusChange (ready/started) |
| * 2. on available -> enableUsage |
| * 3. onStatusChange (!started) -> disableUsage |
| * 4. onStatusChange (ready/started) + available -> enableUsage |
| * 5. on not available -> disableUsage |
| * |
| * --> no interface creation at any point! |
| */ |
| @Test |
| public void testControlFlowWithoutInterface() { |
| // configure HalDeviceManager as ready/wifi started (and to return an interface if |
| // requested) |
| when(mHalDeviceManager.isReady()).thenReturn(true); |
| when(mHalDeviceManager.isStarted()).thenReturn(true); |
| when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); |
| |
| // 1. onStatusChange (ready/started) |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( |
| eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); |
| |
| // 2. NAN is available -> enableUsage |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(true); |
| mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); |
| |
| // 3. onStatusChange (not ready) -> disableUsage |
| when(mHalDeviceManager.isStarted()).thenReturn(false); |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| |
| mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); |
| |
| // 4. onStatusChange (ready/started) + available -> enableUsage |
| when(mHalDeviceManager.isStarted()).thenReturn(true); |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( |
| eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(true); |
| |
| mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); |
| |
| // 5. not available -> disableUsage |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(false); |
| |
| mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); |
| |
| mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); |
| verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, |
| mIWifiNanIface12Mock); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| } |
| |
| /** |
| * Test the control flow (and reference counting) of the manager when Aware is actively used and |
| * reference counted (i.e. irregular requests/releases). |
| */ |
| @Test |
| public void testReferenceCounting() throws Exception { |
| // configure HalDeviceManager as ready/wifi started (and to return an interface if |
| // requested) |
| when(mHalDeviceManager.isReady()).thenReturn(true); |
| when(mHalDeviceManager.isStarted()).thenReturn(true); |
| when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); |
| |
| // 1. onStatusChange (ready/started) |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( |
| eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(true); |
| mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); |
| |
| // 2. request (interface obtained) |
| mDut.tryToGetAware(); |
| mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), |
| any()); |
| mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); |
| assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); |
| |
| // 3. release (interface released) |
| mDut.releaseAware(); |
| mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); |
| |
| // 4. request (interface obtained) |
| mDut.tryToGetAware(); |
| mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), |
| any()); |
| mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); |
| assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); |
| |
| // 5. request (nop - already have interface) |
| mDut.tryToGetAware(); |
| assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); |
| |
| // 6. release (nop - reference counting requests) |
| mDut.releaseAware(); |
| assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); |
| |
| // 7. release (interface released) |
| mDut.releaseAware(); |
| mInOrder.verify(mHalDeviceManager).removeIface(mWifiNanIfaceMock); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); |
| |
| mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); |
| mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); |
| verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, |
| mIWifiNanIface12Mock); |
| } |
| |
| /** |
| * Test the control flow when the interface gets deleted due to external |
| */ |
| @Test |
| public void testRequestFlowWithAsyncDeletes() throws Exception { |
| // configure HalDeviceManager as ready/wifi started (and to return an interface if |
| // requested) |
| when(mHalDeviceManager.isReady()).thenReturn(true); |
| when(mHalDeviceManager.isStarted()).thenReturn(true); |
| when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mWifiNanIfaceMock); |
| |
| // 1. onStatusChange (ready/started) |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( |
| eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(true); |
| mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); |
| |
| // 2. request (interface obtained) |
| mDut.tryToGetAware(); |
| mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), |
| any()); |
| mInOrder.verify(mWifiNanIfaceMock).registerEventCallback(any()); |
| assertEquals("Interface mismatch", mWifiNanIfaceMock, mDut.getWifiNanIface()); |
| |
| // 3. interface gets destroyed |
| mDestroyedListenerCaptor.getValue().onDestroyed("nan0"); |
| |
| mInOrder.verify(mWifiAwareStateManagerMock).disableUsage(); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| // 4. a release doesn't do much |
| mDut.releaseAware(); |
| |
| mInOrder.verify(mHalDeviceManager, never()).createNanIface(any(), any()); |
| mInOrder.verify(mHalDeviceManager, never()).removeIface(any()); |
| verifyNoMoreInteractions(mWifiAwareStateManagerMock, mWifiNanIfaceMock, |
| mIWifiNanIface12Mock); |
| } |
| |
| /** |
| * Test the basic control flow for HAL 1.2 - validate that the correct event registration |
| * occurs. |
| */ |
| @Test |
| public void testBasicFlowHal12() throws Exception { |
| // configure HalDeviceManager as ready/wifi started (and to return an interface if |
| // requested) |
| when(mHalDeviceManager.isReady()).thenReturn(true); |
| when(mHalDeviceManager.isStarted()).thenReturn(true); |
| when(mHalDeviceManager.createNanIface(any(), any())).thenReturn(mIWifiNanIface12Mock); |
| |
| // 1. onStatusChange (ready/started) |
| mManagerStatusListenerCaptor.getValue().onStatusChanged(); |
| mInOrder.verify(mHalDeviceManager).registerInterfaceAvailableForRequestListener( |
| eq(IfaceType.NAN), mAvailListenerCaptor.capture(), any(Handler.class)); |
| assertNull("Interface non-null!", mDut.getWifiNanIface()); |
| |
| mAvailListenerCaptor.getValue().onAvailabilityChanged(true); |
| mInOrder.verify(mWifiAwareStateManagerMock).enableUsage(); |
| |
| // 2. request (interface obtained) |
| mDut.tryToGetAware(); |
| mInOrder.verify(mHalDeviceManager).createNanIface(mDestroyedListenerCaptor.capture(), |
| any()); |
| mInOrder.verify(mIWifiNanIface12Mock).registerEventCallback_1_2(any()); |
| assertEquals("Interface mismatch", mIWifiNanIface12Mock, mDut.getWifiNanIface()); |
| } |
| } |