From 7335b7c3db2656c8379296593c7880ae56ccf9ea Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Mon, 9 May 2016 15:31:22 -0700 Subject: [NAN] NAN RTT service implementation Pipe NAN RTT through NAN service - filling in peer MAC address and RTT configuration parameters. Bug: 26564277 Change-Id: I9c69768a0d9c2ae399c272fd7ff962984c517065 --- .../server/wifi/nan/WifiNanManagerTest.java | 87 +++++++++++++ .../wifi/nan/WifiNanRttStateManagerTest.java | 141 +++++++++++++++++++++ .../server/wifi/nan/WifiNanServiceImplTest.java | 62 ++++++++- .../server/wifi/nan/WifiNanStateManagerTest.java | 80 +++++++++++- 4 files changed, 367 insertions(+), 3 deletions(-) create mode 100644 tests/wifitests/src/com/android/server/wifi/nan/WifiNanRttStateManagerTest.java (limited to 'tests') diff --git a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanManagerTest.java b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanManagerTest.java index 7de78b978..0ce9d4b9a 100644 --- a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanManagerTest.java @@ -19,6 +19,7 @@ package com.android.server.wifi.nan; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.inOrder; @@ -26,6 +27,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import android.net.wifi.RttManager; import android.net.wifi.nan.ConfigRequest; import android.net.wifi.nan.IWifiNanEventCallback; import android.net.wifi.nan.IWifiNanManager; @@ -78,6 +80,9 @@ public class WifiNanManagerTest { @Mock public WifiNanSubscribeSession mockSubscribeSession; + @Mock + public RttManager.RttListener mockRttListener; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -864,6 +869,88 @@ public class WifiNanManagerTest { new PublishConfig.Builder().setTtlSec(-10); } + /* + * Ranging tests + */ + + /** + * Validate ranging + success flow: (1) connect, (2) create a (publish) session, (3) start + * ranging, (4) ranging success callback, (5) ranging aborted callback ignored (since + * listener removed). + */ + @Test + public void testRangingCallbacks() throws Exception { + final int clientId = 4565; + final int sessionId = 123; + final int rangingId = 3482; + final ConfigRequest configRequest = new ConfigRequest.Builder().build(); + final PublishConfig publishConfig = new PublishConfig.Builder().build(); + final RttManager.RttParams rttParams = new RttManager.RttParams(); + rttParams.deviceType = RttManager.RTT_PEER_NAN; + rttParams.bssid = Integer.toString(1234); + final RttManager.RttResult rttResults = new RttManager.RttResult(); + rttResults.distance = 10; + + when(mockNanService.connect(any(IBinder.class), any(IWifiNanEventCallback.class), + eq(configRequest))).thenReturn(clientId); + when(mockNanService.startRanging(anyInt(), anyInt(), + any(RttManager.ParcelableRttParams.class))).thenReturn(rangingId); + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mockNanService, + mockPublishSession, mockRttListener); + ArgumentCaptor clientProxyCallback = ArgumentCaptor + .forClass(IWifiNanEventCallback.class); + ArgumentCaptor sessionProxyCallback = ArgumentCaptor + .forClass(IWifiNanSessionCallback.class); + ArgumentCaptor publishSession = ArgumentCaptor + .forClass(WifiNanPublishSession.class); + ArgumentCaptor rttParamCaptor = ArgumentCaptor + .forClass(RttManager.ParcelableRttParams.class); + ArgumentCaptor rttResultsCaptor = ArgumentCaptor + .forClass(RttManager.RttResult[].class); + + // (1) connect successfully + mDut.connect(mMockLooper.getLooper(), mockCallback, configRequest); + inOrder.verify(mockNanService).connect(any(IBinder.class), clientProxyCallback.capture(), + eq(configRequest)); + clientProxyCallback.getValue().onConnectSuccess(); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onConnectSuccess(); + + // (2) publish successfully + mDut.publish(publishConfig, mockSessionCallback); + inOrder.verify(mockNanService).publish(eq(clientId), eq(publishConfig), + sessionProxyCallback.capture()); + sessionProxyCallback.getValue().onSessionStarted(sessionId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture()); + + // (3) start ranging + publishSession.getValue().startRanging(new RttManager.RttParams[]{rttParams}, + mockRttListener); + inOrder.verify(mockNanService).startRanging(eq(clientId), eq(sessionId), + rttParamCaptor.capture()); + collector.checkThat("RttParams.deviceType", rttParams.deviceType, + equalTo(rttParamCaptor.getValue().mParams[0].deviceType)); + collector.checkThat("RttParams.bssid", rttParams.bssid, + equalTo(rttParamCaptor.getValue().mParams[0].bssid)); + + // (4) ranging success callback + clientProxyCallback.getValue().onRangingSuccess(rangingId, + new RttManager.ParcelableRttResults(new RttManager.RttResult[] { rttResults })); + mMockLooper.dispatchAll(); + inOrder.verify(mockRttListener).onSuccess(rttResultsCaptor.capture()); + collector.checkThat("RttResult.distance", rttResults.distance, + equalTo(rttResultsCaptor.getValue()[0].distance)); + + // (5) ranging aborted callback (should be ignored since listener cleared on first callback) + clientProxyCallback.getValue().onRangingAborted(rangingId); + mMockLooper.dispatchAll(); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockNanService, + mockPublishSession, mockRttListener); + } + /* * Utilities */ diff --git a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanRttStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanRttStateManagerTest.java new file mode 100644 index 000000000..f8af8051c --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanRttStateManagerTest.java @@ -0,0 +1,141 @@ +/* + * 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.nan; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNull.nullValue; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.wifi.IRttManager; +import android.net.wifi.RttManager; +import android.os.Handler; +import android.os.Message; +import android.test.suitebuilder.annotation.SmallTest; + +import com.android.server.wifi.BidirectionalAsyncChannelServer; +import com.android.server.wifi.MockLooper; + +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 WifiNanManager class. + */ +@SmallTest +public class WifiNanRttStateManagerTest { + private WifiNanRttStateManager mDut; + private MockLooper mMockLooper; + + @Mock + private Context mMockContext; + + @Mock + private Handler mMockHandler; + + @Mock + private IRttManager mMockRttService; + + @Rule + public ErrorCollector collector = new ErrorCollector(); + + /** + * Initialize mocks. + */ + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mDut = new WifiNanRttStateManager(); + mMockLooper = new MockLooper(); + BidirectionalAsyncChannelServer server = new BidirectionalAsyncChannelServer( + mMockContext, mMockLooper.getLooper(), mMockHandler); + when(mMockRttService.getMessenger()).thenReturn(server.getMessenger()); + + mDut.startWithRttService(mMockContext, mMockLooper.getLooper(), mMockRttService); + } + + /** + * Validates that startRanging flow works: (1) start ranging, (2) get success callback - pass + * to client (while nulling BSSID info), (3) get fail callback - ignored (since client + * cleaned-out after first callback). + */ + @Test + public void testStartRanging() throws Exception { + final int rangingId = 1234; + WifiNanClientState mockClient = mock(WifiNanClientState.class); + RttManager.RttParams[] params = new RttManager.RttParams[1]; + params[0] = new RttManager.RttParams(); + RttManager.ParcelableRttResults results = + new RttManager.ParcelableRttResults(new RttManager.RttResult[2]); + results.mResults[0] = new RttManager.RttResult(); + results.mResults[0].bssid = "something non-null"; + results.mResults[1] = new RttManager.RttResult(); + results.mResults[1].bssid = "really really non-null"; + + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + ArgumentCaptor rttResultsCaptor = + ArgumentCaptor.forClass(RttManager.ParcelableRttResults.class); + + InOrder inOrder = inOrder(mMockHandler, mockClient); + + // (1) start ranging + mDut.startRanging(rangingId, mockClient, params); + mMockLooper.dispatchAll(); + inOrder.verify(mMockHandler).handleMessage(messageCaptor.capture()); + Message msg = messageCaptor.getValue(); + collector.checkThat("msg.what=RttManager.CMD_OP_START_RANGING", msg.what, + equalTo(RttManager.CMD_OP_START_RANGING)); + collector.checkThat("rangingId", msg.arg2, equalTo(rangingId)); + collector.checkThat("RTT params", ((RttManager.ParcelableRttParams) msg.obj).mParams, + equalTo(params)); + + // (2) get success callback - pass to client + Message successMessage = Message.obtain(); + successMessage.what = RttManager.CMD_OP_SUCCEEDED; + successMessage.arg2 = rangingId; + successMessage.obj = results; + msg.replyTo.send(successMessage); + mMockLooper.dispatchAll(); + inOrder.verify(mockClient).onRangingSuccess(eq(rangingId), rttResultsCaptor.capture()); + collector.checkThat("ParcelableRttResults object", results, + equalTo(rttResultsCaptor.getValue())); + collector.checkThat("RttResults[0].bssid null", + rttResultsCaptor.getValue().mResults[0].bssid, nullValue()); + collector.checkThat("RttResults[1].bssid null", + rttResultsCaptor.getValue().mResults[1].bssid, nullValue()); + + // (3) get fail callback - ignored + Message failMessage = Message.obtain(); + failMessage.what = RttManager.CMD_OP_ABORTED; + failMessage.arg2 = rangingId; + msg.replyTo.send(failMessage); + mMockLooper.dispatchAll(); + + verifyNoMoreInteractions(mMockHandler, mockClient); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanServiceImplTest.java index 577f9ef2c..c5b9c37c7 100644 --- a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanServiceImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanServiceImplTest.java @@ -16,6 +16,7 @@ package com.android.server.wifi.nan; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; @@ -26,6 +27,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.PackageManager; +import android.net.wifi.RttManager; import android.net.wifi.nan.ConfigRequest; import android.net.wifi.nan.IWifiNanEventCallback; import android.net.wifi.nan.IWifiNanSessionCallback; @@ -130,7 +132,7 @@ public class WifiNanServiceImplTest { @Test public void testDisableUsage() throws Exception { mDut.enableUsage(); - int clientId = doConnect(); + doConnect(); mDut.disableUsage(); verify(mNanStateManagerMock).disableUsage(); @@ -361,6 +363,64 @@ public class WifiNanServiceImplTest { message.length, messageId); } + /** + * Validate startRanging() - correct pass-through args + */ + @Test + public void testStartRanging() { + int clientId = doConnect(); + int sessionId = 65345; + RttManager.ParcelableRttParams params = + new RttManager.ParcelableRttParams(new RttManager.RttParams[1]); + + ArgumentCaptor paramsCaptor = + ArgumentCaptor.forClass(RttManager.RttParams[].class); + + int rangingId = mDut.startRanging(clientId, sessionId, params); + + verify(mNanStateManagerMock).startRanging(eq(clientId), eq(sessionId), + paramsCaptor.capture(), eq(rangingId)); + + assertArrayEquals(paramsCaptor.getValue(), params.mParams); + } + + /** + * Validates that sequential startRanging() calls return increasing ranging IDs. + */ + @Test + public void testRangingIdIncrementing() { + int loopCount = 100; + int clientId = doConnect(); + int sessionId = 65345; + RttManager.ParcelableRttParams params = + new RttManager.ParcelableRttParams(new RttManager.RttParams[1]); + + int prevRangingId = 0; + for (int i = 0; i < loopCount; ++i) { + int rangingId = mDut.startRanging(clientId, sessionId, params); + if (i != 0) { + assertTrue("Client ID incrementing", rangingId > prevRangingId); + } + prevRangingId = rangingId; + } + } + + /** + * Validates that startRanging() requires a non-empty list + */ + @Test(expected = IllegalArgumentException.class) + public void testStartRangingZeroArgs() { + int clientId = doConnect(); + int sessionId = 65345; + RttManager.ParcelableRttParams params = + new RttManager.ParcelableRttParams(new RttManager.RttParams[0]); + + ArgumentCaptor paramsCaptor = + ArgumentCaptor.forClass(RttManager.RttParams[].class); + + int rangingId = mDut.startRanging(clientId, sessionId, params); + } + /* * Tests of internal state of WifiNanServiceImpl: very limited (not usually * a good idea). However, these test that the internal state is cleaned-up diff --git a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanStateManagerTest.java index 68d3dddd6..65d36807d 100644 --- a/tests/wifitests/src/com/android/server/wifi/nan/WifiNanStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/nan/WifiNanStateManagerTest.java @@ -33,6 +33,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.Intent; +import android.net.wifi.RttManager; import android.net.wifi.nan.ConfigRequest; import android.net.wifi.nan.IWifiNanEventCallback; import android.net.wifi.nan.IWifiNanSessionCallback; @@ -71,6 +72,7 @@ public class WifiNanStateManagerTest { private WifiNanStateManager mDut; @Mock private WifiNanNative mMockNative; @Mock private Context mMockContext; + @Mock private WifiNanRttStateManager mMockNanRttStateManager; MockAlarmManager mAlarmManager; @Rule @@ -89,7 +91,7 @@ public class WifiNanStateManagerTest { mMockLooper = new MockLooper(); - mDut = installNewNanStateManagerAndResetState(); + mDut = installNewNanStateManagerAndResetState(mMockNanRttStateManager); mDut.start(mMockContext, mMockLooper.getLooper()); mDut.enableUsage(); mMockLooper.dispatchAll(); @@ -1050,6 +1052,75 @@ public class WifiNanStateManagerTest { verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); } + /** + * Validate that start ranging function fills-in correct MAC addresses for peer IDs and + * passed along to RTT module. + */ + @Test + public void testStartRanging() throws Exception { + final int clientId = 1005; + final int subscribeId = 15; + final int requestorId = 22; + final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); + final String peerSsi = "some peer ssi data"; + final String peerMatchFilter = "filter binary array represented as string"; + final int rangingId = 18423; + final RttManager.RttParams[] params = new RttManager.RttParams[2]; + params[0] = new RttManager.RttParams(); + params[0].bssid = Integer.toString(requestorId); + params[1] = new RttManager.RttParams(); + params[1].bssid = Integer.toString(requestorId + 5); + + ConfigRequest configRequest = new ConfigRequest.Builder().build(); + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + + IWifiNanEventCallback mockCallback = mock(IWifiNanEventCallback.class); + IWifiNanSessionCallback mockSessionCallback = mock(IWifiNanSessionCallback.class); + + ArgumentCaptor transactionId = ArgumentCaptor.forClass(Short.class); + ArgumentCaptor sessionId = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor clientCaptor = + ArgumentCaptor.forClass(WifiNanClientState.class); + ArgumentCaptor rttParamsCaptor = + ArgumentCaptor.forClass(RttManager.RttParams[].class); + + InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative, + mMockNanRttStateManager); + + // (1) connect + mDut.connect(clientId, mockCallback, configRequest); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), + eq(true)); + mDut.onConfigSuccessResponse(transactionId.getValue()); + mMockLooper.dispatchAll(); + inOrder.verify(mockCallback).onConnectSuccess(); + + // (2) subscribe & match + mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); + mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); + mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), + peerSsi.length(), peerMatchFilter.getBytes(), peerMatchFilter.length()); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); + inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), + peerSsi.length(), peerMatchFilter.getBytes(), peerMatchFilter.length()); + + // (3) start ranging: pass along a valid peer ID and an invalid one + mDut.startRanging(clientId, sessionId.getValue(), params, rangingId); + mMockLooper.dispatchAll(); + inOrder.verify(mMockNanRttStateManager).startRanging(eq(rangingId), clientCaptor.capture(), + rttParamsCaptor.capture()); + collector.checkThat("RttParams[0].bssid", "06:07:08:09:0A:0B", + equalTo(rttParamsCaptor.getValue()[0].bssid)); + collector.checkThat("RttParams[1].bssid", "", equalTo(rttParamsCaptor.getValue()[1].bssid)); + + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, + mMockNanRttStateManager); + } + /** * Test sequence of configuration: (1) config1, (2) config2 - incompatible, * (3) config3 - compatible with config1 (requiring upgrade), (4) disconnect @@ -1541,7 +1612,8 @@ public class WifiNanStateManagerTest { * Utilities */ - private static WifiNanStateManager installNewNanStateManagerAndResetState() throws Exception { + private static WifiNanStateManager installNewNanStateManagerAndResetState( + WifiNanRttStateManager mockRtt) throws Exception { Constructor ctr = WifiNanStateManager.class.getDeclaredConstructor(); ctr.setAccessible(true); WifiNanStateManager nanStateManager = ctr.newInstance(); @@ -1550,6 +1622,10 @@ public class WifiNanStateManagerTest { field.setAccessible(true); field.set(null, nanStateManager); + field = WifiNanStateManager.class.getDeclaredField("mRtt"); + field.setAccessible(true); + field.set(nanStateManager, mockRtt); + return WifiNanStateManager.getInstance(); } -- cgit v1.2.3