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