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.hamcrest.core.IsNull.notNullValue; 21import static org.hamcrest.core.IsNull.nullValue; 22import static org.junit.Assert.assertEquals; 23import static org.junit.Assert.assertTrue; 24import static org.mockito.ArgumentMatchers.any; 25import static org.mockito.ArgumentMatchers.anyBoolean; 26import static org.mockito.ArgumentMatchers.anyInt; 27import static org.mockito.ArgumentMatchers.anyShort; 28import static org.mockito.ArgumentMatchers.eq; 29import static org.mockito.ArgumentMatchers.isNull; 30import static org.mockito.Mockito.inOrder; 31import static org.mockito.Mockito.mock; 32import static org.mockito.Mockito.times; 33import static org.mockito.Mockito.verify; 34import static org.mockito.Mockito.verifyNoMoreInteractions; 35import static org.mockito.Mockito.when; 36 37import android.Manifest; 38import android.app.AppOpsManager; 39import android.app.test.MockAnswerUtil; 40import android.app.test.TestAlarmManager; 41import android.content.Context; 42import android.content.Intent; 43import android.content.pm.PackageManager; 44import android.hardware.wifi.V1_0.NanStatusType; 45import android.net.ConnectivityManager; 46import android.net.wifi.RttManager; 47import android.net.wifi.aware.ConfigRequest; 48import android.net.wifi.aware.IWifiAwareDiscoverySessionCallback; 49import android.net.wifi.aware.IWifiAwareEventCallback; 50import android.net.wifi.aware.PublishConfig; 51import android.net.wifi.aware.SubscribeConfig; 52import android.net.wifi.aware.WifiAwareManager; 53import android.os.Message; 54import android.os.UserHandle; 55import android.os.test.TestLooper; 56import android.test.suitebuilder.annotation.SmallTest; 57import android.util.Log; 58import android.util.SparseArray; 59 60import libcore.util.HexEncoding; 61 62import org.junit.Before; 63import org.junit.Rule; 64import org.junit.Test; 65import org.junit.rules.ErrorCollector; 66import org.mockito.ArgumentCaptor; 67import org.mockito.InOrder; 68import org.mockito.Mock; 69import org.mockito.MockitoAnnotations; 70 71import java.io.PrintWriter; 72import java.io.StringWriter; 73import java.lang.reflect.Field; 74import java.util.HashMap; 75import java.util.HashSet; 76import java.util.LinkedList; 77import java.util.Map; 78import java.util.Random; 79import java.util.Set; 80 81/** 82 * Unit test harness for WifiAwareStateManager. 83 */ 84@SmallTest 85public class WifiAwareStateManagerTest { 86 private TestLooper mMockLooper; 87 private Random mRandomNg = new Random(15687); 88 private WifiAwareStateManager mDut; 89 @Mock private WifiAwareNativeApi mMockNative; 90 @Mock private Context mMockContext; 91 @Mock private AppOpsManager mMockAppOpsManager; 92 @Mock private WifiAwareRttStateManager mMockAwareRttStateManager; 93 TestAlarmManager mAlarmManager; 94 @Mock private WifiAwareDataPathStateManager mMockAwareDataPathStatemanager; 95 96 @Rule 97 public ErrorCollector collector = new ErrorCollector(); 98 99 private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0}; 100 101 /** 102 * Pre-test configuration. Initialize and install mocks. 103 */ 104 @Before 105 public void setUp() throws Exception { 106 MockitoAnnotations.initMocks(this); 107 108 mAlarmManager = new TestAlarmManager(); 109 when(mMockContext.getSystemService(Context.ALARM_SERVICE)) 110 .thenReturn(mAlarmManager.getAlarmManager()); 111 112 when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( 113 mock(ConnectivityManager.class)); 114 when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager); 115 when(mMockContext.checkPermission(eq(android.Manifest.permission.ACCESS_FINE_LOCATION), 116 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); 117 when(mMockContext.checkPermission(eq(Manifest.permission.ACCESS_COARSE_LOCATION), 118 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); 119 when(mMockAppOpsManager.noteOp(eq(AppOpsManager.OP_FINE_LOCATION), anyInt(), 120 any())).thenReturn(AppOpsManager.MODE_ERRORED); 121 when(mMockAppOpsManager.noteOp(eq(AppOpsManager.OP_COARSE_LOCATION), anyInt(), 122 any())).thenReturn(AppOpsManager.MODE_ERRORED); 123 124 mMockLooper = new TestLooper(); 125 126 mDut = new WifiAwareStateManager(); 127 mDut.setNative(mMockNative); 128 mDut.start(mMockContext, mMockLooper.getLooper()); 129 installMocksInStateManager(mDut, mMockAwareRttStateManager, mMockAwareDataPathStatemanager); 130 131 when(mMockNative.enableAndConfigure(anyShort(), any(), anyBoolean(), 132 anyBoolean())).thenReturn(true); 133 when(mMockNative.disable(anyShort())).thenReturn(true); 134 when(mMockNative.publish(anyShort(), anyInt(), any())).thenReturn(true); 135 when(mMockNative.subscribe(anyShort(), anyInt(), any())) 136 .thenReturn(true); 137 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 138 any(), anyInt())).thenReturn(true); 139 when(mMockNative.stopPublish(anyShort(), anyInt())).thenReturn(true); 140 when(mMockNative.stopSubscribe(anyShort(), anyInt())).thenReturn(true); 141 when(mMockNative.getCapabilities(anyShort())).thenReturn(true); 142 } 143 144 /** 145 * Validate that Aware data-path interfaces are brought up and down correctly. 146 */ 147 @Test 148 public void testAwareDataPathInterfaceUpDown() throws Exception { 149 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 150 InOrder inOrder = inOrder(mMockContext, mMockNative, mMockAwareDataPathStatemanager); 151 152 // (1) enable usage 153 mDut.enableUsage(); 154 mMockLooper.dispatchAll(); 155 validateCorrectAwareStatusChangeBroadcast(inOrder, true); 156 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 157 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 158 mMockLooper.dispatchAll(); 159 inOrder.verify(mMockAwareDataPathStatemanager).createAllInterfaces(); 160 collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); 161 162 // (2) disable usage 163 mDut.disableUsage(); 164 mMockLooper.dispatchAll(); 165 inOrder.verify(mMockAwareDataPathStatemanager).onAwareDownCleanupDataPaths(); 166 inOrder.verify(mMockNative).disable((short) 0); 167 validateCorrectAwareStatusChangeBroadcast(inOrder, false); 168 inOrder.verify(mMockAwareDataPathStatemanager).deleteAllInterfaces(); 169 collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); 170 171 verifyNoMoreInteractions(mMockNative, mMockAwareDataPathStatemanager); 172 } 173 174 /** 175 * Validate that APIs aren't functional when usage is disabled. 176 */ 177 @Test 178 public void testDisableUsageDisablesApis() throws Exception { 179 final int clientId = 12314; 180 final int uid = 1000; 181 final int pid = 2000; 182 final String callingPackage = "com.google.somePackage"; 183 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 184 185 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 186 InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); 187 188 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 189 190 // (1) check initial state 191 mDut.enableUsage(); 192 mMockLooper.dispatchAll(); 193 validateCorrectAwareStatusChangeBroadcast(inOrder, true); 194 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 195 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 196 mMockLooper.dispatchAll(); 197 collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); 198 199 // (2) disable usage and validate state 200 mDut.disableUsage(); 201 mMockLooper.dispatchAll(); 202 collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); 203 inOrder.verify(mMockNative).disable((short) 0); 204 validateCorrectAwareStatusChangeBroadcast(inOrder, false); 205 206 // (3) try connecting and validate that get nothing (app should be aware of non-availability 207 // through state change broadcast and/or query API) 208 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 209 mMockLooper.dispatchAll(); 210 211 verifyNoMoreInteractions(mMockNative, mockCallback); 212 } 213 214 /** 215 * Validate that when API usage is disabled while in the middle of a connection that internal 216 * state is cleaned-up, and that all subsequent operations are NOP. Then enable usage again and 217 * validate that operates correctly. 218 */ 219 @Test 220 public void testDisableUsageFlow() throws Exception { 221 final int clientId = 12341; 222 final int uid = 1000; 223 final int pid = 2000; 224 final String callingPackage = "com.google.somePackage"; 225 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 226 227 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 228 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 229 InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); 230 231 // (1) check initial state 232 mDut.enableUsage(); 233 mMockLooper.dispatchAll(); 234 validateCorrectAwareStatusChangeBroadcast(inOrder, true); 235 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 236 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 237 mMockLooper.dispatchAll(); 238 239 collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); 240 241 // (2) connect (successfully) 242 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 243 mMockLooper.dispatchAll(); 244 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 245 eq(false), eq(true)); 246 mDut.onConfigSuccessResponse(transactionId.getValue()); 247 mMockLooper.dispatchAll(); 248 inOrder.verify(mockCallback).onConnectSuccess(clientId); 249 250 // (3) disable usage & verify callbacks 251 mDut.disableUsage(); 252 mMockLooper.dispatchAll(); 253 collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); 254 inOrder.verify(mMockNative).disable((short) 0); 255 validateCorrectAwareStatusChangeBroadcast(inOrder, false); 256 validateInternalClientInfoCleanedUp(clientId); 257 258 // (4) try connecting again and validate that just get an onAwareDown 259 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 260 mMockLooper.dispatchAll(); 261 262 // (5) disable usage again and validate that not much happens 263 mDut.disableUsage(); 264 mMockLooper.dispatchAll(); 265 collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); 266 267 // (6) enable usage 268 mDut.enableUsage(); 269 mMockLooper.dispatchAll(); 270 collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); 271 validateCorrectAwareStatusChangeBroadcast(inOrder, true); 272 273 // (7) connect (should be successful) 274 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 275 mMockLooper.dispatchAll(); 276 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 277 eq(false), eq(true)); 278 mDut.onConfigSuccessResponse(transactionId.getValue()); 279 mMockLooper.dispatchAll(); 280 inOrder.verify(mockCallback).onConnectSuccess(clientId); 281 282 verifyNoMoreInteractions(mMockNative, mockCallback); 283 } 284 285 /** 286 * Validates that a HAL failure on enable and configure results in failed callback. 287 */ 288 @Test 289 public void testHalFailureEnableAndConfigure() throws Exception { 290 final int clientId = 12341; 291 final int uid = 1000; 292 final int pid = 2000; 293 final String callingPackage = "com.google.somePackage"; 294 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 295 296 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 297 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 298 InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback); 299 300 when(mMockNative.enableAndConfigure(anyShort(), any(), anyBoolean(), 301 anyBoolean())).thenReturn(false); 302 303 // (1) check initial state 304 mDut.enableUsage(); 305 mMockLooper.dispatchAll(); 306 validateCorrectAwareStatusChangeBroadcast(inOrder, true); 307 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 308 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 309 mMockLooper.dispatchAll(); 310 311 // (2) connect with HAL failure 312 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 313 mMockLooper.dispatchAll(); 314 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 315 eq(false), eq(true)); 316 inOrder.verify(mockCallback).onConnectFail(NanStatusType.INTERNAL_FAILURE); 317 318 validateInternalClientInfoCleanedUp(clientId); 319 verifyNoMoreInteractions(mMockNative, mockCallback); 320 } 321 322 /** 323 * Validates that all events are delivered with correct arguments. Validates 324 * that IdentityChanged not delivered if configuration disables delivery. 325 */ 326 @Test 327 public void testAwareEventsDelivery() throws Exception { 328 final int clientId1 = 1005; 329 final int clientId2 = 1007; 330 final int clusterLow = 5; 331 final int clusterHigh = 100; 332 final int masterPref = 111; 333 final int uid = 1000; 334 final int pid = 2000; 335 final String callingPackage = "com.google.somePackage"; 336 final int reason = NanStatusType.INTERNAL_FAILURE; 337 final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); 338 final byte[] someMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); 339 340 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 341 .setClusterHigh(clusterHigh).setMasterPreference(masterPref) 342 .build(); 343 344 IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); 345 IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); 346 ArgumentCaptor<Short> transactionIdCapture = ArgumentCaptor.forClass(Short.class); 347 InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative); 348 349 mDut.enableUsage(); 350 mMockLooper.dispatchAll(); 351 inOrder.verify(mMockNative).getCapabilities(transactionIdCapture.capture()); 352 mDut.onCapabilitiesUpdateResponse(transactionIdCapture.getValue(), getCapabilities()); 353 mMockLooper.dispatchAll(); 354 355 // (1) connect 1st and 2nd clients 356 mDut.connect(clientId1, uid, pid, callingPackage, mockCallback1, configRequest, false); 357 mMockLooper.dispatchAll(); 358 inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(), 359 eq(configRequest), eq(false), eq(true)); 360 short transactionId = transactionIdCapture.getValue(); 361 mDut.onConfigSuccessResponse(transactionId); 362 mMockLooper.dispatchAll(); 363 inOrder.verify(mockCallback1).onConnectSuccess(clientId1); 364 365 mDut.connect(clientId2, uid, pid, callingPackage, mockCallback2, configRequest, true); 366 mMockLooper.dispatchAll(); 367 inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(), 368 eq(configRequest), eq(true), eq(false)); 369 transactionId = transactionIdCapture.getValue(); 370 mDut.onConfigSuccessResponse(transactionId); 371 mMockLooper.dispatchAll(); 372 inOrder.verify(mockCallback2).onConnectSuccess(clientId2); 373 374 // (2) deliver Aware events - without LOCATIONING permission 375 mDut.onClusterChangeNotification(WifiAwareClientState.CLUSTER_CHANGE_EVENT_STARTED, 376 someMac); 377 mDut.onInterfaceAddressChangeNotification(someMac); 378 mMockLooper.dispatchAll(); 379 380 inOrder.verify(mockCallback2).onIdentityChanged(ALL_ZERO_MAC); 381 382 // (3) deliver new identity - still without LOCATIONING permission (should get an event) 383 mDut.onInterfaceAddressChangeNotification(someMac2); 384 mMockLooper.dispatchAll(); 385 386 inOrder.verify(mockCallback2).onIdentityChanged(ALL_ZERO_MAC); 387 388 // (4) deliver same identity - still without LOCATIONING permission (should 389 // not get an event) 390 mDut.onInterfaceAddressChangeNotification(someMac2); 391 mMockLooper.dispatchAll(); 392 393 // (5) deliver new identity - with LOCATIONING permission 394 when(mMockContext.checkPermission(eq(Manifest.permission.ACCESS_COARSE_LOCATION), 395 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 396 when(mMockAppOpsManager.noteOp(eq(AppOpsManager.OP_COARSE_LOCATION), anyInt(), 397 any())).thenReturn(AppOpsManager.MODE_ALLOWED); 398 mDut.onInterfaceAddressChangeNotification(someMac); 399 mMockLooper.dispatchAll(); 400 401 inOrder.verify(mockCallback2).onIdentityChanged(someMac); 402 403 // (6) Aware down (no feedback) 404 mDut.onAwareDownNotification(reason); 405 mMockLooper.dispatchAll(); 406 407 validateInternalClientInfoCleanedUp(clientId1); 408 validateInternalClientInfoCleanedUp(clientId2); 409 410 verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); 411 } 412 413 /** 414 * Validate that when the HAL doesn't respond we get a TIMEOUT (which 415 * results in a failure response) at which point we can process additional 416 * commands. Steps: (1) connect, (2) publish - timeout, (3) publish + 417 * success. 418 */ 419 @Test 420 public void testHalNoResponseTimeout() throws Exception { 421 final int clientId = 12341; 422 final int uid = 1000; 423 final int pid = 2000; 424 final String callingPackage = "com.google.somePackage"; 425 final ConfigRequest configRequest = new ConfigRequest.Builder().build(); 426 final PublishConfig publishConfig = new PublishConfig.Builder().build(); 427 428 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 429 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 430 IWifiAwareDiscoverySessionCallback.class); 431 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 432 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 433 434 mDut.enableUsage(); 435 mMockLooper.dispatchAll(); 436 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 437 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 438 mMockLooper.dispatchAll(); 439 440 // (1) connect (successfully) 441 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 442 mMockLooper.dispatchAll(); 443 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 444 eq(false), eq(true)); 445 mDut.onConfigSuccessResponse(transactionId.getValue()); 446 mMockLooper.dispatchAll(); 447 inOrder.verify(mockCallback).onConnectSuccess(clientId); 448 449 // (2) publish + timeout 450 mDut.publish(clientId, publishConfig, mockSessionCallback); 451 mMockLooper.dispatchAll(); 452 inOrder.verify(mMockNative).publish(anyShort(), eq(0), eq(publishConfig)); 453 assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_COMMAND_TIMEOUT_TAG)); 454 mMockLooper.dispatchAll(); 455 inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 456 validateInternalNoSessions(clientId); 457 458 // (3) publish + success 459 mDut.publish(clientId, publishConfig, mockSessionCallback); 460 mMockLooper.dispatchAll(); 461 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 462 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, 9999); 463 mMockLooper.dispatchAll(); 464 inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); 465 466 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 467 } 468 469 /** 470 * Validates publish flow: (1) initial publish (2) fail informed by notification, (3) fail due 471 * to immediate HAL failure. Expected: get a failure callback. 472 */ 473 @Test 474 public void testPublishFail() throws Exception { 475 final int clientId = 1005; 476 final int uid = 1000; 477 final int pid = 2000; 478 final String callingPackage = "com.google.somePackage"; 479 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 480 481 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 482 PublishConfig publishConfig = new PublishConfig.Builder().build(); 483 484 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 485 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 486 IWifiAwareDiscoverySessionCallback.class); 487 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 488 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 489 490 mDut.enableUsage(); 491 mMockLooper.dispatchAll(); 492 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 493 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 494 mMockLooper.dispatchAll(); 495 496 // (0) connect 497 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 498 mMockLooper.dispatchAll(); 499 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 500 eq(configRequest), eq(false), eq(true)); 501 mDut.onConfigSuccessResponse(transactionId.getValue()); 502 mMockLooper.dispatchAll(); 503 inOrder.verify(mockCallback).onConnectSuccess(clientId); 504 505 // (1) initial publish 506 mDut.publish(clientId, publishConfig, mockSessionCallback); 507 mMockLooper.dispatchAll(); 508 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 509 510 // (2) publish failure callback (i.e. firmware tried and failed) 511 mDut.onSessionConfigFailResponse(transactionId.getValue(), true, reasonFail); 512 mMockLooper.dispatchAll(); 513 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 514 validateInternalNoSessions(clientId); 515 516 // (3) publish and get immediate failure (i.e. HAL failed) 517 when(mMockNative.publish(anyShort(), anyInt(), any())).thenReturn(false); 518 519 mDut.publish(clientId, publishConfig, mockSessionCallback); 520 mMockLooper.dispatchAll(); 521 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 522 523 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 524 validateInternalNoSessions(clientId); 525 526 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 527 } 528 529 /** 530 * Validates the publish flow: (1) initial publish (2) success (3) 531 * termination (e.g. DONE) (4) update session attempt (5) terminateSession 532 * (6) update session attempt. Expected: session ID callback + session 533 * cleaned-up. 534 */ 535 @Test 536 public void testPublishSuccessTerminated() throws Exception { 537 final int clientId = 2005; 538 final int uid = 1000; 539 final int pid = 2000; 540 final String callingPackage = "com.google.somePackage"; 541 final int reasonTerminate = NanStatusType.SUCCESS; 542 final int publishId = 15; 543 544 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 545 PublishConfig publishConfig = new PublishConfig.Builder().build(); 546 547 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 548 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 549 IWifiAwareDiscoverySessionCallback.class); 550 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 551 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 552 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 553 554 mDut.enableUsage(); 555 mMockLooper.dispatchAll(); 556 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 557 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 558 mMockLooper.dispatchAll(); 559 560 // (0) connect 561 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 562 mMockLooper.dispatchAll(); 563 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 564 eq(configRequest), eq(false), eq(true)); 565 mDut.onConfigSuccessResponse(transactionId.getValue()); 566 mMockLooper.dispatchAll(); 567 inOrder.verify(mockCallback).onConnectSuccess(clientId); 568 569 // (1) initial publish 570 mDut.publish(clientId, publishConfig, mockSessionCallback); 571 mMockLooper.dispatchAll(); 572 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 573 574 // (2) publish success 575 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 576 mMockLooper.dispatchAll(); 577 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 578 579 // (3) publish termination (from firmware - not app!) 580 mDut.onSessionTerminatedNotification(publishId, reasonTerminate, true); 581 mMockLooper.dispatchAll(); 582 inOrder.verify(mockSessionCallback).onSessionTerminated(reasonTerminate); 583 584 // (4) app update session (race condition: app didn't get termination 585 // yet) 586 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 587 mMockLooper.dispatchAll(); 588 589 // (5) app terminates session 590 mDut.terminateSession(clientId, sessionId.getValue()); 591 mMockLooper.dispatchAll(); 592 593 // (6) app updates session (app already knows that terminated - will get 594 // a local FAIL). 595 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 596 mMockLooper.dispatchAll(); 597 598 validateInternalSessionInfoCleanedUp(clientId, sessionId.getValue()); 599 600 verifyNoMoreInteractions(mockSessionCallback, mMockNative); 601 } 602 603 /** 604 * Validate the publish flow: (1) initial publish + (2) success + (3) update + (4) update 605 * fails (callback from firmware) + (5) update + (6). Expected: session is still alive after 606 * update failure so second update succeeds (no callbacks) + (7) update + immediate failure from 607 * HAL. 608 */ 609 @Test 610 public void testPublishUpdateFail() throws Exception { 611 final int clientId = 2005; 612 final int uid = 1000; 613 final int pid = 2000; 614 final String callingPackage = "com.google.somePackage"; 615 final int publishId = 15; 616 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 617 618 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 619 PublishConfig publishConfig = new PublishConfig.Builder().build(); 620 621 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 622 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 623 IWifiAwareDiscoverySessionCallback.class); 624 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 625 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 626 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 627 628 mDut.enableUsage(); 629 mMockLooper.dispatchAll(); 630 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 631 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 632 mMockLooper.dispatchAll(); 633 634 // (0) connect 635 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 636 mMockLooper.dispatchAll(); 637 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 638 eq(false), eq(true)); 639 mDut.onConfigSuccessResponse(transactionId.getValue()); 640 mMockLooper.dispatchAll(); 641 inOrder.verify(mockCallback).onConnectSuccess(clientId); 642 643 // (1) initial publish 644 mDut.publish(clientId, publishConfig, mockSessionCallback); 645 mMockLooper.dispatchAll(); 646 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 647 648 // (2) publish success 649 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 650 mMockLooper.dispatchAll(); 651 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 652 653 // (3) update publish 654 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 655 mMockLooper.dispatchAll(); 656 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), 657 eq(publishConfig)); 658 659 // (4) update fails 660 mDut.onSessionConfigFailResponse(transactionId.getValue(), true, reasonFail); 661 mMockLooper.dispatchAll(); 662 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 663 664 // (5) another update publish 665 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 666 mMockLooper.dispatchAll(); 667 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), 668 eq(publishConfig)); 669 670 // (6) update succeeds 671 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 672 mMockLooper.dispatchAll(); 673 inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); 674 675 // (7) another update + immediate failure 676 when(mMockNative.publish(anyShort(), anyInt(), any())).thenReturn(false); 677 678 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 679 mMockLooper.dispatchAll(); 680 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId), 681 eq(publishConfig)); 682 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 683 684 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 685 } 686 687 /** 688 * Validate race condition: publish pending but session terminated (due to 689 * disconnect - can't terminate such a session directly from app). Need to 690 * make sure that once publish succeeds (failure isn't a problem) the 691 * session is immediately terminated since no-one is listening for it. 692 */ 693 @Test 694 public void testDisconnectWhilePublishPending() throws Exception { 695 final int clientId = 2005; 696 final int uid = 1000; 697 final int pid = 2000; 698 final String callingPackage = "com.google.somePackage"; 699 final int publishId = 15; 700 701 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 702 PublishConfig publishConfig = new PublishConfig.Builder().build(); 703 704 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 705 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 706 IWifiAwareDiscoverySessionCallback.class); 707 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 708 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 709 710 mDut.enableUsage(); 711 mMockLooper.dispatchAll(); 712 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 713 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 714 mMockLooper.dispatchAll(); 715 716 // (0) connect 717 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 718 mMockLooper.dispatchAll(); 719 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 720 eq(false), eq(true)); 721 mDut.onConfigSuccessResponse(transactionId.getValue()); 722 mMockLooper.dispatchAll(); 723 inOrder.verify(mockCallback).onConnectSuccess(clientId); 724 725 // (1) initial publish 726 mDut.publish(clientId, publishConfig, mockSessionCallback); 727 mMockLooper.dispatchAll(); 728 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 729 730 // (2) disconnect (but doesn't get executed until get response for 731 // publish command) 732 mDut.disconnect(clientId); 733 mMockLooper.dispatchAll(); 734 735 // (3) publish success 736 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 737 mMockLooper.dispatchAll(); 738 inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); 739 inOrder.verify(mMockNative).stopPublish(transactionId.capture(), eq(publishId)); 740 inOrder.verify(mMockNative).disable((short) 0); 741 742 validateInternalClientInfoCleanedUp(clientId); 743 744 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 745 } 746 747 /** 748 * Validates subscribe flow: (1) initial subscribe (2) fail (callback from firmware), (3) fail 749 * due to immeidate HAL failure. Expected: get a failure callback. 750 */ 751 @Test 752 public void testSubscribeFail() throws Exception { 753 final int clientId = 1005; 754 final int uid = 1000; 755 final int pid = 2000; 756 final String callingPackage = "com.google.somePackage"; 757 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 758 759 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 760 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 761 762 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 763 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 764 IWifiAwareDiscoverySessionCallback.class); 765 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 766 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 767 768 mDut.enableUsage(); 769 mMockLooper.dispatchAll(); 770 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 771 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 772 mMockLooper.dispatchAll(); 773 774 // (0) connect 775 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 776 mMockLooper.dispatchAll(); 777 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 778 eq(false), eq(true)); 779 mDut.onConfigSuccessResponse(transactionId.getValue()); 780 mMockLooper.dispatchAll(); 781 inOrder.verify(mockCallback).onConnectSuccess(clientId); 782 783 // (1) initial subscribe 784 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 785 mMockLooper.dispatchAll(); 786 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 787 788 // (2) subscribe failure 789 mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); 790 mMockLooper.dispatchAll(); 791 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 792 validateInternalNoSessions(clientId); 793 794 // (3) subscribe and get immediate failure (i.e. HAL failed) 795 when(mMockNative.subscribe(anyShort(), anyInt(), any())) 796 .thenReturn(false); 797 798 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 799 mMockLooper.dispatchAll(); 800 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 801 802 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 803 validateInternalNoSessions(clientId); 804 805 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 806 } 807 808 /** 809 * Validates the subscribe flow: (1) initial subscribe (2) success (3) 810 * termination (e.g. DONE) (4) update session attempt (5) terminateSession 811 * (6) update session attempt. Expected: session ID callback + session 812 * cleaned-up 813 */ 814 @Test 815 public void testSubscribeSuccessTerminated() throws Exception { 816 final int clientId = 2005; 817 final int uid = 1000; 818 final int pid = 2000; 819 final String callingPackage = "com.google.somePackage"; 820 final int reasonTerminate = NanStatusType.SUCCESS; 821 final int subscribeId = 15; 822 823 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 824 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 825 826 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 827 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 828 IWifiAwareDiscoverySessionCallback.class); 829 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 830 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 831 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 832 833 mDut.enableUsage(); 834 mMockLooper.dispatchAll(); 835 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 836 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 837 mMockLooper.dispatchAll(); 838 839 // (0) connect 840 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 841 mMockLooper.dispatchAll(); 842 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 843 eq(false), eq(true)); 844 mDut.onConfigSuccessResponse(transactionId.getValue()); 845 mMockLooper.dispatchAll(); 846 inOrder.verify(mockCallback).onConnectSuccess(clientId); 847 848 // (1) initial subscribe 849 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 850 mMockLooper.dispatchAll(); 851 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 852 853 // (2) subscribe success 854 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 855 mMockLooper.dispatchAll(); 856 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 857 858 // (3) subscribe termination (from firmware - not app!) 859 mDut.onSessionTerminatedNotification(subscribeId, reasonTerminate, false); 860 mMockLooper.dispatchAll(); 861 inOrder.verify(mockSessionCallback).onSessionTerminated(reasonTerminate); 862 863 // (4) app update session (race condition: app didn't get termination 864 // yet) 865 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 866 mMockLooper.dispatchAll(); 867 868 // (5) app terminates session 869 mDut.terminateSession(clientId, sessionId.getValue()); 870 mMockLooper.dispatchAll(); 871 872 // (6) app updates session 873 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 874 mMockLooper.dispatchAll(); 875 876 validateInternalSessionInfoCleanedUp(clientId, sessionId.getValue()); 877 878 verifyNoMoreInteractions(mockSessionCallback, mMockNative); 879 } 880 881 /** 882 * Validate the subscribe flow: (1) initial subscribe + (2) success + (3) update + (4) update 883 * fails (callback from firmware) + (5) update + (6). Expected: session is still alive after 884 * update failure so second update succeeds (no callbacks). + (7) update + immediate failure 885 * from HAL. 886 */ 887 @Test 888 public void testSubscribeUpdateFail() throws Exception { 889 final int clientId = 2005; 890 final int uid = 1000; 891 final int pid = 2000; 892 final String callingPackage = "com.google.somePackage"; 893 final int subscribeId = 15; 894 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 895 896 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 897 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 898 899 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 900 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 901 IWifiAwareDiscoverySessionCallback.class); 902 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 903 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 904 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 905 906 mDut.enableUsage(); 907 mMockLooper.dispatchAll(); 908 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 909 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 910 mMockLooper.dispatchAll(); 911 912 // (0) connect 913 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 914 mMockLooper.dispatchAll(); 915 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 916 eq(false), eq(true)); 917 mDut.onConfigSuccessResponse(transactionId.getValue()); 918 mMockLooper.dispatchAll(); 919 inOrder.verify(mockCallback).onConnectSuccess(clientId); 920 921 // (1) initial subscribe 922 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 923 mMockLooper.dispatchAll(); 924 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 925 926 // (2) subscribe success 927 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 928 mMockLooper.dispatchAll(); 929 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 930 931 // (3) update subscribe 932 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 933 mMockLooper.dispatchAll(); 934 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), 935 eq(subscribeConfig)); 936 937 // (4) update fails 938 mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); 939 mMockLooper.dispatchAll(); 940 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 941 942 // (5) another update subscribe 943 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 944 mMockLooper.dispatchAll(); 945 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), 946 eq(subscribeConfig)); 947 948 // (6) update succeeds 949 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 950 mMockLooper.dispatchAll(); 951 inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); 952 953 // (7) another update + immediate failure 954 when(mMockNative.subscribe(anyShort(), anyInt(), any())) 955 .thenReturn(false); 956 957 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 958 mMockLooper.dispatchAll(); 959 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), 960 eq(subscribeConfig)); 961 inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); 962 963 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 964 } 965 966 /** 967 * Validate race condition: subscribe pending but session terminated (due to 968 * disconnect - can't terminate such a session directly from app). Need to 969 * make sure that once subscribe succeeds (failure isn't a problem) the 970 * session is immediately terminated since no-one is listening for it. 971 */ 972 @Test 973 public void testDisconnectWhileSubscribePending() throws Exception { 974 final int clientId = 2005; 975 final int uid = 1000; 976 final int pid = 2000; 977 final String callingPackage = "com.google.somePackage"; 978 final int subscribeId = 15; 979 980 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 981 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 982 983 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 984 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 985 IWifiAwareDiscoverySessionCallback.class); 986 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 987 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 988 989 mDut.enableUsage(); 990 mMockLooper.dispatchAll(); 991 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 992 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 993 mMockLooper.dispatchAll(); 994 995 // (0) connect 996 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 997 mMockLooper.dispatchAll(); 998 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 999 eq(false), eq(true)); 1000 mDut.onConfigSuccessResponse(transactionId.getValue()); 1001 mMockLooper.dispatchAll(); 1002 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1003 1004 // (1) initial subscribe 1005 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1006 mMockLooper.dispatchAll(); 1007 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1008 1009 // (2) disconnect (but doesn't get executed until get response for 1010 // subscribe command) 1011 mDut.disconnect(clientId); 1012 mMockLooper.dispatchAll(); 1013 1014 // (3) subscribe success 1015 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1016 mMockLooper.dispatchAll(); 1017 inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); 1018 inOrder.verify(mMockNative).stopSubscribe((short) 0, subscribeId); 1019 inOrder.verify(mMockNative).disable((short) 0); 1020 1021 validateInternalClientInfoCleanedUp(clientId); 1022 1023 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1024 } 1025 1026 /** 1027 * Validate (1) subscribe (success), (2) match (i.e. discovery), (3) message reception, 1028 * (4) message transmission failed (after ok queuing), (5) message transmission success. 1029 */ 1030 @Test 1031 public void testMatchAndMessages() throws Exception { 1032 final int clientId = 1005; 1033 final int uid = 1000; 1034 final int pid = 2000; 1035 final String callingPackage = "com.google.somePackage"; 1036 final String serviceName = "some-service-name"; 1037 final String ssi = "some much longer and more arbitrary data"; 1038 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 1039 final int subscribeId = 15; 1040 final int requestorId = 22; 1041 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1042 final String peerSsi = "some peer ssi data"; 1043 final String peerMatchFilter = "filter binary array represented as string"; 1044 final String peerMsg = "some message from peer"; 1045 final int messageId = 6948; 1046 final int messageId2 = 6949; 1047 1048 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1049 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1050 .setServiceSpecificInfo(ssi.getBytes()) 1051 .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) 1052 .build(); 1053 1054 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1055 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1056 IWifiAwareDiscoverySessionCallback.class); 1057 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1058 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1059 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1060 1061 mDut.enableUsage(); 1062 mMockLooper.dispatchAll(); 1063 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1064 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1065 mMockLooper.dispatchAll(); 1066 1067 // (0) connect 1068 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1069 mMockLooper.dispatchAll(); 1070 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1071 eq(configRequest), eq(false), eq(true)); 1072 mDut.onConfigSuccessResponse(transactionId.getValue()); 1073 mMockLooper.dispatchAll(); 1074 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1075 1076 // (1) subscribe 1077 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1078 mMockLooper.dispatchAll(); 1079 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1080 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1081 mMockLooper.dispatchAll(); 1082 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1083 1084 // (2) match 1085 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1086 peerMatchFilter.getBytes()); 1087 mMockLooper.dispatchAll(); 1088 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1089 peerMatchFilter.getBytes()); 1090 1091 // (3) message Rx 1092 mDut.onMessageReceivedNotification(subscribeId, requestorId, peerMac, peerMsg.getBytes()); 1093 mMockLooper.dispatchAll(); 1094 inOrder.verify(mockSessionCallback).onMessageReceived(requestorId, peerMsg.getBytes()); 1095 1096 // (4) message Tx successful queuing 1097 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId, 0); 1098 mMockLooper.dispatchAll(); 1099 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1100 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1101 short tid1 = transactionId.getValue(); 1102 mDut.onMessageSendQueuedSuccessResponse(tid1); 1103 mMockLooper.dispatchAll(); 1104 1105 // (5) message Tx successful queuing 1106 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId2, 1107 0); 1108 mMockLooper.dispatchAll(); 1109 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1110 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId2)); 1111 short tid2 = transactionId.getValue(); 1112 mDut.onMessageSendQueuedSuccessResponse(tid2); 1113 mMockLooper.dispatchAll(); 1114 1115 // (4) and (5) final Tx results (on-air results) 1116 mDut.onMessageSendFailNotification(tid1, reasonFail); 1117 mDut.onMessageSendSuccessNotification(tid2); 1118 mMockLooper.dispatchAll(); 1119 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, reasonFail); 1120 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId2); 1121 validateInternalSendMessageQueuesCleanedUp(messageId); 1122 validateInternalSendMessageQueuesCleanedUp(messageId2); 1123 1124 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1125 } 1126 1127 /** 1128 * Summary: in a single publish session interact with multiple peers 1129 * (different MAC addresses). 1130 */ 1131 @Test 1132 public void testMultipleMessageSources() throws Exception { 1133 final int clientId = 300; 1134 final int uid = 1000; 1135 final int pid = 2000; 1136 final String callingPackage = "com.google.somePackage"; 1137 final int clusterLow = 7; 1138 final int clusterHigh = 7; 1139 final int masterPref = 0; 1140 final String serviceName = "some-service-name"; 1141 final int publishId = 88; 1142 final int peerId1 = 568; 1143 final int peerId2 = 873; 1144 final byte[] peerMac1 = HexEncoding.decode("000102030405".toCharArray(), false); 1145 final byte[] peerMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); 1146 final String msgFromPeer1 = "hey from 000102..."; 1147 final String msgFromPeer2 = "hey from 0607..."; 1148 final String msgToPeer1 = "hey there 000102..."; 1149 final String msgToPeer2 = "hey there 0506..."; 1150 final int msgToPeerId1 = 546; 1151 final int msgToPeerId2 = 9654; 1152 final int reason = NanStatusType.INTERNAL_FAILURE; 1153 1154 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 1155 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 1156 1157 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) 1158 .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 1159 1160 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1161 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1162 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1163 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1164 IWifiAwareDiscoverySessionCallback.class); 1165 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 1166 1167 mDut.enableUsage(); 1168 mMockLooper.dispatchAll(); 1169 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1170 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1171 mMockLooper.dispatchAll(); 1172 1173 // (1) connect 1174 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1175 mMockLooper.dispatchAll(); 1176 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1177 eq(false), eq(true)); 1178 mDut.onConfigSuccessResponse(transactionId.getValue()); 1179 mMockLooper.dispatchAll(); 1180 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1181 1182 // (2) publish 1183 mDut.publish(clientId, publishConfig, mockSessionCallback); 1184 mMockLooper.dispatchAll(); 1185 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 1186 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 1187 mMockLooper.dispatchAll(); 1188 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1189 1190 // (3) message received from peers 1 & 2 1191 mDut.onMessageReceivedNotification(publishId, peerId1, peerMac1, msgFromPeer1.getBytes()); 1192 mDut.onMessageReceivedNotification(publishId, peerId2, peerMac2, msgFromPeer2.getBytes()); 1193 mMockLooper.dispatchAll(); 1194 inOrder.verify(mockSessionCallback).onMessageReceived(peerId1, msgFromPeer1.getBytes()); 1195 inOrder.verify(mockSessionCallback).onMessageReceived(peerId2, msgFromPeer2.getBytes()); 1196 1197 // (4) sending messages back to same peers: one Tx fails, other succeeds 1198 mDut.sendMessage(clientId, sessionId.getValue(), peerId2, msgToPeer2.getBytes(), 1199 msgToPeerId2, 0); 1200 mMockLooper.dispatchAll(); 1201 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId2), 1202 eq(peerMac2), eq(msgToPeer2.getBytes()), eq(msgToPeerId2)); 1203 short transactionIdVal = transactionId.getValue(); 1204 mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); 1205 mDut.onMessageSendSuccessNotification(transactionIdVal); 1206 1207 mDut.sendMessage(clientId, sessionId.getValue(), peerId1, msgToPeer1.getBytes(), 1208 msgToPeerId1, 0); 1209 mMockLooper.dispatchAll(); 1210 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); 1211 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId1), 1212 eq(peerMac1), eq(msgToPeer1.getBytes()), eq(msgToPeerId1)); 1213 transactionIdVal = transactionId.getValue(); 1214 mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); 1215 mDut.onMessageSendFailNotification(transactionIdVal, reason); 1216 mMockLooper.dispatchAll(); 1217 inOrder.verify(mockSessionCallback).onMessageSendFail(msgToPeerId1, reason); 1218 validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); 1219 validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); 1220 1221 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 1222 } 1223 1224 /** 1225 * Summary: interact with a peer which changed its identity (MAC address) 1226 * but which keeps its requestor instance ID. Should be transparent. 1227 */ 1228 @Test 1229 public void testMessageWhilePeerChangesIdentity() throws Exception { 1230 final int clientId = 300; 1231 final int uid = 1000; 1232 final int pid = 2000; 1233 final String callingPackage = "com.google.somePackage"; 1234 final int clusterLow = 7; 1235 final int clusterHigh = 7; 1236 final int masterPref = 0; 1237 final String serviceName = "some-service-name"; 1238 final int publishId = 88; 1239 final int peerId = 568; 1240 final byte[] peerMacOrig = HexEncoding.decode("000102030405".toCharArray(), false); 1241 final byte[] peerMacLater = HexEncoding.decode("060708090A0B".toCharArray(), false); 1242 final String msgFromPeer1 = "hey from 000102..."; 1243 final String msgFromPeer2 = "hey from 0607..."; 1244 final String msgToPeer1 = "hey there 000102..."; 1245 final String msgToPeer2 = "hey there 0506..."; 1246 final int msgToPeerId1 = 546; 1247 final int msgToPeerId2 = 9654; 1248 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 1249 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 1250 1251 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) 1252 .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 1253 1254 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1255 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1256 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1257 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1258 IWifiAwareDiscoverySessionCallback.class); 1259 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 1260 1261 mDut.enableUsage(); 1262 mMockLooper.dispatchAll(); 1263 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1264 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1265 mMockLooper.dispatchAll(); 1266 1267 // (1) connect 1268 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1269 mMockLooper.dispatchAll(); 1270 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1271 eq(false), eq(true)); 1272 mDut.onConfigSuccessResponse(transactionId.getValue()); 1273 mMockLooper.dispatchAll(); 1274 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1275 1276 // (2) publish 1277 mDut.publish(clientId, publishConfig, mockSessionCallback); 1278 mMockLooper.dispatchAll(); 1279 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 1280 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 1281 mMockLooper.dispatchAll(); 1282 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1283 1284 // (3) message received & responded to 1285 mDut.onMessageReceivedNotification(publishId, peerId, peerMacOrig, msgFromPeer1.getBytes()); 1286 mDut.sendMessage(clientId, sessionId.getValue(), peerId, msgToPeer1.getBytes(), 1287 msgToPeerId1, 0); 1288 mMockLooper.dispatchAll(); 1289 inOrder.verify(mockSessionCallback).onMessageReceived(peerId, msgFromPeer1.getBytes()); 1290 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 1291 eq(peerMacOrig), eq(msgToPeer1.getBytes()), eq(msgToPeerId1)); 1292 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1293 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1294 mMockLooper.dispatchAll(); 1295 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId1); 1296 validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); 1297 1298 // (4) message received with same peer ID but different MAC 1299 mDut.onMessageReceivedNotification(publishId, peerId, peerMacLater, 1300 msgFromPeer2.getBytes()); 1301 mDut.sendMessage(clientId, sessionId.getValue(), peerId, msgToPeer2.getBytes(), 1302 msgToPeerId2, 0); 1303 mMockLooper.dispatchAll(); 1304 inOrder.verify(mockSessionCallback).onMessageReceived(peerId, msgFromPeer2.getBytes()); 1305 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 1306 eq(peerMacLater), eq(msgToPeer2.getBytes()), eq(msgToPeerId2)); 1307 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1308 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1309 mMockLooper.dispatchAll(); 1310 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); 1311 validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); 1312 1313 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 1314 } 1315 1316 /** 1317 * Validate that get failure (with correct code) when trying to send a 1318 * message to an invalid peer ID. 1319 */ 1320 @Test 1321 public void testSendMessageToInvalidPeerId() throws Exception { 1322 final int clientId = 1005; 1323 final int uid = 1000; 1324 final int pid = 2000; 1325 final String callingPackage = "com.google.somePackage"; 1326 final String ssi = "some much longer and more arbitrary data"; 1327 final int subscribeId = 15; 1328 final int requestorId = 22; 1329 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1330 final String peerSsi = "some peer ssi data"; 1331 final String peerMatchFilter = "filter binary array represented as string"; 1332 final int messageId = 6948; 1333 1334 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1335 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1336 1337 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1338 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1339 IWifiAwareDiscoverySessionCallback.class); 1340 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1341 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1342 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1343 1344 mDut.enableUsage(); 1345 mMockLooper.dispatchAll(); 1346 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1347 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1348 mMockLooper.dispatchAll(); 1349 1350 // (1) connect 1351 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1352 mMockLooper.dispatchAll(); 1353 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1354 eq(false), eq(true)); 1355 mDut.onConfigSuccessResponse(transactionId.getValue()); 1356 mMockLooper.dispatchAll(); 1357 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1358 1359 // (2) subscribe & match 1360 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1361 mMockLooper.dispatchAll(); 1362 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1363 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1364 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1365 peerMatchFilter.getBytes()); 1366 mMockLooper.dispatchAll(); 1367 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1368 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1369 peerMatchFilter.getBytes()); 1370 1371 // (3) send message to invalid peer ID 1372 mDut.sendMessage(clientId, sessionId.getValue(), requestorId + 5, ssi.getBytes(), 1373 messageId, 0); 1374 mMockLooper.dispatchAll(); 1375 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1376 NanStatusType.INTERNAL_FAILURE); 1377 validateInternalSendMessageQueuesCleanedUp(messageId); 1378 1379 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1380 } 1381 1382 /** 1383 * Validate that on send message errors are handled correctly: immediate send error, queue fail 1384 * error (not queue full), and timeout. Behavior: correct callback is dispatched and a later 1385 * firmware notification is ignored. Intersperse with one successfull transmission. 1386 */ 1387 @Test 1388 public void testSendMessageErrorsImmediateQueueTimeout() throws Exception { 1389 final int clientId = 1005; 1390 final int uid = 1000; 1391 final int pid = 2000; 1392 final String callingPackage = "com.google.somePackage"; 1393 final String ssi = "some much longer and more arbitrary data"; 1394 final int subscribeId = 15; 1395 final int requestorId = 22; 1396 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1397 final String peerSsi = "some peer ssi data"; 1398 final String peerMatchFilter = "filter binary array represented as string"; 1399 final int messageId = 6948; 1400 1401 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1402 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1403 1404 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1405 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1406 IWifiAwareDiscoverySessionCallback.class); 1407 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1408 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1409 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1410 1411 mDut.enableUsage(); 1412 mMockLooper.dispatchAll(); 1413 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1414 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1415 mMockLooper.dispatchAll(); 1416 1417 // (1) connect 1418 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1419 mMockLooper.dispatchAll(); 1420 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1421 eq(false), eq(true)); 1422 mDut.onConfigSuccessResponse(transactionId.getValue()); 1423 mMockLooper.dispatchAll(); 1424 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1425 1426 // (2) subscribe & match 1427 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1428 mMockLooper.dispatchAll(); 1429 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1430 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1431 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1432 peerMatchFilter.getBytes()); 1433 mMockLooper.dispatchAll(); 1434 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1435 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1436 peerMatchFilter.getBytes()); 1437 1438 // (3) send 2 messages and enqueue successfully 1439 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1440 messageId, 0); 1441 mMockLooper.dispatchAll(); 1442 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1443 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1444 short transactionId1 = transactionId.getValue(); 1445 mDut.onMessageSendQueuedSuccessResponse(transactionId1); 1446 mMockLooper.dispatchAll(); 1447 1448 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1449 messageId + 1, 0); 1450 mMockLooper.dispatchAll(); 1451 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1452 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 1)); 1453 short transactionId2 = transactionId.getValue(); 1454 mDut.onMessageSendQueuedSuccessResponse(transactionId2); 1455 mMockLooper.dispatchAll(); 1456 1457 // (4) send a message and get a queueing failure (not queue full) 1458 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 2, 1459 0); 1460 mMockLooper.dispatchAll(); 1461 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1462 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2)); 1463 short transactionId3 = transactionId.getValue(); 1464 mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusType.INTERNAL_FAILURE); 1465 mMockLooper.dispatchAll(); 1466 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 2, 1467 NanStatusType.INTERNAL_FAILURE); 1468 validateInternalSendMessageQueuesCleanedUp(messageId + 2); 1469 1470 // (5) send a message and get an immediate failure (configure first) 1471 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1472 any(), anyInt())).thenReturn(false); 1473 1474 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 3, 1475 0); 1476 mMockLooper.dispatchAll(); 1477 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1478 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3)); 1479 short transactionId4 = transactionId.getValue(); 1480 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 3, 1481 NanStatusType.INTERNAL_FAILURE); 1482 validateInternalSendMessageQueuesCleanedUp(messageId + 3); 1483 1484 // (6) message send timeout 1485 assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_SEND_MESSAGE_TIMEOUT_TAG)); 1486 mMockLooper.dispatchAll(); 1487 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1488 NanStatusType.INTERNAL_FAILURE); 1489 validateInternalSendMessageQueuesCleanedUp(messageId); 1490 1491 // (7) firmware response (unlikely - but good to check) 1492 mDut.onMessageSendSuccessNotification(transactionId1); 1493 mDut.onMessageSendSuccessNotification(transactionId2); 1494 1495 // bogus: these didn't even go to firmware or weren't queued 1496 mDut.onMessageSendSuccessNotification(transactionId3); 1497 mDut.onMessageSendFailNotification(transactionId4, NanStatusType.INTERNAL_FAILURE); 1498 mMockLooper.dispatchAll(); 1499 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId + 1); 1500 1501 validateInternalSendMessageQueuesCleanedUp(messageId + 1); 1502 1503 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1504 } 1505 1506 /** 1507 * Validate that when sending a message with a retry count the message is retried the specified 1508 * number of times. Scenario ending with success. 1509 */ 1510 @Test 1511 public void testSendMessageRetransmitSuccess() throws Exception { 1512 final int clientId = 1005; 1513 final int uid = 1000; 1514 final int pid = 2000; 1515 final String callingPackage = "com.google.somePackage"; 1516 final String ssi = "some much longer and more arbitrary data"; 1517 final int subscribeId = 15; 1518 final int requestorId = 22; 1519 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1520 final String peerSsi = "some peer ssi data"; 1521 final String peerMatchFilter = "filter binary array represented as string"; 1522 final int messageId = 6948; 1523 final int retryCount = 3; 1524 1525 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1526 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1527 1528 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1529 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1530 IWifiAwareDiscoverySessionCallback.class); 1531 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1532 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1533 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1534 1535 mDut.enableUsage(); 1536 mMockLooper.dispatchAll(); 1537 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1538 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1539 mMockLooper.dispatchAll(); 1540 1541 // (1) connect 1542 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1543 mMockLooper.dispatchAll(); 1544 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1545 eq(false), eq(true)); 1546 mDut.onConfigSuccessResponse(transactionId.getValue()); 1547 mMockLooper.dispatchAll(); 1548 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1549 1550 // (2) subscribe & match 1551 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1552 mMockLooper.dispatchAll(); 1553 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1554 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1555 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1556 peerMatchFilter.getBytes()); 1557 mMockLooper.dispatchAll(); 1558 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1559 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1560 peerMatchFilter.getBytes()); 1561 1562 // (3) send message and enqueue successfully 1563 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1564 messageId, retryCount); 1565 mMockLooper.dispatchAll(); 1566 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1567 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1568 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1569 mMockLooper.dispatchAll(); 1570 1571 // (4) loop and fail until reach retryCount 1572 for (int i = 0; i < retryCount; ++i) { 1573 mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); 1574 mMockLooper.dispatchAll(); 1575 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1576 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1577 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1578 mMockLooper.dispatchAll(); 1579 } 1580 1581 // (5) succeed on last retry 1582 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1583 mMockLooper.dispatchAll(); 1584 1585 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1586 validateInternalSendMessageQueuesCleanedUp(messageId); 1587 1588 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1589 } 1590 1591 /** 1592 * Validate that when sending a message with a retry count the message is retried the specified 1593 * number of times. Scenario ending with failure. 1594 */ 1595 @Test 1596 public void testSendMessageRetransmitFail() throws Exception { 1597 final int clientId = 1005; 1598 final int uid = 1000; 1599 final int pid = 2000; 1600 final String callingPackage = "com.google.somePackage"; 1601 final String ssi = "some much longer and more arbitrary data"; 1602 final int subscribeId = 15; 1603 final int requestorId = 22; 1604 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1605 final String peerSsi = "some peer ssi data"; 1606 final String peerMatchFilter = "filter binary array represented as string"; 1607 final int messageId = 6948; 1608 final int retryCount = 3; 1609 1610 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1611 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1612 1613 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1614 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1615 IWifiAwareDiscoverySessionCallback.class); 1616 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1617 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1618 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1619 1620 mDut.enableUsage(); 1621 mMockLooper.dispatchAll(); 1622 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1623 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1624 mMockLooper.dispatchAll(); 1625 1626 // (1) connect 1627 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1628 mMockLooper.dispatchAll(); 1629 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1630 eq(false), eq(true)); 1631 mDut.onConfigSuccessResponse(transactionId.getValue()); 1632 mMockLooper.dispatchAll(); 1633 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1634 1635 // (2) subscribe & match 1636 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1637 mMockLooper.dispatchAll(); 1638 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1639 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1640 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1641 peerMatchFilter.getBytes()); 1642 mMockLooper.dispatchAll(); 1643 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1644 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1645 peerMatchFilter.getBytes()); 1646 1647 // (3) send message and enqueue successfully 1648 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId, 1649 retryCount); 1650 mMockLooper.dispatchAll(); 1651 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1652 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1653 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1654 mMockLooper.dispatchAll(); 1655 1656 // (4) loop and fail until reach retryCount+1 1657 for (int i = 0; i < retryCount + 1; ++i) { 1658 mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); 1659 mMockLooper.dispatchAll(); 1660 1661 if (i != retryCount) { 1662 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1663 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1664 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1665 mMockLooper.dispatchAll(); 1666 } 1667 } 1668 1669 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1670 NanStatusType.NO_OTA_ACK); 1671 validateInternalSendMessageQueuesCleanedUp(messageId); 1672 1673 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1674 } 1675 1676 /** 1677 * Validate that the host-side message queue functions. Tests the perfect case of queue always 1678 * succeeds and all messages are received on first attempt. 1679 */ 1680 @Test 1681 public void testSendMessageQueueSequence() throws Exception { 1682 final int clientId = 1005; 1683 final int uid = 1000; 1684 final int pid = 2000; 1685 final String callingPackage = "com.google.somePackage"; 1686 final String serviceName = "some-service-name"; 1687 final int subscribeId = 15; 1688 final int requestorId = 22; 1689 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1690 final int messageIdBase = 6948; 1691 final int numberOfMessages = 30; 1692 final int queueDepth = 6; 1693 1694 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1695 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1696 .build(); 1697 1698 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1699 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1700 IWifiAwareDiscoverySessionCallback.class); 1701 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1702 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1703 ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class); 1704 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1705 1706 mDut.enableUsage(); 1707 mMockLooper.dispatchAll(); 1708 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1709 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1710 mMockLooper.dispatchAll(); 1711 1712 // (0) connect 1713 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1714 mMockLooper.dispatchAll(); 1715 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1716 eq(configRequest), eq(false), eq(true)); 1717 mDut.onConfigSuccessResponse(transactionId.getValue()); 1718 mMockLooper.dispatchAll(); 1719 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1720 1721 // (1) subscribe 1722 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1723 mMockLooper.dispatchAll(); 1724 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1725 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1726 mMockLooper.dispatchAll(); 1727 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1728 1729 // (2) match 1730 mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null); 1731 mMockLooper.dispatchAll(); 1732 inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null); 1733 1734 // (3) transmit messages 1735 SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, 1736 null, null, null); 1737 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1738 any(), anyInt())).thenAnswer(answerObj); 1739 1740 int remainingMessages = numberOfMessages; 1741 for (int i = 0; i < numberOfMessages; ++i) { 1742 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i, 1743 0); 1744 mMockLooper.dispatchAll(); 1745 // at 1/2 interval have the system simulate transmitting a queued message over-the-air 1746 if (i % 2 == 1) { 1747 assertTrue(answerObj.process()); 1748 remainingMessages--; 1749 mMockLooper.dispatchAll(); 1750 } 1751 } 1752 for (int i = 0; i < remainingMessages; ++i) { 1753 assertTrue(answerObj.process()); 1754 mMockLooper.dispatchAll(); 1755 } 1756 assertEquals("queue empty", 0, answerObj.queueSize()); 1757 1758 inOrder.verify(mockSessionCallback, times(numberOfMessages)).onMessageSendSuccess( 1759 messageIdCaptor.capture()); 1760 for (int i = 0; i < numberOfMessages; ++i) { 1761 assertEquals("message ID: " + i, (long) messageIdBase + i, 1762 (long) messageIdCaptor.getAllValues().get(i)); 1763 } 1764 1765 verifyNoMoreInteractions(mockCallback, mockSessionCallback); 1766 } 1767 1768 /** 1769 * Validate that the host-side message queue functions. A combination of imperfect conditions: 1770 * - Failure to queue: synchronous firmware error 1771 * - Failure to queue: asyncronous firmware error 1772 * - Failure to transmit: OTA (which will be retried) 1773 * - Failure to transmit: other 1774 */ 1775 @Test 1776 public void testSendMessageQueueSequenceImperfect() throws Exception { 1777 final int clientId = 1005; 1778 final int uid = 1000; 1779 final int pid = 2000; 1780 final String callingPackage = "com.google.somePackage"; 1781 final String serviceName = "some-service-name"; 1782 final int subscribeId = 15; 1783 final int requestorId = 22; 1784 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1785 final int messageIdBase = 6948; 1786 final int numberOfMessages = 300; 1787 final int queueDepth = 6; 1788 final int retransmitCount = 3; // not the maximum 1789 1790 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1791 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1792 .build(); 1793 1794 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1795 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1796 IWifiAwareDiscoverySessionCallback.class); 1797 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1798 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1799 ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class); 1800 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1801 1802 mDut.enableUsage(); 1803 mMockLooper.dispatchAll(); 1804 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1805 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1806 mMockLooper.dispatchAll(); 1807 1808 // (0) connect 1809 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1810 mMockLooper.dispatchAll(); 1811 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1812 eq(configRequest), eq(false), eq(true)); 1813 mDut.onConfigSuccessResponse(transactionId.getValue()); 1814 mMockLooper.dispatchAll(); 1815 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1816 1817 // (1) subscribe 1818 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1819 mMockLooper.dispatchAll(); 1820 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1821 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1822 mMockLooper.dispatchAll(); 1823 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1824 1825 // (2) match 1826 mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null); 1827 mMockLooper.dispatchAll(); 1828 inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null); 1829 1830 // (3) transmit messages: configure a mix of failures/success 1831 Set<Integer> failQueueCommandImmediately = new HashSet<>(); 1832 Set<Integer> failQueueCommandLater = new HashSet<>(); 1833 Map<Integer, Integer> numberOfRetries = new HashMap<>(); 1834 1835 int numOfSuccesses = 0; 1836 int numOfFailuresInternalFailure = 0; 1837 int numOfFailuresNoOta = 0; 1838 for (int i = 0; i < numberOfMessages; ++i) { 1839 // random results: 1840 // - 0-50: success 1841 // - 51-60: retransmit value (which will fail for >5) 1842 // - 61-70: fail queue later 1843 // - 71-80: fail queue immediately 1844 // - 81-90: fail retransmit with non-OTA failure 1845 int random = mRandomNg.nextInt(90); 1846 if (random <= 50) { 1847 numberOfRetries.put(messageIdBase + i, 0); 1848 numOfSuccesses++; 1849 } else if (random <= 60) { 1850 numberOfRetries.put(messageIdBase + i, random - 51); 1851 if (random - 51 > retransmitCount) { 1852 numOfFailuresNoOta++; 1853 } else { 1854 numOfSuccesses++; 1855 } 1856 } else if (random <= 70) { 1857 failQueueCommandLater.add(messageIdBase + i); 1858 numOfFailuresInternalFailure++; 1859 } else if (random <= 80) { 1860 failQueueCommandImmediately.add(messageIdBase + i); 1861 numOfFailuresInternalFailure++; 1862 } else { 1863 numberOfRetries.put(messageIdBase + i, -1); 1864 numOfFailuresInternalFailure++; 1865 } 1866 } 1867 1868 Log.v("WifiAwareStateManagerTest", 1869 "failQueueCommandImmediately=" + failQueueCommandImmediately 1870 + ", failQueueCommandLater=" + failQueueCommandLater + ", numberOfRetries=" 1871 + numberOfRetries + ", numOfSuccesses=" + numOfSuccesses 1872 + ", numOfFailuresInternalFailure=" + numOfFailuresInternalFailure 1873 + ", numOfFailuresNoOta=" + numOfFailuresNoOta); 1874 1875 SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, 1876 failQueueCommandImmediately, failQueueCommandLater, numberOfRetries); 1877 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1878 any(), anyInt())).thenAnswer(answerObj); 1879 1880 for (int i = 0; i < numberOfMessages; ++i) { 1881 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i, 1882 retransmitCount); 1883 mMockLooper.dispatchAll(); 1884 } 1885 1886 while (answerObj.queueSize() != 0) { 1887 assertTrue(answerObj.process()); 1888 mMockLooper.dispatchAll(); 1889 } 1890 1891 verify(mockSessionCallback, times(numOfSuccesses)).onMessageSendSuccess(anyInt()); 1892 verify(mockSessionCallback, times(numOfFailuresInternalFailure)).onMessageSendFail(anyInt(), 1893 eq(NanStatusType.INTERNAL_FAILURE)); 1894 verify(mockSessionCallback, times(numOfFailuresNoOta)).onMessageSendFail(anyInt(), 1895 eq(NanStatusType.NO_OTA_ACK)); 1896 1897 verifyNoMoreInteractions(mockCallback, mockSessionCallback); 1898 } 1899 1900 /** 1901 * Validate that can send empty message successfully: null, byte[0], "" 1902 */ 1903 @Test 1904 public void testSendEmptyMessages() throws Exception { 1905 final int clientId = 1005; 1906 final int uid = 1000; 1907 final int pid = 2000; 1908 final String callingPackage = "com.google.somePackage"; 1909 final String serviceName = "some-service-name"; 1910 final String ssi = "some much longer and more arbitrary data"; 1911 final int subscribeId = 15; 1912 final int requestorId = 22; 1913 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1914 final String peerSsi = "some peer ssi data"; 1915 final String peerMatchFilter = "filter binary array represented as string"; 1916 final int messageId = 6948; 1917 1918 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1919 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1920 .setServiceSpecificInfo(ssi.getBytes()) 1921 .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) 1922 .build(); 1923 1924 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1925 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1926 IWifiAwareDiscoverySessionCallback.class); 1927 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1928 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1929 ArgumentCaptor<byte[]> byteArrayCaptor = ArgumentCaptor.forClass(byte[].class); 1930 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1931 1932 mDut.enableUsage(); 1933 mMockLooper.dispatchAll(); 1934 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1935 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1936 mMockLooper.dispatchAll(); 1937 1938 // (0) connect 1939 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1940 mMockLooper.dispatchAll(); 1941 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1942 eq(configRequest), eq(false), eq(true)); 1943 mDut.onConfigSuccessResponse(transactionId.getValue()); 1944 mMockLooper.dispatchAll(); 1945 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1946 1947 // (1) subscribe 1948 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1949 mMockLooper.dispatchAll(); 1950 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1951 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1952 mMockLooper.dispatchAll(); 1953 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1954 1955 // (2) match 1956 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1957 peerMatchFilter.getBytes()); 1958 mMockLooper.dispatchAll(); 1959 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1960 peerMatchFilter.getBytes()); 1961 1962 // (3) message null Tx successful queuing 1963 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageId, 0); 1964 mMockLooper.dispatchAll(); 1965 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1966 eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId)); 1967 short tid = transactionId.getValue(); 1968 mDut.onMessageSendQueuedSuccessResponse(tid); 1969 mMockLooper.dispatchAll(); 1970 1971 // (4) final Tx results (on-air results) 1972 mDut.onMessageSendSuccessNotification(tid); 1973 mMockLooper.dispatchAll(); 1974 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1975 validateInternalSendMessageQueuesCleanedUp(messageId); 1976 1977 // (5) message byte[0] Tx successful queuing 1978 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, new byte[0], messageId, 0); 1979 mMockLooper.dispatchAll(); 1980 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1981 eq(requestorId), eq(peerMac), eq(new byte[0]), eq(messageId)); 1982 tid = transactionId.getValue(); 1983 mDut.onMessageSendQueuedSuccessResponse(tid); 1984 mMockLooper.dispatchAll(); 1985 1986 // (6) final Tx results (on-air results) 1987 mDut.onMessageSendSuccessNotification(tid); 1988 mMockLooper.dispatchAll(); 1989 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1990 validateInternalSendMessageQueuesCleanedUp(messageId); 1991 1992 // (7) message "" Tx successful queuing 1993 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, "".getBytes(), messageId, 0); 1994 mMockLooper.dispatchAll(); 1995 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1996 eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId)); 1997 collector.checkThat("Empty message contents", "", 1998 equalTo(new String(byteArrayCaptor.getValue()))); 1999 tid = transactionId.getValue(); 2000 mDut.onMessageSendQueuedSuccessResponse(tid); 2001 mMockLooper.dispatchAll(); 2002 2003 // (8) final Tx results (on-air results) 2004 mDut.onMessageSendSuccessNotification(tid); 2005 mMockLooper.dispatchAll(); 2006 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 2007 validateInternalSendMessageQueuesCleanedUp(messageId); 2008 2009 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 2010 } 2011 2012 private class SendMessageQueueModelAnswer extends MockAnswerUtil.AnswerWithArguments { 2013 private final int mMaxQueueDepth; 2014 2015 // keyed by message ID 2016 private final Set<Integer> mFailQueueCommandImmediately; // return a false 2017 private final Set<Integer> mFailQueueCommandLater; // return an error != TX_QUEUE_FULL 2018 2019 // # of times to return NO_OTA_ACK before returning SUCCESS. So a 0 means success on first 2020 // try, a very large number means - never succeed (since max retry is 5). 2021 // a -1 impiles a non-OTA failure: on first attempt 2022 private final Map<Integer, Integer> mRetryLimit; 2023 2024 private final LinkedList<Short> mQueue = new LinkedList<>(); // transaction ID (tid) 2025 private final Map<Short, Integer> mMessageIdsByTid = new HashMap<>(); // tid -> message ID 2026 private final Map<Integer, Integer> mTriesUsedByMid = new HashMap<>(); // mid -> # of retx 2027 2028 SendMessageQueueModelAnswer(int maxQueueDepth, Set<Integer> failQueueCommandImmediately, 2029 Set<Integer> failQueueCommandLater, Map<Integer, Integer> numberOfRetries) { 2030 mMaxQueueDepth = maxQueueDepth; 2031 mFailQueueCommandImmediately = failQueueCommandImmediately; 2032 mFailQueueCommandLater = failQueueCommandLater; 2033 mRetryLimit = numberOfRetries; 2034 2035 if (mRetryLimit != null) { 2036 for (int mid : mRetryLimit.keySet()) { 2037 mTriesUsedByMid.put(mid, 0); 2038 } 2039 } 2040 } 2041 2042 public boolean answer(short transactionId, int pubSubId, int requestorInstanceId, 2043 byte[] dest, byte[] message, int messageId) throws Exception { 2044 if (mFailQueueCommandImmediately != null && mFailQueueCommandImmediately.contains( 2045 messageId)) { 2046 return false; 2047 } 2048 2049 if (mFailQueueCommandLater != null && mFailQueueCommandLater.contains(messageId)) { 2050 mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusType.INTERNAL_FAILURE); 2051 } else { 2052 if (mQueue.size() <= mMaxQueueDepth) { 2053 mQueue.addLast(transactionId); 2054 mMessageIdsByTid.put(transactionId, messageId); 2055 mDut.onMessageSendQueuedSuccessResponse(transactionId); 2056 } else { 2057 mDut.onMessageSendQueuedFailResponse(transactionId, 2058 NanStatusType.FOLLOWUP_TX_QUEUE_FULL); 2059 } 2060 } 2061 2062 return true; 2063 } 2064 2065 /** 2066 * Processes the first message in the queue: i.e. responds as if sent over-the-air 2067 * (successfully or failed) 2068 */ 2069 boolean process() { 2070 if (mQueue.size() == 0) { 2071 return false; 2072 } 2073 short tid = mQueue.poll(); 2074 int mid = mMessageIdsByTid.get(tid); 2075 2076 if (mRetryLimit != null && mRetryLimit.containsKey(mid)) { 2077 int numRetries = mRetryLimit.get(mid); 2078 if (numRetries == -1) { 2079 mDut.onMessageSendFailNotification(tid, NanStatusType.INTERNAL_FAILURE); 2080 } else { 2081 int currentRetries = mTriesUsedByMid.get(mid); 2082 if (currentRetries > numRetries) { 2083 return false; // shouldn't be retrying!? 2084 } else if (currentRetries == numRetries) { 2085 mDut.onMessageSendSuccessNotification(tid); 2086 } else { 2087 mDut.onMessageSendFailNotification(tid, NanStatusType.NO_OTA_ACK); 2088 } 2089 mTriesUsedByMid.put(mid, currentRetries + 1); 2090 } 2091 } else { 2092 mDut.onMessageSendSuccessNotification(tid); 2093 } 2094 2095 return true; 2096 } 2097 2098 /** 2099 * Returns the number of elements in the queue. 2100 */ 2101 int queueSize() { 2102 return mQueue.size(); 2103 } 2104 } 2105 2106 /** 2107 * Validate that start ranging function fills-in correct MAC addresses for peer IDs and 2108 * passed along to RTT module. 2109 */ 2110 @Test 2111 public void testStartRanging() throws Exception { 2112 final int clientId = 1005; 2113 final int uid = 1000; 2114 final int pid = 2000; 2115 final String callingPackage = "com.google.somePackage"; 2116 final int subscribeId = 15; 2117 final int requestorId = 22; 2118 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 2119 final String peerSsi = "some peer ssi data"; 2120 final String peerMatchFilter = "filter binary array represented as string"; 2121 final int rangingId = 18423; 2122 final RttManager.RttParams[] params = new RttManager.RttParams[2]; 2123 params[0] = new RttManager.RttParams(); 2124 params[0].bssid = Integer.toString(requestorId); 2125 params[1] = new RttManager.RttParams(); 2126 params[1].bssid = Integer.toString(requestorId + 5); 2127 2128 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2129 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2130 2131 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2132 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2133 IWifiAwareDiscoverySessionCallback.class); 2134 2135 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2136 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2137 ArgumentCaptor<WifiAwareClientState> clientCaptor = 2138 ArgumentCaptor.forClass(WifiAwareClientState.class); 2139 ArgumentCaptor<RttManager.RttParams[]> rttParamsCaptor = 2140 ArgumentCaptor.forClass(RttManager.RttParams[].class); 2141 2142 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative, 2143 mMockAwareRttStateManager); 2144 2145 mDut.enableUsage(); 2146 mMockLooper.dispatchAll(); 2147 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2148 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2149 mMockLooper.dispatchAll(); 2150 2151 // (1) connect 2152 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2153 mMockLooper.dispatchAll(); 2154 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2155 eq(false), eq(true)); 2156 mDut.onConfigSuccessResponse(transactionId.getValue()); 2157 mMockLooper.dispatchAll(); 2158 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2159 2160 // (2) subscribe & match 2161 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 2162 mMockLooper.dispatchAll(); 2163 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 2164 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 2165 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 2166 peerMatchFilter.getBytes()); 2167 mMockLooper.dispatchAll(); 2168 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2169 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 2170 peerMatchFilter.getBytes()); 2171 2172 // (3) start ranging: pass along a valid peer ID and an invalid one 2173 mDut.startRanging(clientId, sessionId.getValue(), params, rangingId); 2174 mMockLooper.dispatchAll(); 2175 inOrder.verify(mMockAwareRttStateManager).startRanging(eq(rangingId), 2176 clientCaptor.capture(), rttParamsCaptor.capture()); 2177 collector.checkThat("RttParams[0].bssid", "06:07:08:09:0A:0B", 2178 equalTo(rttParamsCaptor.getValue()[0].bssid)); 2179 collector.checkThat("RttParams[1].bssid", "", equalTo(rttParamsCaptor.getValue()[1].bssid)); 2180 2181 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, 2182 mMockAwareRttStateManager); 2183 } 2184 2185 /** 2186 * Test sequence of configuration: (1) config1, (2) config2 - incompatible, 2187 * (3) config3 - compatible with config1 (requiring upgrade), (4) disconnect 2188 * config3 (should get a downgrade), (5) disconnect config1 (should get a 2189 * disable). 2190 */ 2191 @Test 2192 public void testConfigs() throws Exception { 2193 final int clientId1 = 9999; 2194 final int clientId2 = 1001; 2195 final int clientId3 = 1005; 2196 final int uid = 1000; 2197 final int pid = 2000; 2198 final String callingPackage = "com.google.somePackage"; 2199 final int masterPref1 = 111; 2200 final int masterPref3 = 115; 2201 final int dwInterval1Band24 = 2; 2202 final int dwInterval3Band24 = 1; 2203 final int dwInterval3Band5 = 0; 2204 2205 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2206 ArgumentCaptor<ConfigRequest> crCapture = ArgumentCaptor.forClass(ConfigRequest.class); 2207 2208 ConfigRequest configRequest1 = new ConfigRequest.Builder() 2209 .setClusterLow(5).setClusterHigh(100) 2210 .setMasterPreference(masterPref1) 2211 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval1Band24) 2212 .build(); 2213 2214 ConfigRequest configRequest2 = new ConfigRequest.Builder() 2215 .setSupport5gBand(true) // compatible 2216 .setClusterLow(7).setClusterHigh(155) // incompatible! 2217 .setMasterPreference(0) // compatible 2218 .build(); 2219 2220 ConfigRequest configRequest3 = new ConfigRequest.Builder() 2221 .setSupport5gBand(true) // compatible (will use true) 2222 .setClusterLow(5).setClusterHigh(100) // identical (hence compatible) 2223 .setMasterPreference(masterPref3) // compatible (will use max) 2224 // compatible: will use min 2225 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval3Band24) 2226 // compatible: will use interval3 since interval1 not init 2227 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_5GHZ, dwInterval3Band5) 2228 .build(); 2229 2230 IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); 2231 IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); 2232 IWifiAwareEventCallback mockCallback3 = mock(IWifiAwareEventCallback.class); 2233 2234 InOrder inOrder = inOrder(mMockNative, mockCallback1, mockCallback2, mockCallback3); 2235 2236 mDut.enableUsage(); 2237 mMockLooper.dispatchAll(); 2238 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2239 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2240 mMockLooper.dispatchAll(); 2241 2242 // (1) config1 (valid) 2243 mDut.connect(clientId1, uid, pid, callingPackage, mockCallback1, configRequest1, false); 2244 mMockLooper.dispatchAll(); 2245 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2246 crCapture.capture(), eq(false), eq(true)); 2247 collector.checkThat("merge: stage 1", crCapture.getValue(), equalTo(configRequest1)); 2248 mDut.onConfigSuccessResponse(transactionId.getValue()); 2249 mMockLooper.dispatchAll(); 2250 inOrder.verify(mockCallback1).onConnectSuccess(clientId1); 2251 2252 // (2) config2 (incompatible with config1) 2253 mDut.connect(clientId2, uid, pid, callingPackage, mockCallback2, configRequest2, false); 2254 mMockLooper.dispatchAll(); 2255 inOrder.verify(mockCallback2).onConnectFail(NanStatusType.INTERNAL_FAILURE); 2256 validateInternalClientInfoCleanedUp(clientId2); 2257 2258 // (3) config3 (compatible with config1) 2259 mDut.connect(clientId3, uid, pid, callingPackage, mockCallback3, configRequest3, true); 2260 mMockLooper.dispatchAll(); 2261 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2262 crCapture.capture(), eq(true), eq(false)); 2263 mDut.onConfigSuccessResponse(transactionId.getValue()); 2264 mMockLooper.dispatchAll(); 2265 inOrder.verify(mockCallback3).onConnectSuccess(clientId3); 2266 2267 collector.checkThat("support 5g: or", true, equalTo(crCapture.getValue().mSupport5gBand)); 2268 collector.checkThat("master preference: max", Math.max(masterPref1, masterPref3), 2269 equalTo(crCapture.getValue().mMasterPreference)); 2270 collector.checkThat("dw interval on 2.4: ~min", 2271 Math.min(dwInterval1Band24, dwInterval3Band24), 2272 equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest 2273 .NAN_BAND_24GHZ])); 2274 collector.checkThat("dw interval on 5: ~min", dwInterval3Band5, 2275 equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest 2276 .NAN_BAND_5GHZ])); 2277 2278 // (4) disconnect config3: downgrade to config1 2279 mDut.disconnect(clientId3); 2280 mMockLooper.dispatchAll(); 2281 validateInternalClientInfoCleanedUp(clientId3); 2282 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2283 crCapture.capture(), eq(false), eq(false)); 2284 2285 collector.checkThat("configRequest1", configRequest1, equalTo(crCapture.getValue())); 2286 2287 mDut.onConfigSuccessResponse(transactionId.getValue()); 2288 mMockLooper.dispatchAll(); 2289 2290 // (5) disconnect config1: disable 2291 mDut.disconnect(clientId1); 2292 mMockLooper.dispatchAll(); 2293 validateInternalClientInfoCleanedUp(clientId1); 2294 inOrder.verify(mMockNative).disable((short) 0); 2295 2296 verifyNoMoreInteractions(mMockNative, mockCallback1, mockCallback2, mockCallback3); 2297 } 2298 2299 /** 2300 * Summary: disconnect a client while there are pending transactions. 2301 */ 2302 @Test 2303 public void testDisconnectWithPendingTransactions() throws Exception { 2304 final int clientId = 125; 2305 final int uid = 1000; 2306 final int pid = 2000; 2307 final String callingPackage = "com.google.somePackage"; 2308 final int clusterLow = 5; 2309 final int clusterHigh = 100; 2310 final int masterPref = 111; 2311 final String serviceName = "some-service-name"; 2312 final String ssi = "some much longer and more arbitrary data"; 2313 final int publishId = 22; 2314 2315 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 2316 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 2317 2318 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 2319 serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( 2320 PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 2321 2322 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2323 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2324 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2325 IWifiAwareDiscoverySessionCallback.class); 2326 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2327 2328 mDut.enableUsage(); 2329 mMockLooper.dispatchAll(); 2330 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2331 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2332 mMockLooper.dispatchAll(); 2333 2334 // (1) connect 2335 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2336 mMockLooper.dispatchAll(); 2337 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2338 eq(false), eq(true)); 2339 mDut.onConfigSuccessResponse(transactionId.getValue()); 2340 mMockLooper.dispatchAll(); 2341 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2342 2343 // (2) publish (no response yet) 2344 mDut.publish(clientId, publishConfig, mockSessionCallback); 2345 mMockLooper.dispatchAll(); 2346 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2347 2348 // (3) disconnect (but doesn't get executed until get a RESPONSE to the 2349 // previous publish) 2350 mDut.disconnect(clientId); 2351 mMockLooper.dispatchAll(); 2352 2353 // (4) get successful response to the publish 2354 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 2355 mMockLooper.dispatchAll(); 2356 inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); 2357 inOrder.verify(mMockNative).stopPublish((short) 0, publishId); 2358 inOrder.verify(mMockNative).disable((short) 0); 2359 2360 validateInternalClientInfoCleanedUp(clientId); 2361 2362 // (5) trying to publish on the same client: NOP 2363 mDut.publish(clientId, publishConfig, mockSessionCallback); 2364 mMockLooper.dispatchAll(); 2365 2366 // (6) got some callback on original publishId - should be ignored 2367 mDut.onSessionTerminatedNotification(publishId, 0, true); 2368 mMockLooper.dispatchAll(); 2369 2370 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2371 } 2372 2373 /** 2374 * Validate that an unknown transaction (i.e. a callback from HAL with an 2375 * unknown type) is simply ignored - but also cleans up its state. 2376 */ 2377 @Test 2378 public void testUnknownTransactionType() throws Exception { 2379 final int clientId = 129; 2380 final int uid = 1000; 2381 final int pid = 2000; 2382 final String callingPackage = "com.google.somePackage"; 2383 final int clusterLow = 15; 2384 final int clusterHigh = 192; 2385 final int masterPref = 234; 2386 final String serviceName = "some-service-name"; 2387 final String ssi = "some much longer and more arbitrary data"; 2388 2389 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 2390 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 2391 2392 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 2393 serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( 2394 PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 2395 2396 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2397 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2398 IWifiAwareDiscoverySessionCallback mockPublishSessionCallback = mock( 2399 IWifiAwareDiscoverySessionCallback.class); 2400 InOrder inOrder = inOrder(mMockNative, mockCallback, mockPublishSessionCallback); 2401 2402 mDut.enableUsage(); 2403 mMockLooper.dispatchAll(); 2404 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2405 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2406 mMockLooper.dispatchAll(); 2407 2408 // (1) connect 2409 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2410 mMockLooper.dispatchAll(); 2411 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2412 eq(false), eq(true)); 2413 mDut.onConfigSuccessResponse(transactionId.getValue()); 2414 mMockLooper.dispatchAll(); 2415 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2416 2417 // (2) publish - no response 2418 mDut.publish(clientId, publishConfig, mockPublishSessionCallback); 2419 mMockLooper.dispatchAll(); 2420 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2421 2422 verifyNoMoreInteractions(mMockNative, mockCallback, mockPublishSessionCallback); 2423 } 2424 2425 /** 2426 * Validate that a NoOp transaction (i.e. a callback from HAL which doesn't 2427 * require any action except clearing up state) actually cleans up its state 2428 * (and does nothing else). 2429 */ 2430 @Test 2431 public void testNoOpTransaction() throws Exception { 2432 final int clientId = 1294; 2433 final int uid = 1000; 2434 final int pid = 2000; 2435 final String callingPackage = "com.google.somePackage"; 2436 2437 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2438 2439 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2440 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2441 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2442 IWifiAwareDiscoverySessionCallback.class); 2443 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2444 2445 mDut.enableUsage(); 2446 mMockLooper.dispatchAll(); 2447 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2448 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2449 mMockLooper.dispatchAll(); 2450 2451 // (1) connect (no response) 2452 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2453 mMockLooper.dispatchAll(); 2454 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2455 eq(false), eq(true)); 2456 2457 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2458 } 2459 2460 /** 2461 * Validate that getting callbacks from HAL with unknown (expired) 2462 * transaction ID or invalid publish/subscribe ID session doesn't have any 2463 * impact. 2464 */ 2465 @Test 2466 public void testInvalidCallbackIdParameters() throws Exception { 2467 final int pubSubId = 1235; 2468 final int clientId = 132; 2469 final int uid = 1000; 2470 final int pid = 2000; 2471 final String callingPackage = "com.google.somePackage"; 2472 2473 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2474 2475 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2476 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2477 InOrder inOrder = inOrder(mMockNative, mockCallback); 2478 2479 mDut.enableUsage(); 2480 mMockLooper.dispatchAll(); 2481 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2482 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2483 mMockLooper.dispatchAll(); 2484 2485 // (1) connect and succeed 2486 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2487 mMockLooper.dispatchAll(); 2488 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2489 eq(false), eq(true)); 2490 short transactionIdConfig = transactionId.getValue(); 2491 mDut.onConfigSuccessResponse(transactionIdConfig); 2492 mMockLooper.dispatchAll(); 2493 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2494 2495 // (2) use the same transaction ID to send a bunch of other responses 2496 mDut.onConfigSuccessResponse(transactionIdConfig); 2497 mDut.onConfigFailedResponse(transactionIdConfig, -1); 2498 mDut.onSessionConfigFailResponse(transactionIdConfig, true, -1); 2499 mDut.onMessageSendQueuedSuccessResponse(transactionIdConfig); 2500 mDut.onMessageSendQueuedFailResponse(transactionIdConfig, -1); 2501 mDut.onSessionConfigFailResponse(transactionIdConfig, false, -1); 2502 mDut.onMatchNotification(-1, -1, new byte[0], new byte[0], new byte[0]); 2503 mDut.onSessionTerminatedNotification(-1, -1, true); 2504 mDut.onSessionTerminatedNotification(-1, -1, false); 2505 mDut.onMessageReceivedNotification(-1, -1, new byte[0], new byte[0]); 2506 mDut.onSessionConfigSuccessResponse(transactionIdConfig, true, pubSubId); 2507 mDut.onSessionConfigSuccessResponse(transactionIdConfig, false, pubSubId); 2508 mMockLooper.dispatchAll(); 2509 2510 verifyNoMoreInteractions(mMockNative, mockCallback); 2511 } 2512 2513 /** 2514 * Validate that trying to update-subscribe on a publish session fails. 2515 */ 2516 @Test 2517 public void testSubscribeOnPublishSessionType() throws Exception { 2518 final int clientId = 188; 2519 final int uid = 1000; 2520 final int pid = 2000; 2521 final String callingPackage = "com.google.somePackage"; 2522 final int publishId = 25; 2523 2524 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2525 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2526 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2527 2528 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2529 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2530 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2531 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2532 IWifiAwareDiscoverySessionCallback.class); 2533 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2534 2535 mDut.enableUsage(); 2536 mMockLooper.dispatchAll(); 2537 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2538 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2539 mMockLooper.dispatchAll(); 2540 2541 // (1) connect 2542 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2543 mMockLooper.dispatchAll(); 2544 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2545 eq(false), eq(true)); 2546 mDut.onConfigSuccessResponse(transactionId.getValue()); 2547 mMockLooper.dispatchAll(); 2548 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2549 2550 // (2) publish 2551 mDut.publish(clientId, publishConfig, mockSessionCallback); 2552 mMockLooper.dispatchAll(); 2553 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2554 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 2555 mMockLooper.dispatchAll(); 2556 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2557 2558 // (3) update-subscribe -> failure 2559 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 2560 mMockLooper.dispatchAll(); 2561 inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 2562 2563 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2564 } 2565 2566 /** 2567 * Validate that trying to (re)subscribe on a publish session or (re)publish 2568 * on a subscribe session fails. 2569 */ 2570 @Test 2571 public void testPublishOnSubscribeSessionType() throws Exception { 2572 final int clientId = 188; 2573 final int uid = 1000; 2574 final int pid = 2000; 2575 final String callingPackage = "com.google.somePackage"; 2576 final int subscribeId = 25; 2577 2578 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2579 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2580 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2581 2582 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2583 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2584 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2585 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2586 IWifiAwareDiscoverySessionCallback.class); 2587 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2588 2589 mDut.enableUsage(); 2590 mMockLooper.dispatchAll(); 2591 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2592 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2593 mMockLooper.dispatchAll(); 2594 2595 // (1) connect 2596 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2597 mMockLooper.dispatchAll(); 2598 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2599 eq(configRequest), eq(false), eq(true)); 2600 mDut.onConfigSuccessResponse(transactionId.getValue()); 2601 mMockLooper.dispatchAll(); 2602 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2603 2604 // (2) subscribe 2605 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 2606 mMockLooper.dispatchAll(); 2607 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 2608 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 2609 mMockLooper.dispatchAll(); 2610 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2611 2612 // (3) update-publish -> error 2613 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 2614 mMockLooper.dispatchAll(); 2615 inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 2616 2617 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2618 } 2619 2620 /** 2621 * Validate that the session ID increments monotonically 2622 */ 2623 @Test 2624 public void testSessionIdIncrement() throws Exception { 2625 final int clientId = 188; 2626 final int uid = 1000; 2627 final int pid = 2000; 2628 final String callingPackage = "com.google.somePackage"; 2629 int loopCount = 100; 2630 2631 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2632 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2633 2634 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2635 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2636 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2637 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2638 IWifiAwareDiscoverySessionCallback.class); 2639 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2640 2641 mDut.enableUsage(); 2642 mMockLooper.dispatchAll(); 2643 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2644 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2645 mMockLooper.dispatchAll(); 2646 2647 // (1) connect 2648 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2649 mMockLooper.dispatchAll(); 2650 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2651 eq(configRequest), eq(false), eq(true)); 2652 mDut.onConfigSuccessResponse(transactionId.getValue()); 2653 mMockLooper.dispatchAll(); 2654 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2655 2656 int prevId = 0; 2657 for (int i = 0; i < loopCount; ++i) { 2658 // (2) publish 2659 mDut.publish(clientId, publishConfig, mockSessionCallback); 2660 mMockLooper.dispatchAll(); 2661 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2662 2663 // (3) publish-success 2664 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, i + 1); 2665 mMockLooper.dispatchAll(); 2666 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2667 2668 if (i != 0) { 2669 assertTrue("Session ID incrementing", sessionId.getValue() > prevId); 2670 } 2671 prevId = sessionId.getValue(); 2672 } 2673 } 2674 2675 /* 2676 * Tests of internal state of WifiAwareStateManager: very limited (not usually 2677 * a good idea). However, these test that the internal state is cleaned-up 2678 * appropriately. Alternatively would cause issues with memory leaks or 2679 * information leak between sessions. 2680 */ 2681 2682 /** 2683 * Utility routine used to validate that the internal state is cleaned-up 2684 * after a client is disconnected. To be used in every test which terminates 2685 * a client. 2686 * 2687 * @param clientId The ID of the client which should be deleted. 2688 */ 2689 private void validateInternalClientInfoCleanedUp(int clientId) throws Exception { 2690 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2691 collector.checkThat("Client record not cleared up for clientId=" + clientId, client, 2692 nullValue()); 2693 } 2694 2695 /** 2696 * Utility routine used to validate that the internal state is cleaned-up 2697 * (deleted) after a session is terminated through API (not callback!). To 2698 * be used in every test which terminates a session. 2699 * 2700 * @param clientId The ID of the client containing the session. 2701 * @param sessionId The ID of the terminated session. 2702 */ 2703 private void validateInternalSessionInfoCleanedUp(int clientId, int sessionId) 2704 throws Exception { 2705 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2706 collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); 2707 WifiAwareDiscoverySessionState session = getInternalSessionState(client, sessionId); 2708 collector.checkThat("Client record not cleaned-up for sessionId=" + sessionId, session, 2709 nullValue()); 2710 } 2711 2712 /** 2713 * Utility routine used to validate that the internal state is cleaned-up 2714 * (deleted) correctly. Checks that a specific client has no sessions 2715 * attached to it. 2716 * 2717 * @param clientId The ID of the client which we want to check. 2718 */ 2719 private void validateInternalNoSessions(int clientId) throws Exception { 2720 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2721 collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); 2722 2723 Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); 2724 field.setAccessible(true); 2725 @SuppressWarnings("unchecked") 2726 SparseArray<WifiAwareDiscoverySessionState> sessions = 2727 (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); 2728 2729 collector.checkThat("No sessions exist for clientId=" + clientId, sessions.size(), 2730 equalTo(0)); 2731 } 2732 2733 /** 2734 * Validates that the broadcast sent on Aware status change is correct. 2735 * 2736 * @param expectedEnabled The expected change status - i.e. are we expected 2737 * to announce that Aware is enabled (true) or disabled (false). 2738 */ 2739 private void validateCorrectAwareStatusChangeBroadcast(InOrder inOrder, 2740 boolean expectedEnabled) { 2741 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 2742 2743 inOrder.verify(mMockContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL)); 2744 2745 collector.checkThat("intent action", intent.getValue().getAction(), 2746 equalTo(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED)); 2747 } 2748 2749 /* 2750 * Utilities 2751 */ 2752 private void dumpDut(String prefix) { 2753 StringWriter sw = new StringWriter(); 2754 mDut.dump(null, new PrintWriter(sw), null); 2755 Log.e("WifiAwareStateManagerTest", prefix + sw.toString()); 2756 } 2757 2758 private static void installMocksInStateManager(WifiAwareStateManager awareStateManager, 2759 WifiAwareRttStateManager mockRtt, WifiAwareDataPathStateManager mockDpMgr) 2760 throws Exception { 2761 Field field = WifiAwareStateManager.class.getDeclaredField("mRtt"); 2762 field.setAccessible(true); 2763 field.set(awareStateManager, mockRtt); 2764 2765 field = WifiAwareStateManager.class.getDeclaredField("mDataPathMgr"); 2766 field.setAccessible(true); 2767 field.set(awareStateManager, mockDpMgr); 2768 } 2769 2770 private static WifiAwareClientState getInternalClientState(WifiAwareStateManager dut, 2771 int clientId) throws Exception { 2772 Field field = WifiAwareStateManager.class.getDeclaredField("mClients"); 2773 field.setAccessible(true); 2774 @SuppressWarnings("unchecked") 2775 SparseArray<WifiAwareClientState> clients = (SparseArray<WifiAwareClientState>) field.get( 2776 dut); 2777 2778 return clients.get(clientId); 2779 } 2780 2781 private static WifiAwareDiscoverySessionState getInternalSessionState( 2782 WifiAwareClientState client, int sessionId) throws Exception { 2783 Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); 2784 field.setAccessible(true); 2785 @SuppressWarnings("unchecked") 2786 SparseArray<WifiAwareDiscoverySessionState> sessions = 2787 (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); 2788 2789 return sessions.get(sessionId); 2790 } 2791 2792 private void validateInternalSendMessageQueuesCleanedUp(int messageId) throws Exception { 2793 Field field = WifiAwareStateManager.class.getDeclaredField("mSm"); 2794 field.setAccessible(true); 2795 WifiAwareStateManager.WifiAwareStateMachine sm = 2796 (WifiAwareStateManager.WifiAwareStateMachine) field.get(mDut); 2797 2798 field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( 2799 "mHostQueuedSendMessages"); 2800 field.setAccessible(true); 2801 SparseArray<Message> hostQueuedSendMessages = (SparseArray<Message>) field.get(sm); 2802 2803 field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( 2804 "mFwQueuedSendMessages"); 2805 field.setAccessible(true); 2806 Map<Short, Message> fwQueuedSendMessages = (Map<Short, Message>) field.get(sm); 2807 2808 for (int i = 0; i < hostQueuedSendMessages.size(); ++i) { 2809 Message msg = hostQueuedSendMessages.valueAt(i); 2810 if (msg.getData().getInt("message_id") == messageId) { 2811 collector.checkThat( 2812 "Message not cleared-up from host queue. Message ID=" + messageId, msg, 2813 nullValue()); 2814 } 2815 } 2816 2817 for (Message msg: fwQueuedSendMessages.values()) { 2818 if (msg.getData().getInt("message_id") == messageId) { 2819 collector.checkThat( 2820 "Message not cleared-up from firmware queue. Message ID=" + messageId, msg, 2821 nullValue()); 2822 } 2823 } 2824 } 2825 2826 private static Capabilities getCapabilities() { 2827 Capabilities cap = new Capabilities(); 2828 cap.maxConcurrentAwareClusters = 1; 2829 cap.maxPublishes = 2; 2830 cap.maxSubscribes = 2; 2831 cap.maxServiceNameLen = 255; 2832 cap.maxMatchFilterLen = 255; 2833 cap.maxTotalMatchFilterLen = 255; 2834 cap.maxServiceSpecificInfoLen = 255; 2835 cap.maxExtendedServiceSpecificInfoLen = 255; 2836 cap.maxNdiInterfaces = 1; 2837 cap.maxNdpSessions = 1; 2838 cap.maxAppInfoLen = 255; 2839 cap.maxQueuedTransmitMessages = 6; 2840 return cap; 2841 } 2842} 2843 2844