WifiAwareDataPathStateManagerTest.java revision bd0447ff06c5719494960e2e3ec95b84941baf2a
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.aware; 18 19import static android.hardware.wifi.V1_0.NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP; 20 21import static org.hamcrest.core.IsEqual.equalTo; 22import static org.junit.Assert.assertTrue; 23import static org.mockito.ArgumentMatchers.any; 24import static org.mockito.ArgumentMatchers.anyBoolean; 25import static org.mockito.ArgumentMatchers.anyInt; 26import static org.mockito.ArgumentMatchers.anyShort; 27import static org.mockito.ArgumentMatchers.eq; 28import static org.mockito.Mockito.inOrder; 29import static org.mockito.Mockito.mock; 30import static org.mockito.Mockito.verify; 31import static org.mockito.Mockito.verifyNoMoreInteractions; 32import static org.mockito.Mockito.when; 33 34import android.app.test.TestAlarmManager; 35import android.content.Context; 36import android.net.ConnectivityManager; 37import android.net.NetworkCapabilities; 38import android.net.NetworkFactory; 39import android.net.NetworkRequest; 40import android.net.NetworkSpecifier; 41import android.net.wifi.aware.AttachCallback; 42import android.net.wifi.aware.ConfigRequest; 43import android.net.wifi.aware.DiscoverySession; 44import android.net.wifi.aware.DiscoverySessionCallback; 45import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; 46import android.net.wifi.aware.IWifiAwareEventCallback; 47import android.net.wifi.aware.IWifiAwareManager; 48import android.net.wifi.aware.PeerHandle; 49import android.net.wifi.aware.PublishConfig; 50import android.net.wifi.aware.PublishDiscoverySession; 51import android.net.wifi.aware.SubscribeConfig; 52import android.net.wifi.aware.SubscribeDiscoverySession; 53import android.net.wifi.aware.WifiAwareManager; 54import android.net.wifi.aware.WifiAwareNetworkSpecifier; 55import android.net.wifi.aware.WifiAwareSession; 56import android.os.Handler; 57import android.os.INetworkManagementService; 58import android.os.Message; 59import android.os.Messenger; 60import android.os.test.TestLooper; 61import android.test.suitebuilder.annotation.SmallTest; 62import android.util.Pair; 63 64import com.android.internal.util.AsyncChannel; 65 66import libcore.util.HexEncoding; 67 68import org.junit.Before; 69import org.junit.Rule; 70import org.junit.Test; 71import org.junit.rules.ErrorCollector; 72import org.mockito.ArgumentCaptor; 73import org.mockito.InOrder; 74import org.mockito.Mock; 75import org.mockito.MockitoAnnotations; 76 77import java.lang.reflect.Field; 78import java.util.Arrays; 79 80/** 81 * Unit test harness for WifiAwareDataPathStateManager class. 82 */ 83@SmallTest 84public class WifiAwareDataPathStateManagerTest { 85 private static final String sAwareInterfacePrefix = "aware_data"; 86 87 private TestLooper mMockLooper; 88 private Handler mMockLooperHandler; 89 private WifiAwareStateManager mDut; 90 @Mock private WifiAwareNativeApi mMockNative; 91 @Mock private Context mMockContext; 92 @Mock private IWifiAwareManager mMockAwareService; 93 @Mock private ConnectivityManager mMockCm; 94 @Mock private INetworkManagementService mMockNwMgt; 95 @Mock private WifiAwareDataPathStateManager.NetworkInterfaceWrapper mMockNetworkInterface; 96 @Mock private IWifiAwareEventCallback mMockCallback; 97 @Mock IWifiAwareDiscoverySessionCallback mMockSessionCallback; 98 TestAlarmManager mAlarmManager; 99 100 @Rule 101 public ErrorCollector collector = new ErrorCollector(); 102 103 /** 104 * Initialize mocks. 105 */ 106 @Before 107 public void setUp() throws Exception { 108 MockitoAnnotations.initMocks(this); 109 110 mAlarmManager = new TestAlarmManager(); 111 when(mMockContext.getSystemService(Context.ALARM_SERVICE)) 112 .thenReturn(mAlarmManager.getAlarmManager()); 113 114 when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(mMockCm); 115 116 mMockLooper = new TestLooper(); 117 mMockLooperHandler = new Handler(mMockLooper.getLooper()); 118 119 mDut = new WifiAwareStateManager(); 120 mDut.setNative(mMockNative); 121 mDut.start(mMockContext, mMockLooper.getLooper()); 122 mDut.startLate(); 123 124 when(mMockNative.getCapabilities(anyShort())).thenReturn(true); 125 when(mMockNative.enableAndConfigure(anyShort(), any(), anyBoolean(), 126 anyBoolean())).thenReturn(true); 127 when(mMockNative.disable(anyShort())).thenReturn(true); 128 when(mMockNative.publish(anyShort(), anyInt(), any())).thenReturn(true); 129 when(mMockNative.subscribe(anyShort(), anyInt(), any())) 130 .thenReturn(true); 131 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 132 any(), anyInt())).thenReturn(true); 133 when(mMockNative.stopPublish(anyShort(), anyInt())).thenReturn(true); 134 when(mMockNative.stopSubscribe(anyShort(), anyInt())).thenReturn(true); 135 when(mMockNative.createAwareNetworkInterface(anyShort(), any())).thenReturn(true); 136 when(mMockNative.deleteAwareNetworkInterface(anyShort(), any())).thenReturn(true); 137 when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), 138 any(), any(), any(), any(), 139 any())).thenReturn(true); 140 when(mMockNative.respondToDataPathRequest(anyShort(), anyBoolean(), anyInt(), any(), 141 any(), any(), any())).thenReturn(true); 142 when(mMockNative.endDataPath(anyShort(), anyInt())).thenReturn(true); 143 144 when(mMockNetworkInterface.configureAgentProperties(any(), any(), anyInt(), any(), any(), 145 any())).thenReturn(true); 146 147 installDataPathStateManagerMocks(); 148 } 149 150 /** 151 * Validates that creating and deleting all interfaces works based on capabilities. 152 */ 153 @Test 154 public void testCreateDeleteAllInterfaces() throws Exception { 155 final int numNdis = 3; 156 final int failCreateInterfaceIndex = 1; 157 158 Capabilities capabilities = new Capabilities(); 159 capabilities.maxNdiInterfaces = numNdis; 160 161 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 162 ArgumentCaptor<String> interfaceName = ArgumentCaptor.forClass(String.class); 163 InOrder inOrder = inOrder(mMockNative); 164 165 // (1) get capabilities 166 mDut.queryCapabilities(); 167 mMockLooper.dispatchAll(); 168 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 169 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities); 170 mMockLooper.dispatchAll(); 171 172 // (2) create all interfaces 173 mDut.createAllDataPathInterfaces(); 174 mMockLooper.dispatchAll(); 175 for (int i = 0; i < numNdis; ++i) { 176 inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), 177 interfaceName.capture()); 178 collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i, 179 equalTo(interfaceName.getValue())); 180 mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); 181 mMockLooper.dispatchAll(); 182 } 183 184 // (3) delete all interfaces [one unsuccessfully] - note that will not necessarily be 185 // done sequentially 186 boolean[] done = new boolean[numNdis]; 187 Arrays.fill(done, false); 188 mDut.deleteAllDataPathInterfaces(); 189 mMockLooper.dispatchAll(); 190 for (int i = 0; i < numNdis; ++i) { 191 inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(), 192 interfaceName.capture()); 193 int interfaceIndex = Integer.valueOf( 194 interfaceName.getValue().substring(sAwareInterfacePrefix.length())); 195 done[interfaceIndex] = true; 196 if (interfaceIndex == failCreateInterfaceIndex) { 197 mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), false, 0); 198 } else { 199 mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0); 200 } 201 mMockLooper.dispatchAll(); 202 } 203 for (int i = 0; i < numNdis; ++i) { 204 collector.checkThat("interface deleted -- " + i, done[i], equalTo(true)); 205 } 206 207 // (4) create all interfaces (should get a delete for the one which couldn't delete earlier) 208 mDut.createAllDataPathInterfaces(); 209 mMockLooper.dispatchAll(); 210 for (int i = 0; i < numNdis; ++i) { 211 if (i == failCreateInterfaceIndex) { 212 inOrder.verify(mMockNative).deleteAwareNetworkInterface(transactionId.capture(), 213 interfaceName.capture()); 214 collector.checkThat("interface delete pre-create -- " + i, 215 sAwareInterfacePrefix + i, equalTo(interfaceName.getValue())); 216 mDut.onDeleteDataPathInterfaceResponse(transactionId.getValue(), true, 0); 217 mMockLooper.dispatchAll(); 218 } 219 inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), 220 interfaceName.capture()); 221 collector.checkThat("interface created -- " + i, sAwareInterfacePrefix + i, 222 equalTo(interfaceName.getValue())); 223 mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); 224 mMockLooper.dispatchAll(); 225 } 226 227 verifyNoMoreInteractions(mMockNative); 228 } 229 230 /* 231 * Initiator tests 232 */ 233 234 /** 235 * Validate the success flow of the Initiator: using session network specifier with a non-null 236 * token. 237 */ 238 @Test 239 public void testDataPathInitiatorMacTokenSuccess() throws Exception { 240 testDataPathInitiatorUtility(false, true, true, true, false); 241 } 242 243 /** 244 * Validate the fail flow of the Initiator: using session network specifier with a 0 245 * peer ID. 246 */ 247 @Test(expected = IllegalArgumentException.class) 248 public void testDataPathInitiatorNoMacFail() throws Exception { 249 testDataPathInitiatorUtility(false, false, true, true, false); 250 } 251 252 /** 253 * Validate the success flow of the Initiator: using a direct network specifier with a non-null 254 * peer mac and non-null token. 255 */ 256 @Test 257 public void testDataPathInitiatorDirectMacTokenSuccess() throws Exception { 258 testDataPathInitiatorUtility(true, true, true, true, false); 259 } 260 261 /** 262 * Validate the fail flow of the Initiator: using a direct network specifier with a null peer 263 * mac and non-null token. 264 */ 265 @Test(expected = IllegalArgumentException.class) 266 public void testDataPathInitiatorDirectNoMacTokenFail() throws Exception { 267 testDataPathInitiatorUtility(true, false, true, true, false); 268 } 269 270 /** 271 * Validate the fail flow of the Initiator: using a direct network specifier with a null peer 272 * mac and null token. 273 */ 274 @Test(expected = IllegalArgumentException.class) 275 public void testDataPathInitiatorDirectNoMacNoTokenFail() throws Exception { 276 testDataPathInitiatorUtility(true, false, false, true, false); 277 } 278 279 /** 280 * Validate the fail flow of the Initiator: use a session network specifier with a non-null 281 * token, but don't get a confirmation. 282 */ 283 @Test 284 public void testDataPathInitiatorNoConfirmationTimeoutFail() throws Exception { 285 testDataPathInitiatorUtility(false, true, true, false, false); 286 } 287 288 /** 289 * Validate the fail flow of the Initiator: use a session network specifier with a non-null 290 * token, but get an immediate failure 291 */ 292 @Test 293 public void testDataPathInitiatorNoConfirmationHalFail() throws Exception { 294 testDataPathInitiatorUtility(false, true, true, true, true); 295 } 296 297 /** 298 * Validate the fail flow of a mis-configured request: Publisher as Initiator 299 */ 300 @Test 301 public void testDataPathInitiatorOnPublisherError() throws Exception { 302 testDataPathInitiatorResponderMismatchUtility(true); 303 } 304 305 /* 306 * Responder tests 307 */ 308 309 /** 310 * Validate the success flow of the Responder: using session network specifier with a non-null 311 * token. 312 */ 313 @Test 314 public void testDataPathResonderMacTokenSuccess() throws Exception { 315 testDataPathResponderUtility(false, true, true, true); 316 } 317 318 /** 319 * Validate the success flow of the Responder: using session network specifier with a null 320 * token. 321 */ 322 @Test 323 public void testDataPathResonderMacNoTokenSuccess() throws Exception { 324 testDataPathResponderUtility(false, true, false, true); 325 } 326 327 /** 328 * Validate the success flow of the Responder: using session network specifier with a 329 * token and no peer ID (i.e. 0). 330 */ 331 @Test 332 public void testDataPathResonderMacTokenNoPeerIdSuccess() throws Exception { 333 testDataPathResponderUtility(false, false, true, true); 334 } 335 336 /** 337 * Validate the success flow of the Responder: using session network specifier with a null 338 * token and no peer ID (i.e. 0). 339 */ 340 @Test 341 public void testDataPathResonderMacTokenNoPeerIdNoTokenSuccess() throws Exception { 342 testDataPathResponderUtility(false, false, false, true); 343 } 344 345 /** 346 * Validate the success flow of the Responder: using a direct network specifier with a non-null 347 * peer mac and non-null token. 348 */ 349 @Test 350 public void testDataPathResonderDirectMacTokenSuccess() throws Exception { 351 testDataPathResponderUtility(true, true, true, true); 352 } 353 354 /** 355 * Validate the success flow of the Responder: using a direct network specifier with a non-null 356 * peer mac and null token. 357 */ 358 @Test 359 public void testDataPathResonderDirectMacNoTokenSuccess() throws Exception { 360 testDataPathResponderUtility(true, true, false, true); 361 } 362 363 /** 364 * Validate the success flow of the Responder: using a direct network specifier with a null peer 365 * mac and non-null token. 366 */ 367 @Test 368 public void testDataPathResonderDirectNoMacTokenSuccess() throws Exception { 369 testDataPathResponderUtility(true, false, true, true); 370 } 371 372 /** 373 * Validate the success flow of the Responder: using a direct network specifier with a null peer 374 * mac and null token. 375 */ 376 @Test 377 public void testDataPathResonderDirectNoMacNoTokenSuccess() throws Exception { 378 testDataPathResponderUtility(true, false, false, true); 379 } 380 381 /** 382 * Validate the fail flow of the Responder: use a session network specifier with a non-null 383 * token, but don't get a confirmation. 384 */ 385 @Test 386 public void testDataPathResponderNoConfirmationTimeoutFail() throws Exception { 387 testDataPathResponderUtility(false, true, true, false); 388 } 389 390 /** 391 * Validate the fail flow of a mis-configured request: Subscriber as Responder 392 */ 393 @Test 394 public void testDataPathResponderOnSubscriberError() throws Exception { 395 testDataPathInitiatorResponderMismatchUtility(false); 396 } 397 398 /* 399 * Utilities 400 */ 401 402 private void testDataPathInitiatorResponderMismatchUtility(boolean doPublish) throws Exception { 403 final int clientId = 123; 404 final int pubSubId = 11234; 405 final int ndpId = 2; 406 final byte[] pmk = "some bytes".getBytes(); 407 final PeerHandle peerHandle = new PeerHandle(1341234); 408 final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); 409 410 InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); 411 412 // (0) initialize 413 Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle, 414 peerDiscoveryMac, inOrder, doPublish); 415 416 // (1) request network 417 NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, pmk, 418 doPublish); 419 420 // corrupt the network specifier: reverse the role (so it's mis-matched) 421 WifiAwareNetworkSpecifier ns = 422 (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier(); 423 ns = new WifiAwareNetworkSpecifier( 424 ns.type, 425 1 - ns.role, // corruption hack 426 ns.clientId, 427 ns.sessionId, 428 ns.peerId, 429 ns.peerMac, 430 ns.pmk, 431 ns.passphrase 432 ); 433 nr.networkCapabilities.setNetworkSpecifier(ns); 434 435 Message reqNetworkMsg = Message.obtain(); 436 reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK; 437 reqNetworkMsg.obj = nr; 438 reqNetworkMsg.arg1 = 0; 439 res.second.send(reqNetworkMsg); 440 mMockLooper.dispatchAll(); 441 442 // consequences of failure: 443 // Responder (publisher): responds with a rejection to any data-path requests 444 // Initiator (subscribe): doesn't initiate (i.e. no HAL requests) 445 if (doPublish) { 446 // (2) get request & respond 447 mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId); 448 mMockLooper.dispatchAll(); 449 inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false), 450 eq(ndpId), eq(""), eq(null), eq(null), any()); 451 } 452 453 verifyNoMoreInteractions(mMockNative, mMockCm); 454 } 455 456 private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac, 457 boolean providePmk, boolean getConfirmation, boolean immediateHalFailure) 458 throws Exception { 459 final int clientId = 123; 460 final int pubSubId = 11234; 461 final PeerHandle peerHandle = new PeerHandle(1341234); 462 final int ndpId = 2; 463 final byte[] pmk = "some bytes".getBytes(); 464 final String peerToken = "let's go!"; 465 final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); 466 final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); 467 468 ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); 469 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 470 InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); 471 472 if (immediateHalFailure) { 473 when(mMockNative.initiateDataPath(anyShort(), anyInt(), anyInt(), anyInt(), any(), 474 any(), any(), any(), any())).thenReturn(false); 475 476 } 477 478 // (0) initialize 479 Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle, 480 peerDiscoveryMac, inOrder, false); 481 482 // (1) request network 483 NetworkRequest nr; 484 if (useDirect) { 485 nr = getDirectNetworkRequest(clientId, 486 WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, 487 provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null); 488 } else { 489 nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null, 490 providePmk ? pmk : null, false); 491 } 492 493 Message reqNetworkMsg = Message.obtain(); 494 reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK; 495 reqNetworkMsg.obj = nr; 496 reqNetworkMsg.arg1 = 0; 497 res.second.send(reqNetworkMsg); 498 mMockLooper.dispatchAll(); 499 inOrder.verify(mMockNative).initiateDataPath(transactionId.capture(), 500 eq(useDirect ? 0 : peerHandle.peerId), 501 eq(REQUEST_CHANNEL_SETUP), eq(2437), eq(peerDiscoveryMac), 502 eq(sAwareInterfacePrefix + "0"), eq(pmk), eq(null), any()); 503 if (immediateHalFailure) { 504 // short-circuit the rest of this test 505 verifyNoMoreInteractions(mMockNative, mMockCm); 506 return; 507 } 508 509 mDut.onInitiateDataPathResponseSuccess(transactionId.getValue(), ndpId); 510 mMockLooper.dispatchAll(); 511 512 // (2) get confirmation OR timeout 513 if (getConfirmation) { 514 mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, 515 peerToken.getBytes()); 516 mMockLooper.dispatchAll(); 517 inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), any(), 518 any(), anyInt(), any()); 519 } else { 520 assertTrue(mAlarmManager.dispatch( 521 WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG)); 522 mMockLooper.dispatchAll(); 523 inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); 524 mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); 525 mMockLooper.dispatchAll(); 526 } 527 528 // (3) end data-path (unless didn't get confirmation) 529 if (getConfirmation) { 530 Message endNetworkReqMsg = Message.obtain(); 531 endNetworkReqMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; 532 endNetworkReqMsg.obj = nr; 533 res.second.send(endNetworkReqMsg); 534 535 Message endNetworkUsageMsg = Message.obtain(); 536 endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; 537 messengerCaptor.getValue().send(endNetworkUsageMsg); 538 539 mMockLooper.dispatchAll(); 540 inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); 541 mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); 542 mMockLooper.dispatchAll(); 543 } 544 545 verifyNoMoreInteractions(mMockNative, mMockCm); 546 } 547 548 private void testDataPathResponderUtility(boolean useDirect, boolean provideMac, 549 boolean providePmk, boolean getConfirmation) throws Exception { 550 final int clientId = 123; 551 final int pubSubId = 11234; 552 final PeerHandle peerHandle = new PeerHandle(1341234); 553 final int ndpId = 2; 554 final byte[] pmk = "some bytes".getBytes(); 555 final String peerToken = "let's go!"; 556 final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false); 557 final byte[] peerDataPathMac = HexEncoding.decode("0A0B0C0D0E0F".toCharArray(), false); 558 559 ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); 560 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 561 InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback); 562 563 // (0) initialize 564 Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle, 565 peerDiscoveryMac, inOrder, true); 566 567 // (1) request network 568 NetworkRequest nr; 569 if (useDirect) { 570 nr = getDirectNetworkRequest(clientId, 571 WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, 572 provideMac ? peerDiscoveryMac : null, providePmk ? pmk : null); 573 } else { 574 nr = getSessionNetworkRequest(clientId, res.first, provideMac ? peerHandle : null, 575 providePmk ? pmk : null, true); 576 } 577 578 Message reqNetworkMsg = Message.obtain(); 579 reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK; 580 reqNetworkMsg.obj = nr; 581 reqNetworkMsg.arg1 = 0; 582 res.second.send(reqNetworkMsg); 583 mMockLooper.dispatchAll(); 584 585 // (2) get request & respond 586 mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId); 587 mMockLooper.dispatchAll(); 588 inOrder.verify(mMockNative).respondToDataPathRequest(transactionId.capture(), eq(true), 589 eq(ndpId), eq(sAwareInterfacePrefix + "0"), eq(providePmk ? pmk : null), eq(null), 590 any()); 591 mDut.onRespondToDataPathSetupRequestResponse(transactionId.getValue(), true, 0); 592 mMockLooper.dispatchAll(); 593 594 // (3) get confirmation OR timeout 595 if (getConfirmation) { 596 mDut.onDataPathConfirmNotification(ndpId, peerDataPathMac, true, 0, 597 peerToken.getBytes()); 598 mMockLooper.dispatchAll(); 599 inOrder.verify(mMockCm).registerNetworkAgent(messengerCaptor.capture(), any(), any(), 600 any(), anyInt(), any()); 601 } else { 602 assertTrue(mAlarmManager.dispatch( 603 WifiAwareStateManager.HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG)); 604 mMockLooper.dispatchAll(); 605 inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); 606 mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); 607 mMockLooper.dispatchAll(); 608 } 609 610 // (4) end data-path (unless didn't get confirmation) 611 if (getConfirmation) { 612 Message endNetworkMsg = Message.obtain(); 613 endNetworkMsg.what = NetworkFactory.CMD_CANCEL_REQUEST; 614 endNetworkMsg.obj = nr; 615 res.second.send(endNetworkMsg); 616 617 Message endNetworkUsageMsg = Message.obtain(); 618 endNetworkUsageMsg.what = AsyncChannel.CMD_CHANNEL_DISCONNECTED; 619 messengerCaptor.getValue().send(endNetworkUsageMsg); 620 621 mMockLooper.dispatchAll(); 622 inOrder.verify(mMockNative).endDataPath(transactionId.capture(), eq(ndpId)); 623 mDut.onEndDataPathResponse(transactionId.getValue(), true, 0); 624 mMockLooper.dispatchAll(); 625 } 626 627 verifyNoMoreInteractions(mMockNative, mMockCm); 628 } 629 630 private void installDataPathStateManagerMocks() throws Exception { 631 Field field = WifiAwareStateManager.class.getDeclaredField("mDataPathMgr"); 632 field.setAccessible(true); 633 Object mDataPathMgr = field.get(mDut); 634 635 field = WifiAwareDataPathStateManager.class.getDeclaredField("mNwService"); 636 field.setAccessible(true); 637 field.set(mDataPathMgr, mMockNwMgt); 638 639 field = WifiAwareDataPathStateManager.class.getDeclaredField("mNiWrapper"); 640 field.setAccessible(true); 641 field.set(mDataPathMgr, mMockNetworkInterface); 642 } 643 644 private NetworkRequest getSessionNetworkRequest(int clientId, int sessionId, 645 PeerHandle peerHandle, byte[] pmk, boolean doPublish) 646 throws Exception { 647 final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService); 648 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 649 final PublishConfig publishConfig = new PublishConfig.Builder().build(); 650 final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 651 652 ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( 653 WifiAwareSession.class); 654 ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor 655 .forClass(IWifiAwareEventCallback.class); 656 ArgumentCaptor<IWifiAwareDiscoverySessionCallback> sessionProxyCallback = ArgumentCaptor 657 .forClass(IWifiAwareDiscoverySessionCallback.class); 658 ArgumentCaptor<DiscoverySession> discoverySession = ArgumentCaptor 659 .forClass(DiscoverySession.class); 660 661 AttachCallback mockCallback = mock(AttachCallback.class); 662 DiscoverySessionCallback mockSessionCallback = mock( 663 DiscoverySessionCallback.class); 664 665 mgr.attach(mMockLooperHandler, configRequest, mockCallback, null); 666 verify(mMockAwareService).connect(any(), any(), 667 clientProxyCallback.capture(), eq(configRequest), eq(false)); 668 clientProxyCallback.getValue().onConnectSuccess(clientId); 669 mMockLooper.dispatchAll(); 670 verify(mockCallback).onAttached(sessionCaptor.capture()); 671 if (doPublish) { 672 sessionCaptor.getValue().publish(publishConfig, mockSessionCallback, 673 mMockLooperHandler); 674 verify(mMockAwareService).publish(eq(clientId), eq(publishConfig), 675 sessionProxyCallback.capture()); 676 } else { 677 sessionCaptor.getValue().subscribe(subscribeConfig, mockSessionCallback, 678 mMockLooperHandler); 679 verify(mMockAwareService).subscribe(eq(clientId), eq(subscribeConfig), 680 sessionProxyCallback.capture()); 681 } 682 sessionProxyCallback.getValue().onSessionStarted(sessionId); 683 mMockLooper.dispatchAll(); 684 if (doPublish) { 685 verify(mockSessionCallback).onPublishStarted( 686 (PublishDiscoverySession) discoverySession.capture()); 687 } else { 688 verify(mockSessionCallback).onSubscribeStarted( 689 (SubscribeDiscoverySession) discoverySession.capture()); 690 } 691 692 NetworkSpecifier ns; 693 if (pmk == null) { 694 ns = discoverySession.getValue().createNetworkSpecifierOpen(peerHandle); 695 } else { 696 ns = discoverySession.getValue().createNetworkSpecifierPmk(peerHandle, pmk); 697 } 698 699 NetworkCapabilities nc = new NetworkCapabilities(); 700 nc.clearAll(); 701 nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); 702 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).addCapability( 703 NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 704 nc.setNetworkSpecifier(ns); 705 nc.setLinkUpstreamBandwidthKbps(1); 706 nc.setLinkDownstreamBandwidthKbps(1); 707 nc.setSignalStrength(1); 708 709 return new NetworkRequest(nc, 0, 0, NetworkRequest.Type.NONE); 710 } 711 712 private NetworkRequest getDirectNetworkRequest(int clientId, int role, byte[] peer, 713 byte[] pmk) throws Exception { 714 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 715 final WifiAwareManager mgr = new WifiAwareManager(mMockContext, mMockAwareService); 716 717 ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass( 718 WifiAwareSession.class); 719 ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor 720 .forClass(IWifiAwareEventCallback.class); 721 722 AttachCallback mockCallback = mock(AttachCallback.class); 723 724 mgr.attach(mMockLooperHandler, configRequest, mockCallback, null); 725 verify(mMockAwareService).connect(any(), any(), 726 clientProxyCallback.capture(), eq(configRequest), eq(false)); 727 clientProxyCallback.getValue().onConnectSuccess(clientId); 728 mMockLooper.dispatchAll(); 729 verify(mockCallback).onAttached(sessionCaptor.capture()); 730 731 NetworkSpecifier ns; 732 if (pmk == null) { 733 ns = sessionCaptor.getValue().createNetworkSpecifierOpen(role, peer); 734 } else { 735 ns = sessionCaptor.getValue().createNetworkSpecifierPmk(role, peer, pmk); 736 } 737 NetworkCapabilities nc = new NetworkCapabilities(); 738 nc.clearAll(); 739 nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); 740 nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).addCapability( 741 NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 742 nc.setNetworkSpecifier(ns); 743 nc.setLinkUpstreamBandwidthKbps(1); 744 nc.setLinkDownstreamBandwidthKbps(1); 745 nc.setSignalStrength(1); 746 747 return new NetworkRequest(nc, 0, 0, NetworkRequest.Type.REQUEST); 748 } 749 750 private Pair<Integer, Messenger> initDataPathEndPoint(int clientId, int pubSubId, 751 PeerHandle peerHandle, byte[] peerDiscoveryMac, InOrder inOrder, 752 boolean doPublish) 753 throws Exception { 754 final int uid = 1000; 755 final int pid = 2000; 756 final String callingPackage = "com.android.somePackage"; 757 final String someMsg = "some arbitrary message from peer"; 758 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 759 final PublishConfig publishConfig = new PublishConfig.Builder().build(); 760 final SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 761 762 Capabilities capabilities = new Capabilities(); 763 capabilities.maxNdiInterfaces = 1; 764 765 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 766 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 767 ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class); 768 ArgumentCaptor<String> strCaptor = ArgumentCaptor.forClass(String.class); 769 770 // (0) start/registrations 771 inOrder.verify(mMockCm).registerNetworkFactory(messengerCaptor.capture(), 772 strCaptor.capture()); 773 collector.checkThat("factory name", "WIFI_AWARE_FACTORY", equalTo(strCaptor.getValue())); 774 775 // (1) get capabilities 776 mDut.queryCapabilities(); 777 mMockLooper.dispatchAll(); 778 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 779 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), capabilities); 780 mMockLooper.dispatchAll(); 781 782 // (2) enable usage (creates interfaces) 783 mDut.enableUsage(); 784 mMockLooper.dispatchAll(); 785 inOrder.verify(mMockNative).createAwareNetworkInterface(transactionId.capture(), 786 strCaptor.capture()); 787 collector.checkThat("interface created -- 0", sAwareInterfacePrefix + 0, 788 equalTo(strCaptor.getValue())); 789 mDut.onCreateDataPathInterfaceResponse(transactionId.getValue(), true, 0); 790 mMockLooper.dispatchAll(); 791 792 // (3) create client & session & rx message 793 mDut.connect(clientId, uid, pid, callingPackage, mMockCallback, configRequest, false); 794 mMockLooper.dispatchAll(); 795 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 796 eq(configRequest), eq(false), eq(true)); 797 mDut.onConfigSuccessResponse(transactionId.getValue()); 798 mMockLooper.dispatchAll(); 799 inOrder.verify(mMockCallback).onConnectSuccess(clientId); 800 if (doPublish) { 801 mDut.publish(clientId, publishConfig, mMockSessionCallback); 802 } else { 803 mDut.subscribe(clientId, subscribeConfig, mMockSessionCallback); 804 } 805 mMockLooper.dispatchAll(); 806 if (doPublish) { 807 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 808 } else { 809 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), 810 eq(subscribeConfig)); 811 } 812 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), doPublish, pubSubId); 813 mMockLooper.dispatchAll(); 814 inOrder.verify(mMockSessionCallback).onSessionStarted(sessionId.capture()); 815 mDut.onMessageReceivedNotification(pubSubId, peerHandle.peerId, peerDiscoveryMac, 816 someMsg.getBytes()); 817 mMockLooper.dispatchAll(); 818 inOrder.verify(mMockSessionCallback).onMessageReceived(peerHandle.peerId, 819 someMsg.getBytes()); 820 821 return new Pair<>(sessionId.getValue(), messengerCaptor.getValue()); 822 } 823} 824