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