WifiAwareStateManagerTest.java revision 9fdded9b33d8b519b713d682ca63dffc8a2191bc
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 subscribeCount = 7; 1039 final int reasonFail = NanStatusType.INTERNAL_FAILURE; 1040 final int subscribeId = 15; 1041 final int requestorId = 22; 1042 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1043 final String peerSsi = "some peer ssi data"; 1044 final String peerMatchFilter = "filter binary array represented as string"; 1045 final String peerMsg = "some message from peer"; 1046 final int messageId = 6948; 1047 final int messageId2 = 6949; 1048 1049 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1050 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1051 .setServiceSpecificInfo(ssi.getBytes()) 1052 .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) 1053 .setSubscribeCount(subscribeCount).build(); 1054 1055 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1056 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1057 IWifiAwareDiscoverySessionCallback.class); 1058 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1059 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1060 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1061 1062 mDut.enableUsage(); 1063 mMockLooper.dispatchAll(); 1064 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1065 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1066 mMockLooper.dispatchAll(); 1067 1068 // (0) connect 1069 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1070 mMockLooper.dispatchAll(); 1071 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1072 eq(configRequest), eq(false), eq(true)); 1073 mDut.onConfigSuccessResponse(transactionId.getValue()); 1074 mMockLooper.dispatchAll(); 1075 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1076 1077 // (1) subscribe 1078 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1079 mMockLooper.dispatchAll(); 1080 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1081 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1082 mMockLooper.dispatchAll(); 1083 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1084 1085 // (2) match 1086 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1087 peerMatchFilter.getBytes()); 1088 mMockLooper.dispatchAll(); 1089 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1090 peerMatchFilter.getBytes()); 1091 1092 // (3) message Rx 1093 mDut.onMessageReceivedNotification(subscribeId, requestorId, peerMac, peerMsg.getBytes()); 1094 mMockLooper.dispatchAll(); 1095 inOrder.verify(mockSessionCallback).onMessageReceived(requestorId, peerMsg.getBytes()); 1096 1097 // (4) message Tx successful queuing 1098 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId, 0); 1099 mMockLooper.dispatchAll(); 1100 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1101 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1102 short tid1 = transactionId.getValue(); 1103 mDut.onMessageSendQueuedSuccessResponse(tid1); 1104 mMockLooper.dispatchAll(); 1105 1106 // (5) message Tx successful queuing 1107 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId2, 1108 0); 1109 mMockLooper.dispatchAll(); 1110 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1111 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId2)); 1112 short tid2 = transactionId.getValue(); 1113 mDut.onMessageSendQueuedSuccessResponse(tid2); 1114 mMockLooper.dispatchAll(); 1115 1116 // (4) and (5) final Tx results (on-air results) 1117 mDut.onMessageSendFailNotification(tid1, reasonFail); 1118 mDut.onMessageSendSuccessNotification(tid2); 1119 mMockLooper.dispatchAll(); 1120 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, reasonFail); 1121 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId2); 1122 validateInternalSendMessageQueuesCleanedUp(messageId); 1123 validateInternalSendMessageQueuesCleanedUp(messageId2); 1124 1125 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1126 } 1127 1128 /** 1129 * Summary: in a single publish session interact with multiple peers 1130 * (different MAC addresses). 1131 */ 1132 @Test 1133 public void testMultipleMessageSources() throws Exception { 1134 final int clientId = 300; 1135 final int uid = 1000; 1136 final int pid = 2000; 1137 final String callingPackage = "com.google.somePackage"; 1138 final int clusterLow = 7; 1139 final int clusterHigh = 7; 1140 final int masterPref = 0; 1141 final String serviceName = "some-service-name"; 1142 final int publishId = 88; 1143 final int peerId1 = 568; 1144 final int peerId2 = 873; 1145 final byte[] peerMac1 = HexEncoding.decode("000102030405".toCharArray(), false); 1146 final byte[] peerMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); 1147 final String msgFromPeer1 = "hey from 000102..."; 1148 final String msgFromPeer2 = "hey from 0607..."; 1149 final String msgToPeer1 = "hey there 000102..."; 1150 final String msgToPeer2 = "hey there 0506..."; 1151 final int msgToPeerId1 = 546; 1152 final int msgToPeerId2 = 9654; 1153 final int reason = NanStatusType.INTERNAL_FAILURE; 1154 1155 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 1156 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 1157 1158 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) 1159 .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 1160 1161 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1162 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1163 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1164 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1165 IWifiAwareDiscoverySessionCallback.class); 1166 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 1167 1168 mDut.enableUsage(); 1169 mMockLooper.dispatchAll(); 1170 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1171 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1172 mMockLooper.dispatchAll(); 1173 1174 // (1) connect 1175 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1176 mMockLooper.dispatchAll(); 1177 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1178 eq(false), eq(true)); 1179 mDut.onConfigSuccessResponse(transactionId.getValue()); 1180 mMockLooper.dispatchAll(); 1181 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1182 1183 // (2) publish 1184 mDut.publish(clientId, publishConfig, mockSessionCallback); 1185 mMockLooper.dispatchAll(); 1186 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 1187 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 1188 mMockLooper.dispatchAll(); 1189 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1190 1191 // (3) message received from peers 1 & 2 1192 mDut.onMessageReceivedNotification(publishId, peerId1, peerMac1, msgFromPeer1.getBytes()); 1193 mDut.onMessageReceivedNotification(publishId, peerId2, peerMac2, msgFromPeer2.getBytes()); 1194 mMockLooper.dispatchAll(); 1195 inOrder.verify(mockSessionCallback).onMessageReceived(peerId1, msgFromPeer1.getBytes()); 1196 inOrder.verify(mockSessionCallback).onMessageReceived(peerId2, msgFromPeer2.getBytes()); 1197 1198 // (4) sending messages back to same peers: one Tx fails, other succeeds 1199 mDut.sendMessage(clientId, sessionId.getValue(), peerId2, msgToPeer2.getBytes(), 1200 msgToPeerId2, 0); 1201 mMockLooper.dispatchAll(); 1202 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId2), 1203 eq(peerMac2), eq(msgToPeer2.getBytes()), eq(msgToPeerId2)); 1204 short transactionIdVal = transactionId.getValue(); 1205 mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); 1206 mDut.onMessageSendSuccessNotification(transactionIdVal); 1207 1208 mDut.sendMessage(clientId, sessionId.getValue(), peerId1, msgToPeer1.getBytes(), 1209 msgToPeerId1, 0); 1210 mMockLooper.dispatchAll(); 1211 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); 1212 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId1), 1213 eq(peerMac1), eq(msgToPeer1.getBytes()), eq(msgToPeerId1)); 1214 transactionIdVal = transactionId.getValue(); 1215 mDut.onMessageSendQueuedSuccessResponse(transactionIdVal); 1216 mDut.onMessageSendFailNotification(transactionIdVal, reason); 1217 mMockLooper.dispatchAll(); 1218 inOrder.verify(mockSessionCallback).onMessageSendFail(msgToPeerId1, reason); 1219 validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); 1220 validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); 1221 1222 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 1223 } 1224 1225 /** 1226 * Summary: interact with a peer which changed its identity (MAC address) 1227 * but which keeps its requestor instance ID. Should be transparent. 1228 */ 1229 @Test 1230 public void testMessageWhilePeerChangesIdentity() throws Exception { 1231 final int clientId = 300; 1232 final int uid = 1000; 1233 final int pid = 2000; 1234 final String callingPackage = "com.google.somePackage"; 1235 final int clusterLow = 7; 1236 final int clusterHigh = 7; 1237 final int masterPref = 0; 1238 final String serviceName = "some-service-name"; 1239 final int publishId = 88; 1240 final int peerId = 568; 1241 final byte[] peerMacOrig = HexEncoding.decode("000102030405".toCharArray(), false); 1242 final byte[] peerMacLater = HexEncoding.decode("060708090A0B".toCharArray(), false); 1243 final String msgFromPeer1 = "hey from 000102..."; 1244 final String msgFromPeer2 = "hey from 0607..."; 1245 final String msgToPeer1 = "hey there 000102..."; 1246 final String msgToPeer2 = "hey there 0506..."; 1247 final int msgToPeerId1 = 546; 1248 final int msgToPeerId2 = 9654; 1249 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 1250 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 1251 1252 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(serviceName) 1253 .setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED).build(); 1254 1255 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1256 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1257 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1258 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1259 IWifiAwareDiscoverySessionCallback.class); 1260 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 1261 1262 mDut.enableUsage(); 1263 mMockLooper.dispatchAll(); 1264 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1265 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1266 mMockLooper.dispatchAll(); 1267 1268 // (1) connect 1269 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1270 mMockLooper.dispatchAll(); 1271 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1272 eq(false), eq(true)); 1273 mDut.onConfigSuccessResponse(transactionId.getValue()); 1274 mMockLooper.dispatchAll(); 1275 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1276 1277 // (2) publish 1278 mDut.publish(clientId, publishConfig, mockSessionCallback); 1279 mMockLooper.dispatchAll(); 1280 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 1281 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 1282 mMockLooper.dispatchAll(); 1283 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1284 1285 // (3) message received & responded to 1286 mDut.onMessageReceivedNotification(publishId, peerId, peerMacOrig, msgFromPeer1.getBytes()); 1287 mDut.sendMessage(clientId, sessionId.getValue(), peerId, msgToPeer1.getBytes(), 1288 msgToPeerId1, 0); 1289 mMockLooper.dispatchAll(); 1290 inOrder.verify(mockSessionCallback).onMessageReceived(peerId, msgFromPeer1.getBytes()); 1291 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 1292 eq(peerMacOrig), eq(msgToPeer1.getBytes()), eq(msgToPeerId1)); 1293 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1294 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1295 mMockLooper.dispatchAll(); 1296 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId1); 1297 validateInternalSendMessageQueuesCleanedUp(msgToPeerId1); 1298 1299 // (4) message received with same peer ID but different MAC 1300 mDut.onMessageReceivedNotification(publishId, peerId, peerMacLater, 1301 msgFromPeer2.getBytes()); 1302 mDut.sendMessage(clientId, sessionId.getValue(), peerId, msgToPeer2.getBytes(), 1303 msgToPeerId2, 0); 1304 mMockLooper.dispatchAll(); 1305 inOrder.verify(mockSessionCallback).onMessageReceived(peerId, msgFromPeer2.getBytes()); 1306 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 1307 eq(peerMacLater), eq(msgToPeer2.getBytes()), eq(msgToPeerId2)); 1308 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1309 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1310 mMockLooper.dispatchAll(); 1311 inOrder.verify(mockSessionCallback).onMessageSendSuccess(msgToPeerId2); 1312 validateInternalSendMessageQueuesCleanedUp(msgToPeerId2); 1313 1314 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 1315 } 1316 1317 /** 1318 * Validate that get failure (with correct code) when trying to send a 1319 * message to an invalid peer ID. 1320 */ 1321 @Test 1322 public void testSendMessageToInvalidPeerId() throws Exception { 1323 final int clientId = 1005; 1324 final int uid = 1000; 1325 final int pid = 2000; 1326 final String callingPackage = "com.google.somePackage"; 1327 final String ssi = "some much longer and more arbitrary data"; 1328 final int subscribeId = 15; 1329 final int requestorId = 22; 1330 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1331 final String peerSsi = "some peer ssi data"; 1332 final String peerMatchFilter = "filter binary array represented as string"; 1333 final int messageId = 6948; 1334 1335 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1336 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1337 1338 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1339 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1340 IWifiAwareDiscoverySessionCallback.class); 1341 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1342 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1343 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1344 1345 mDut.enableUsage(); 1346 mMockLooper.dispatchAll(); 1347 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1348 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1349 mMockLooper.dispatchAll(); 1350 1351 // (1) connect 1352 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1353 mMockLooper.dispatchAll(); 1354 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1355 eq(false), eq(true)); 1356 mDut.onConfigSuccessResponse(transactionId.getValue()); 1357 mMockLooper.dispatchAll(); 1358 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1359 1360 // (2) subscribe & match 1361 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1362 mMockLooper.dispatchAll(); 1363 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1364 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1365 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1366 peerMatchFilter.getBytes()); 1367 mMockLooper.dispatchAll(); 1368 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1369 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1370 peerMatchFilter.getBytes()); 1371 1372 // (3) send message to invalid peer ID 1373 mDut.sendMessage(clientId, sessionId.getValue(), requestorId + 5, ssi.getBytes(), 1374 messageId, 0); 1375 mMockLooper.dispatchAll(); 1376 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1377 NanStatusType.INTERNAL_FAILURE); 1378 validateInternalSendMessageQueuesCleanedUp(messageId); 1379 1380 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1381 } 1382 1383 /** 1384 * Validate that on send message errors are handled correctly: immediate send error, queue fail 1385 * error (not queue full), and timeout. Behavior: correct callback is dispatched and a later 1386 * firmware notification is ignored. Intersperse with one successfull transmission. 1387 */ 1388 @Test 1389 public void testSendMessageErrorsImmediateQueueTimeout() throws Exception { 1390 final int clientId = 1005; 1391 final int uid = 1000; 1392 final int pid = 2000; 1393 final String callingPackage = "com.google.somePackage"; 1394 final String ssi = "some much longer and more arbitrary data"; 1395 final int subscribeId = 15; 1396 final int requestorId = 22; 1397 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1398 final String peerSsi = "some peer ssi data"; 1399 final String peerMatchFilter = "filter binary array represented as string"; 1400 final int messageId = 6948; 1401 1402 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1403 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1404 1405 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1406 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1407 IWifiAwareDiscoverySessionCallback.class); 1408 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1409 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1410 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1411 1412 mDut.enableUsage(); 1413 mMockLooper.dispatchAll(); 1414 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1415 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1416 mMockLooper.dispatchAll(); 1417 1418 // (1) connect 1419 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1420 mMockLooper.dispatchAll(); 1421 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1422 eq(false), eq(true)); 1423 mDut.onConfigSuccessResponse(transactionId.getValue()); 1424 mMockLooper.dispatchAll(); 1425 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1426 1427 // (2) subscribe & match 1428 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1429 mMockLooper.dispatchAll(); 1430 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1431 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1432 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1433 peerMatchFilter.getBytes()); 1434 mMockLooper.dispatchAll(); 1435 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1436 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1437 peerMatchFilter.getBytes()); 1438 1439 // (3) send 2 messages and enqueue successfully 1440 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1441 messageId, 0); 1442 mMockLooper.dispatchAll(); 1443 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1444 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1445 short transactionId1 = transactionId.getValue(); 1446 mDut.onMessageSendQueuedSuccessResponse(transactionId1); 1447 mMockLooper.dispatchAll(); 1448 1449 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1450 messageId + 1, 0); 1451 mMockLooper.dispatchAll(); 1452 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1453 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 1)); 1454 short transactionId2 = transactionId.getValue(); 1455 mDut.onMessageSendQueuedSuccessResponse(transactionId2); 1456 mMockLooper.dispatchAll(); 1457 1458 // (4) send a message and get a queueing failure (not queue full) 1459 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 2, 1460 0); 1461 mMockLooper.dispatchAll(); 1462 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1463 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 2)); 1464 short transactionId3 = transactionId.getValue(); 1465 mDut.onMessageSendQueuedFailResponse(transactionId3, NanStatusType.INTERNAL_FAILURE); 1466 mMockLooper.dispatchAll(); 1467 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 2, 1468 NanStatusType.INTERNAL_FAILURE); 1469 validateInternalSendMessageQueuesCleanedUp(messageId + 2); 1470 1471 // (5) send a message and get an immediate failure (configure first) 1472 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1473 any(), anyInt())).thenReturn(false); 1474 1475 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId + 3, 1476 0); 1477 mMockLooper.dispatchAll(); 1478 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1479 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId + 3)); 1480 short transactionId4 = transactionId.getValue(); 1481 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId + 3, 1482 NanStatusType.INTERNAL_FAILURE); 1483 validateInternalSendMessageQueuesCleanedUp(messageId + 3); 1484 1485 // (6) message send timeout 1486 assertTrue(mAlarmManager.dispatch(WifiAwareStateManager.HAL_SEND_MESSAGE_TIMEOUT_TAG)); 1487 mMockLooper.dispatchAll(); 1488 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1489 NanStatusType.INTERNAL_FAILURE); 1490 validateInternalSendMessageQueuesCleanedUp(messageId); 1491 1492 // (7) firmware response (unlikely - but good to check) 1493 mDut.onMessageSendSuccessNotification(transactionId1); 1494 mDut.onMessageSendSuccessNotification(transactionId2); 1495 1496 // bogus: these didn't even go to firmware or weren't queued 1497 mDut.onMessageSendSuccessNotification(transactionId3); 1498 mDut.onMessageSendFailNotification(transactionId4, NanStatusType.INTERNAL_FAILURE); 1499 mMockLooper.dispatchAll(); 1500 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId + 1); 1501 1502 validateInternalSendMessageQueuesCleanedUp(messageId + 1); 1503 1504 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1505 } 1506 1507 /** 1508 * Validate that when sending a message with a retry count the message is retried the specified 1509 * number of times. Scenario ending with success. 1510 */ 1511 @Test 1512 public void testSendMessageRetransmitSuccess() throws Exception { 1513 final int clientId = 1005; 1514 final int uid = 1000; 1515 final int pid = 2000; 1516 final String callingPackage = "com.google.somePackage"; 1517 final String ssi = "some much longer and more arbitrary data"; 1518 final int subscribeId = 15; 1519 final int requestorId = 22; 1520 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1521 final String peerSsi = "some peer ssi data"; 1522 final String peerMatchFilter = "filter binary array represented as string"; 1523 final int messageId = 6948; 1524 final int retryCount = 3; 1525 1526 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1527 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1528 1529 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1530 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1531 IWifiAwareDiscoverySessionCallback.class); 1532 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1533 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1534 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1535 1536 mDut.enableUsage(); 1537 mMockLooper.dispatchAll(); 1538 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1539 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1540 mMockLooper.dispatchAll(); 1541 1542 // (1) connect 1543 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1544 mMockLooper.dispatchAll(); 1545 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1546 eq(false), eq(true)); 1547 mDut.onConfigSuccessResponse(transactionId.getValue()); 1548 mMockLooper.dispatchAll(); 1549 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1550 1551 // (2) subscribe & match 1552 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1553 mMockLooper.dispatchAll(); 1554 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1555 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1556 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1557 peerMatchFilter.getBytes()); 1558 mMockLooper.dispatchAll(); 1559 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1560 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1561 peerMatchFilter.getBytes()); 1562 1563 // (3) send message and enqueue successfully 1564 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), 1565 messageId, retryCount); 1566 mMockLooper.dispatchAll(); 1567 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1568 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1569 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1570 mMockLooper.dispatchAll(); 1571 1572 // (4) loop and fail until reach retryCount 1573 for (int i = 0; i < retryCount; ++i) { 1574 mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); 1575 mMockLooper.dispatchAll(); 1576 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1577 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1578 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1579 mMockLooper.dispatchAll(); 1580 } 1581 1582 // (5) succeed on last retry 1583 mDut.onMessageSendSuccessNotification(transactionId.getValue()); 1584 mMockLooper.dispatchAll(); 1585 1586 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1587 validateInternalSendMessageQueuesCleanedUp(messageId); 1588 1589 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1590 } 1591 1592 /** 1593 * Validate that when sending a message with a retry count the message is retried the specified 1594 * number of times. Scenario ending with failure. 1595 */ 1596 @Test 1597 public void testSendMessageRetransmitFail() throws Exception { 1598 final int clientId = 1005; 1599 final int uid = 1000; 1600 final int pid = 2000; 1601 final String callingPackage = "com.google.somePackage"; 1602 final String ssi = "some much longer and more arbitrary data"; 1603 final int subscribeId = 15; 1604 final int requestorId = 22; 1605 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1606 final String peerSsi = "some peer ssi data"; 1607 final String peerMatchFilter = "filter binary array represented as string"; 1608 final int messageId = 6948; 1609 final int retryCount = 3; 1610 1611 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1612 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 1613 1614 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1615 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1616 IWifiAwareDiscoverySessionCallback.class); 1617 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1618 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1619 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1620 1621 mDut.enableUsage(); 1622 mMockLooper.dispatchAll(); 1623 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1624 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1625 mMockLooper.dispatchAll(); 1626 1627 // (1) connect 1628 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1629 mMockLooper.dispatchAll(); 1630 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 1631 eq(false), eq(true)); 1632 mDut.onConfigSuccessResponse(transactionId.getValue()); 1633 mMockLooper.dispatchAll(); 1634 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1635 1636 // (2) subscribe & match 1637 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1638 mMockLooper.dispatchAll(); 1639 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1640 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1641 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1642 peerMatchFilter.getBytes()); 1643 mMockLooper.dispatchAll(); 1644 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1645 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1646 peerMatchFilter.getBytes()); 1647 1648 // (3) send message and enqueue successfully 1649 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, ssi.getBytes(), messageId, 1650 retryCount); 1651 mMockLooper.dispatchAll(); 1652 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1653 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1654 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1655 mMockLooper.dispatchAll(); 1656 1657 // (4) loop and fail until reach retryCount+1 1658 for (int i = 0; i < retryCount + 1; ++i) { 1659 mDut.onMessageSendFailNotification(transactionId.getValue(), NanStatusType.NO_OTA_ACK); 1660 mMockLooper.dispatchAll(); 1661 1662 if (i != retryCount) { 1663 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1664 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(messageId)); 1665 mDut.onMessageSendQueuedSuccessResponse(transactionId.getValue()); 1666 mMockLooper.dispatchAll(); 1667 } 1668 } 1669 1670 inOrder.verify(mockSessionCallback).onMessageSendFail(messageId, 1671 NanStatusType.NO_OTA_ACK); 1672 validateInternalSendMessageQueuesCleanedUp(messageId); 1673 1674 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 1675 } 1676 1677 /** 1678 * Validate that the host-side message queue functions. Tests the perfect case of queue always 1679 * succeeds and all messages are received on first attempt. 1680 */ 1681 @Test 1682 public void testSendMessageQueueSequence() throws Exception { 1683 final int clientId = 1005; 1684 final int uid = 1000; 1685 final int pid = 2000; 1686 final String callingPackage = "com.google.somePackage"; 1687 final String serviceName = "some-service-name"; 1688 final int subscribeId = 15; 1689 final int requestorId = 22; 1690 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1691 final int messageIdBase = 6948; 1692 final int numberOfMessages = 30; 1693 final int queueDepth = 6; 1694 1695 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1696 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1697 .build(); 1698 1699 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1700 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1701 IWifiAwareDiscoverySessionCallback.class); 1702 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1703 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1704 ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class); 1705 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1706 1707 mDut.enableUsage(); 1708 mMockLooper.dispatchAll(); 1709 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1710 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1711 mMockLooper.dispatchAll(); 1712 1713 // (0) connect 1714 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1715 mMockLooper.dispatchAll(); 1716 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1717 eq(configRequest), eq(false), eq(true)); 1718 mDut.onConfigSuccessResponse(transactionId.getValue()); 1719 mMockLooper.dispatchAll(); 1720 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1721 1722 // (1) subscribe 1723 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1724 mMockLooper.dispatchAll(); 1725 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1726 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1727 mMockLooper.dispatchAll(); 1728 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1729 1730 // (2) match 1731 mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null); 1732 mMockLooper.dispatchAll(); 1733 inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null); 1734 1735 // (3) transmit messages 1736 SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, 1737 null, null, null); 1738 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1739 any(), anyInt())).thenAnswer(answerObj); 1740 1741 int remainingMessages = numberOfMessages; 1742 for (int i = 0; i < numberOfMessages; ++i) { 1743 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i, 1744 0); 1745 mMockLooper.dispatchAll(); 1746 // at 1/2 interval have the system simulate transmitting a queued message over-the-air 1747 if (i % 2 == 1) { 1748 assertTrue(answerObj.process()); 1749 remainingMessages--; 1750 mMockLooper.dispatchAll(); 1751 } 1752 } 1753 for (int i = 0; i < remainingMessages; ++i) { 1754 assertTrue(answerObj.process()); 1755 mMockLooper.dispatchAll(); 1756 } 1757 assertEquals("queue empty", 0, answerObj.queueSize()); 1758 1759 inOrder.verify(mockSessionCallback, times(numberOfMessages)).onMessageSendSuccess( 1760 messageIdCaptor.capture()); 1761 for (int i = 0; i < numberOfMessages; ++i) { 1762 assertEquals("message ID: " + i, (long) messageIdBase + i, 1763 (long) messageIdCaptor.getAllValues().get(i)); 1764 } 1765 1766 verifyNoMoreInteractions(mockCallback, mockSessionCallback); 1767 } 1768 1769 /** 1770 * Validate that the host-side message queue functions. A combination of imperfect conditions: 1771 * - Failure to queue: synchronous firmware error 1772 * - Failure to queue: asyncronous firmware error 1773 * - Failure to transmit: OTA (which will be retried) 1774 * - Failure to transmit: other 1775 */ 1776 @Test 1777 public void testSendMessageQueueSequenceImperfect() throws Exception { 1778 final int clientId = 1005; 1779 final int uid = 1000; 1780 final int pid = 2000; 1781 final String callingPackage = "com.google.somePackage"; 1782 final String serviceName = "some-service-name"; 1783 final int subscribeId = 15; 1784 final int requestorId = 22; 1785 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1786 final int messageIdBase = 6948; 1787 final int numberOfMessages = 300; 1788 final int queueDepth = 6; 1789 final int retransmitCount = 3; // not the maximum 1790 1791 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1792 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1793 .build(); 1794 1795 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1796 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1797 IWifiAwareDiscoverySessionCallback.class); 1798 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1799 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1800 ArgumentCaptor<Integer> messageIdCaptor = ArgumentCaptor.forClass(Integer.class); 1801 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1802 1803 mDut.enableUsage(); 1804 mMockLooper.dispatchAll(); 1805 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1806 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1807 mMockLooper.dispatchAll(); 1808 1809 // (0) connect 1810 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1811 mMockLooper.dispatchAll(); 1812 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1813 eq(configRequest), eq(false), eq(true)); 1814 mDut.onConfigSuccessResponse(transactionId.getValue()); 1815 mMockLooper.dispatchAll(); 1816 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1817 1818 // (1) subscribe 1819 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1820 mMockLooper.dispatchAll(); 1821 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1822 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1823 mMockLooper.dispatchAll(); 1824 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1825 1826 // (2) match 1827 mDut.onMatchNotification(subscribeId, requestorId, peerMac, null, null); 1828 mMockLooper.dispatchAll(); 1829 inOrder.verify(mockSessionCallback).onMatch(requestorId, null, null); 1830 1831 // (3) transmit messages: configure a mix of failures/success 1832 Set<Integer> failQueueCommandImmediately = new HashSet<>(); 1833 Set<Integer> failQueueCommandLater = new HashSet<>(); 1834 Map<Integer, Integer> numberOfRetries = new HashMap<>(); 1835 1836 int numOfSuccesses = 0; 1837 int numOfFailuresInternalFailure = 0; 1838 int numOfFailuresNoOta = 0; 1839 for (int i = 0; i < numberOfMessages; ++i) { 1840 // random results: 1841 // - 0-50: success 1842 // - 51-60: retransmit value (which will fail for >5) 1843 // - 61-70: fail queue later 1844 // - 71-80: fail queue immediately 1845 // - 81-90: fail retransmit with non-OTA failure 1846 int random = mRandomNg.nextInt(90); 1847 if (random <= 50) { 1848 numberOfRetries.put(messageIdBase + i, 0); 1849 numOfSuccesses++; 1850 } else if (random <= 60) { 1851 numberOfRetries.put(messageIdBase + i, random - 51); 1852 if (random - 51 > retransmitCount) { 1853 numOfFailuresNoOta++; 1854 } else { 1855 numOfSuccesses++; 1856 } 1857 } else if (random <= 70) { 1858 failQueueCommandLater.add(messageIdBase + i); 1859 numOfFailuresInternalFailure++; 1860 } else if (random <= 80) { 1861 failQueueCommandImmediately.add(messageIdBase + i); 1862 numOfFailuresInternalFailure++; 1863 } else { 1864 numberOfRetries.put(messageIdBase + i, -1); 1865 numOfFailuresInternalFailure++; 1866 } 1867 } 1868 1869 Log.v("WifiAwareStateManagerTest", 1870 "failQueueCommandImmediately=" + failQueueCommandImmediately 1871 + ", failQueueCommandLater=" + failQueueCommandLater + ", numberOfRetries=" 1872 + numberOfRetries + ", numOfSuccesses=" + numOfSuccesses 1873 + ", numOfFailuresInternalFailure=" + numOfFailuresInternalFailure 1874 + ", numOfFailuresNoOta=" + numOfFailuresNoOta); 1875 1876 SendMessageQueueModelAnswer answerObj = new SendMessageQueueModelAnswer(queueDepth, 1877 failQueueCommandImmediately, failQueueCommandLater, numberOfRetries); 1878 when(mMockNative.sendMessage(anyShort(), anyInt(), anyInt(), any(), 1879 any(), anyInt())).thenAnswer(answerObj); 1880 1881 for (int i = 0; i < numberOfMessages; ++i) { 1882 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageIdBase + i, 1883 retransmitCount); 1884 mMockLooper.dispatchAll(); 1885 } 1886 1887 while (answerObj.queueSize() != 0) { 1888 assertTrue(answerObj.process()); 1889 mMockLooper.dispatchAll(); 1890 } 1891 1892 verify(mockSessionCallback, times(numOfSuccesses)).onMessageSendSuccess(anyInt()); 1893 verify(mockSessionCallback, times(numOfFailuresInternalFailure)).onMessageSendFail(anyInt(), 1894 eq(NanStatusType.INTERNAL_FAILURE)); 1895 verify(mockSessionCallback, times(numOfFailuresNoOta)).onMessageSendFail(anyInt(), 1896 eq(NanStatusType.NO_OTA_ACK)); 1897 1898 verifyNoMoreInteractions(mockCallback, mockSessionCallback); 1899 } 1900 1901 /** 1902 * Validate that can send empty message successfully: null, byte[0], "" 1903 */ 1904 @Test 1905 public void testSendEmptyMessages() throws Exception { 1906 final int clientId = 1005; 1907 final int uid = 1000; 1908 final int pid = 2000; 1909 final String callingPackage = "com.google.somePackage"; 1910 final String serviceName = "some-service-name"; 1911 final String ssi = "some much longer and more arbitrary data"; 1912 final int subscribeCount = 7; 1913 final int subscribeId = 15; 1914 final int requestorId = 22; 1915 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 1916 final String peerSsi = "some peer ssi data"; 1917 final String peerMatchFilter = "filter binary array represented as string"; 1918 final int messageId = 6948; 1919 1920 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 1921 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) 1922 .setServiceSpecificInfo(ssi.getBytes()) 1923 .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) 1924 .setSubscribeCount(subscribeCount).build(); 1925 1926 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 1927 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 1928 IWifiAwareDiscoverySessionCallback.class); 1929 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1930 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 1931 ArgumentCaptor<byte[]> byteArrayCaptor = ArgumentCaptor.forClass(byte[].class); 1932 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); 1933 1934 mDut.enableUsage(); 1935 mMockLooper.dispatchAll(); 1936 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 1937 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 1938 mMockLooper.dispatchAll(); 1939 1940 // (0) connect 1941 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 1942 mMockLooper.dispatchAll(); 1943 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 1944 eq(configRequest), eq(false), eq(true)); 1945 mDut.onConfigSuccessResponse(transactionId.getValue()); 1946 mMockLooper.dispatchAll(); 1947 inOrder.verify(mockCallback).onConnectSuccess(clientId); 1948 1949 // (1) subscribe 1950 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 1951 mMockLooper.dispatchAll(); 1952 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 1953 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 1954 mMockLooper.dispatchAll(); 1955 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 1956 1957 // (2) match 1958 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 1959 peerMatchFilter.getBytes()); 1960 mMockLooper.dispatchAll(); 1961 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 1962 peerMatchFilter.getBytes()); 1963 1964 // (3) message null Tx successful queuing 1965 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, null, messageId, 0); 1966 mMockLooper.dispatchAll(); 1967 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1968 eq(requestorId), eq(peerMac), isNull(byte[].class), eq(messageId)); 1969 short tid = transactionId.getValue(); 1970 mDut.onMessageSendQueuedSuccessResponse(tid); 1971 mMockLooper.dispatchAll(); 1972 1973 // (4) final Tx results (on-air results) 1974 mDut.onMessageSendSuccessNotification(tid); 1975 mMockLooper.dispatchAll(); 1976 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1977 validateInternalSendMessageQueuesCleanedUp(messageId); 1978 1979 // (5) message byte[0] Tx successful queuing 1980 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, new byte[0], messageId, 0); 1981 mMockLooper.dispatchAll(); 1982 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1983 eq(requestorId), eq(peerMac), eq(new byte[0]), eq(messageId)); 1984 tid = transactionId.getValue(); 1985 mDut.onMessageSendQueuedSuccessResponse(tid); 1986 mMockLooper.dispatchAll(); 1987 1988 // (6) final Tx results (on-air results) 1989 mDut.onMessageSendSuccessNotification(tid); 1990 mMockLooper.dispatchAll(); 1991 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 1992 validateInternalSendMessageQueuesCleanedUp(messageId); 1993 1994 // (7) message "" Tx successful queuing 1995 mDut.sendMessage(clientId, sessionId.getValue(), requestorId, "".getBytes(), messageId, 0); 1996 mMockLooper.dispatchAll(); 1997 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 1998 eq(requestorId), eq(peerMac), byteArrayCaptor.capture(), eq(messageId)); 1999 collector.checkThat("Empty message contents", "", 2000 equalTo(new String(byteArrayCaptor.getValue()))); 2001 tid = transactionId.getValue(); 2002 mDut.onMessageSendQueuedSuccessResponse(tid); 2003 mMockLooper.dispatchAll(); 2004 2005 // (8) final Tx results (on-air results) 2006 mDut.onMessageSendSuccessNotification(tid); 2007 mMockLooper.dispatchAll(); 2008 inOrder.verify(mockSessionCallback).onMessageSendSuccess(messageId); 2009 validateInternalSendMessageQueuesCleanedUp(messageId); 2010 2011 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); 2012 } 2013 2014 private class SendMessageQueueModelAnswer extends MockAnswerUtil.AnswerWithArguments { 2015 private final int mMaxQueueDepth; 2016 2017 // keyed by message ID 2018 private final Set<Integer> mFailQueueCommandImmediately; // return a false 2019 private final Set<Integer> mFailQueueCommandLater; // return an error != TX_QUEUE_FULL 2020 2021 // # of times to return NO_OTA_ACK before returning SUCCESS. So a 0 means success on first 2022 // try, a very large number means - never succeed (since max retry is 5). 2023 // a -1 impiles a non-OTA failure: on first attempt 2024 private final Map<Integer, Integer> mRetryLimit; 2025 2026 private final LinkedList<Short> mQueue = new LinkedList<>(); // transaction ID (tid) 2027 private final Map<Short, Integer> mMessageIdsByTid = new HashMap<>(); // tid -> message ID 2028 private final Map<Integer, Integer> mTriesUsedByMid = new HashMap<>(); // mid -> # of retx 2029 2030 SendMessageQueueModelAnswer(int maxQueueDepth, Set<Integer> failQueueCommandImmediately, 2031 Set<Integer> failQueueCommandLater, Map<Integer, Integer> numberOfRetries) { 2032 mMaxQueueDepth = maxQueueDepth; 2033 mFailQueueCommandImmediately = failQueueCommandImmediately; 2034 mFailQueueCommandLater = failQueueCommandLater; 2035 mRetryLimit = numberOfRetries; 2036 2037 if (mRetryLimit != null) { 2038 for (int mid : mRetryLimit.keySet()) { 2039 mTriesUsedByMid.put(mid, 0); 2040 } 2041 } 2042 } 2043 2044 public boolean answer(short transactionId, int pubSubId, int requestorInstanceId, 2045 byte[] dest, byte[] message, int messageId) throws Exception { 2046 if (mFailQueueCommandImmediately != null && mFailQueueCommandImmediately.contains( 2047 messageId)) { 2048 return false; 2049 } 2050 2051 if (mFailQueueCommandLater != null && mFailQueueCommandLater.contains(messageId)) { 2052 mDut.onMessageSendQueuedFailResponse(transactionId, NanStatusType.INTERNAL_FAILURE); 2053 } else { 2054 if (mQueue.size() <= mMaxQueueDepth) { 2055 mQueue.addLast(transactionId); 2056 mMessageIdsByTid.put(transactionId, messageId); 2057 mDut.onMessageSendQueuedSuccessResponse(transactionId); 2058 } else { 2059 mDut.onMessageSendQueuedFailResponse(transactionId, 2060 NanStatusType.FOLLOWUP_TX_QUEUE_FULL); 2061 } 2062 } 2063 2064 return true; 2065 } 2066 2067 /** 2068 * Processes the first message in the queue: i.e. responds as if sent over-the-air 2069 * (successfully or failed) 2070 */ 2071 boolean process() { 2072 if (mQueue.size() == 0) { 2073 return false; 2074 } 2075 short tid = mQueue.poll(); 2076 int mid = mMessageIdsByTid.get(tid); 2077 2078 if (mRetryLimit != null && mRetryLimit.containsKey(mid)) { 2079 int numRetries = mRetryLimit.get(mid); 2080 if (numRetries == -1) { 2081 mDut.onMessageSendFailNotification(tid, NanStatusType.INTERNAL_FAILURE); 2082 } else { 2083 int currentRetries = mTriesUsedByMid.get(mid); 2084 if (currentRetries > numRetries) { 2085 return false; // shouldn't be retrying!? 2086 } else if (currentRetries == numRetries) { 2087 mDut.onMessageSendSuccessNotification(tid); 2088 } else { 2089 mDut.onMessageSendFailNotification(tid, NanStatusType.NO_OTA_ACK); 2090 } 2091 mTriesUsedByMid.put(mid, currentRetries + 1); 2092 } 2093 } else { 2094 mDut.onMessageSendSuccessNotification(tid); 2095 } 2096 2097 return true; 2098 } 2099 2100 /** 2101 * Returns the number of elements in the queue. 2102 */ 2103 int queueSize() { 2104 return mQueue.size(); 2105 } 2106 } 2107 2108 /** 2109 * Validate that start ranging function fills-in correct MAC addresses for peer IDs and 2110 * passed along to RTT module. 2111 */ 2112 @Test 2113 public void testStartRanging() throws Exception { 2114 final int clientId = 1005; 2115 final int uid = 1000; 2116 final int pid = 2000; 2117 final String callingPackage = "com.google.somePackage"; 2118 final int subscribeId = 15; 2119 final int requestorId = 22; 2120 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 2121 final String peerSsi = "some peer ssi data"; 2122 final String peerMatchFilter = "filter binary array represented as string"; 2123 final int rangingId = 18423; 2124 final RttManager.RttParams[] params = new RttManager.RttParams[2]; 2125 params[0] = new RttManager.RttParams(); 2126 params[0].bssid = Integer.toString(requestorId); 2127 params[1] = new RttManager.RttParams(); 2128 params[1].bssid = Integer.toString(requestorId + 5); 2129 2130 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2131 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2132 2133 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2134 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2135 IWifiAwareDiscoverySessionCallback.class); 2136 2137 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2138 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2139 ArgumentCaptor<WifiAwareClientState> clientCaptor = 2140 ArgumentCaptor.forClass(WifiAwareClientState.class); 2141 ArgumentCaptor<RttManager.RttParams[]> rttParamsCaptor = 2142 ArgumentCaptor.forClass(RttManager.RttParams[].class); 2143 2144 InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative, 2145 mMockAwareRttStateManager); 2146 2147 mDut.enableUsage(); 2148 mMockLooper.dispatchAll(); 2149 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2150 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2151 mMockLooper.dispatchAll(); 2152 2153 // (1) connect 2154 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2155 mMockLooper.dispatchAll(); 2156 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2157 eq(false), eq(true)); 2158 mDut.onConfigSuccessResponse(transactionId.getValue()); 2159 mMockLooper.dispatchAll(); 2160 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2161 2162 // (2) subscribe & match 2163 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 2164 mMockLooper.dispatchAll(); 2165 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 2166 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 2167 mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), 2168 peerMatchFilter.getBytes()); 2169 mMockLooper.dispatchAll(); 2170 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2171 inOrder.verify(mockSessionCallback).onMatch(requestorId, peerSsi.getBytes(), 2172 peerMatchFilter.getBytes()); 2173 2174 // (3) start ranging: pass along a valid peer ID and an invalid one 2175 mDut.startRanging(clientId, sessionId.getValue(), params, rangingId); 2176 mMockLooper.dispatchAll(); 2177 inOrder.verify(mMockAwareRttStateManager).startRanging(eq(rangingId), 2178 clientCaptor.capture(), rttParamsCaptor.capture()); 2179 collector.checkThat("RttParams[0].bssid", "06:07:08:09:0A:0B", 2180 equalTo(rttParamsCaptor.getValue()[0].bssid)); 2181 collector.checkThat("RttParams[1].bssid", "", equalTo(rttParamsCaptor.getValue()[1].bssid)); 2182 2183 verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, 2184 mMockAwareRttStateManager); 2185 } 2186 2187 /** 2188 * Test sequence of configuration: (1) config1, (2) config2 - incompatible, 2189 * (3) config3 - compatible with config1 (requiring upgrade), (4) disconnect 2190 * config3 (should get a downgrade), (5) disconnect config1 (should get a 2191 * disable). 2192 */ 2193 @Test 2194 public void testConfigs() throws Exception { 2195 final int clientId1 = 9999; 2196 final int clientId2 = 1001; 2197 final int clientId3 = 1005; 2198 final int uid = 1000; 2199 final int pid = 2000; 2200 final String callingPackage = "com.google.somePackage"; 2201 final int masterPref1 = 111; 2202 final int masterPref3 = 115; 2203 final int dwInterval1Band24 = 2; 2204 final int dwInterval3Band24 = 1; 2205 final int dwInterval3Band5 = 0; 2206 2207 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2208 ArgumentCaptor<ConfigRequest> crCapture = ArgumentCaptor.forClass(ConfigRequest.class); 2209 2210 ConfigRequest configRequest1 = new ConfigRequest.Builder() 2211 .setClusterLow(5).setClusterHigh(100) 2212 .setMasterPreference(masterPref1) 2213 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval1Band24) 2214 .build(); 2215 2216 ConfigRequest configRequest2 = new ConfigRequest.Builder() 2217 .setSupport5gBand(true) // compatible 2218 .setClusterLow(7).setClusterHigh(155) // incompatible! 2219 .setMasterPreference(0) // compatible 2220 .build(); 2221 2222 ConfigRequest configRequest3 = new ConfigRequest.Builder() 2223 .setSupport5gBand(true) // compatible (will use true) 2224 .setClusterLow(5).setClusterHigh(100) // identical (hence compatible) 2225 .setMasterPreference(masterPref3) // compatible (will use max) 2226 // compatible: will use min 2227 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, dwInterval3Band24) 2228 // compatible: will use interval3 since interval1 not init 2229 .setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_5GHZ, dwInterval3Band5) 2230 .build(); 2231 2232 IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); 2233 IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); 2234 IWifiAwareEventCallback mockCallback3 = mock(IWifiAwareEventCallback.class); 2235 2236 InOrder inOrder = inOrder(mMockNative, mockCallback1, mockCallback2, mockCallback3); 2237 2238 mDut.enableUsage(); 2239 mMockLooper.dispatchAll(); 2240 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2241 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2242 mMockLooper.dispatchAll(); 2243 2244 // (1) config1 (valid) 2245 mDut.connect(clientId1, uid, pid, callingPackage, mockCallback1, configRequest1, false); 2246 mMockLooper.dispatchAll(); 2247 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2248 crCapture.capture(), eq(false), eq(true)); 2249 collector.checkThat("merge: stage 1", crCapture.getValue(), equalTo(configRequest1)); 2250 mDut.onConfigSuccessResponse(transactionId.getValue()); 2251 mMockLooper.dispatchAll(); 2252 inOrder.verify(mockCallback1).onConnectSuccess(clientId1); 2253 2254 // (2) config2 (incompatible with config1) 2255 mDut.connect(clientId2, uid, pid, callingPackage, mockCallback2, configRequest2, false); 2256 mMockLooper.dispatchAll(); 2257 inOrder.verify(mockCallback2).onConnectFail(NanStatusType.INTERNAL_FAILURE); 2258 validateInternalClientInfoCleanedUp(clientId2); 2259 2260 // (3) config3 (compatible with config1) 2261 mDut.connect(clientId3, uid, pid, callingPackage, mockCallback3, configRequest3, true); 2262 mMockLooper.dispatchAll(); 2263 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2264 crCapture.capture(), eq(true), eq(false)); 2265 mDut.onConfigSuccessResponse(transactionId.getValue()); 2266 mMockLooper.dispatchAll(); 2267 inOrder.verify(mockCallback3).onConnectSuccess(clientId3); 2268 2269 collector.checkThat("support 5g: or", true, equalTo(crCapture.getValue().mSupport5gBand)); 2270 collector.checkThat("master preference: max", Math.max(masterPref1, masterPref3), 2271 equalTo(crCapture.getValue().mMasterPreference)); 2272 collector.checkThat("dw interval on 2.4: ~min", 2273 Math.min(dwInterval1Band24, dwInterval3Band24), 2274 equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest 2275 .NAN_BAND_24GHZ])); 2276 collector.checkThat("dw interval on 5: ~min", dwInterval3Band5, 2277 equalTo(crCapture.getValue().mDiscoveryWindowInterval[ConfigRequest 2278 .NAN_BAND_5GHZ])); 2279 2280 // (4) disconnect config3: downgrade to config1 2281 mDut.disconnect(clientId3); 2282 mMockLooper.dispatchAll(); 2283 validateInternalClientInfoCleanedUp(clientId3); 2284 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2285 crCapture.capture(), eq(false), eq(false)); 2286 2287 collector.checkThat("configRequest1", configRequest1, equalTo(crCapture.getValue())); 2288 2289 mDut.onConfigSuccessResponse(transactionId.getValue()); 2290 mMockLooper.dispatchAll(); 2291 2292 // (5) disconnect config1: disable 2293 mDut.disconnect(clientId1); 2294 mMockLooper.dispatchAll(); 2295 validateInternalClientInfoCleanedUp(clientId1); 2296 inOrder.verify(mMockNative).disable((short) 0); 2297 2298 verifyNoMoreInteractions(mMockNative, mockCallback1, mockCallback2, mockCallback3); 2299 } 2300 2301 /** 2302 * Summary: disconnect a client while there are pending transactions. 2303 */ 2304 @Test 2305 public void testDisconnectWithPendingTransactions() throws Exception { 2306 final int clientId = 125; 2307 final int uid = 1000; 2308 final int pid = 2000; 2309 final String callingPackage = "com.google.somePackage"; 2310 final int clusterLow = 5; 2311 final int clusterHigh = 100; 2312 final int masterPref = 111; 2313 final String serviceName = "some-service-name"; 2314 final String ssi = "some much longer and more arbitrary data"; 2315 final int publishCount = 7; 2316 final int publishId = 22; 2317 2318 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 2319 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 2320 2321 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 2322 serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( 2323 PublishConfig.PUBLISH_TYPE_UNSOLICITED).setPublishCount(publishCount).build(); 2324 2325 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2326 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2327 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2328 IWifiAwareDiscoverySessionCallback.class); 2329 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2330 2331 mDut.enableUsage(); 2332 mMockLooper.dispatchAll(); 2333 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2334 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2335 mMockLooper.dispatchAll(); 2336 2337 // (1) connect 2338 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2339 mMockLooper.dispatchAll(); 2340 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2341 eq(false), eq(true)); 2342 mDut.onConfigSuccessResponse(transactionId.getValue()); 2343 mMockLooper.dispatchAll(); 2344 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2345 2346 // (2) publish (no response yet) 2347 mDut.publish(clientId, publishConfig, mockSessionCallback); 2348 mMockLooper.dispatchAll(); 2349 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2350 2351 // (3) disconnect (but doesn't get executed until get a RESPONSE to the 2352 // previous publish) 2353 mDut.disconnect(clientId); 2354 mMockLooper.dispatchAll(); 2355 2356 // (4) get successful response to the publish 2357 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 2358 mMockLooper.dispatchAll(); 2359 inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); 2360 inOrder.verify(mMockNative).stopPublish((short) 0, publishId); 2361 inOrder.verify(mMockNative).disable((short) 0); 2362 2363 validateInternalClientInfoCleanedUp(clientId); 2364 2365 // (5) trying to publish on the same client: NOP 2366 mDut.publish(clientId, publishConfig, mockSessionCallback); 2367 mMockLooper.dispatchAll(); 2368 2369 // (6) got some callback on original publishId - should be ignored 2370 mDut.onSessionTerminatedNotification(publishId, 0, true); 2371 mMockLooper.dispatchAll(); 2372 2373 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2374 } 2375 2376 /** 2377 * Validate that an unknown transaction (i.e. a callback from HAL with an 2378 * unknown type) is simply ignored - but also cleans up its state. 2379 */ 2380 @Test 2381 public void testUnknownTransactionType() throws Exception { 2382 final int clientId = 129; 2383 final int uid = 1000; 2384 final int pid = 2000; 2385 final String callingPackage = "com.google.somePackage"; 2386 final int clusterLow = 15; 2387 final int clusterHigh = 192; 2388 final int masterPref = 234; 2389 final String serviceName = "some-service-name"; 2390 final String ssi = "some much longer and more arbitrary data"; 2391 final int publishCount = 15; 2392 2393 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 2394 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 2395 2396 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 2397 serviceName).setServiceSpecificInfo(ssi.getBytes()).setPublishType( 2398 PublishConfig.PUBLISH_TYPE_UNSOLICITED).setPublishCount(publishCount).build(); 2399 2400 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2401 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2402 IWifiAwareDiscoverySessionCallback mockPublishSessionCallback = mock( 2403 IWifiAwareDiscoverySessionCallback.class); 2404 InOrder inOrder = inOrder(mMockNative, mockCallback, mockPublishSessionCallback); 2405 2406 mDut.enableUsage(); 2407 mMockLooper.dispatchAll(); 2408 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2409 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2410 mMockLooper.dispatchAll(); 2411 2412 // (1) connect 2413 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2414 mMockLooper.dispatchAll(); 2415 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2416 eq(false), eq(true)); 2417 mDut.onConfigSuccessResponse(transactionId.getValue()); 2418 mMockLooper.dispatchAll(); 2419 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2420 2421 // (2) publish - no response 2422 mDut.publish(clientId, publishConfig, mockPublishSessionCallback); 2423 mMockLooper.dispatchAll(); 2424 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2425 2426 verifyNoMoreInteractions(mMockNative, mockCallback, mockPublishSessionCallback); 2427 } 2428 2429 /** 2430 * Validate that a NoOp transaction (i.e. a callback from HAL which doesn't 2431 * require any action except clearing up state) actually cleans up its state 2432 * (and does nothing else). 2433 */ 2434 @Test 2435 public void testNoOpTransaction() throws Exception { 2436 final int clientId = 1294; 2437 final int uid = 1000; 2438 final int pid = 2000; 2439 final String callingPackage = "com.google.somePackage"; 2440 2441 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2442 2443 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2444 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2445 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2446 IWifiAwareDiscoverySessionCallback.class); 2447 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2448 2449 mDut.enableUsage(); 2450 mMockLooper.dispatchAll(); 2451 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2452 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2453 mMockLooper.dispatchAll(); 2454 2455 // (1) connect (no response) 2456 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2457 mMockLooper.dispatchAll(); 2458 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2459 eq(false), eq(true)); 2460 2461 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2462 } 2463 2464 /** 2465 * Validate that getting callbacks from HAL with unknown (expired) 2466 * transaction ID or invalid publish/subscribe ID session doesn't have any 2467 * impact. 2468 */ 2469 @Test 2470 public void testInvalidCallbackIdParameters() throws Exception { 2471 final int pubSubId = 1235; 2472 final int clientId = 132; 2473 final int uid = 1000; 2474 final int pid = 2000; 2475 final String callingPackage = "com.google.somePackage"; 2476 2477 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2478 2479 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2480 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2481 InOrder inOrder = inOrder(mMockNative, mockCallback); 2482 2483 mDut.enableUsage(); 2484 mMockLooper.dispatchAll(); 2485 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2486 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2487 mMockLooper.dispatchAll(); 2488 2489 // (1) connect and succeed 2490 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2491 mMockLooper.dispatchAll(); 2492 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2493 eq(false), eq(true)); 2494 short transactionIdConfig = transactionId.getValue(); 2495 mDut.onConfigSuccessResponse(transactionIdConfig); 2496 mMockLooper.dispatchAll(); 2497 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2498 2499 // (2) use the same transaction ID to send a bunch of other responses 2500 mDut.onConfigSuccessResponse(transactionIdConfig); 2501 mDut.onConfigFailedResponse(transactionIdConfig, -1); 2502 mDut.onSessionConfigFailResponse(transactionIdConfig, true, -1); 2503 mDut.onMessageSendQueuedSuccessResponse(transactionIdConfig); 2504 mDut.onMessageSendQueuedFailResponse(transactionIdConfig, -1); 2505 mDut.onSessionConfigFailResponse(transactionIdConfig, false, -1); 2506 mDut.onMatchNotification(-1, -1, new byte[0], new byte[0], new byte[0]); 2507 mDut.onSessionTerminatedNotification(-1, -1, true); 2508 mDut.onSessionTerminatedNotification(-1, -1, false); 2509 mDut.onMessageReceivedNotification(-1, -1, new byte[0], new byte[0]); 2510 mDut.onSessionConfigSuccessResponse(transactionIdConfig, true, pubSubId); 2511 mDut.onSessionConfigSuccessResponse(transactionIdConfig, false, pubSubId); 2512 mMockLooper.dispatchAll(); 2513 2514 verifyNoMoreInteractions(mMockNative, mockCallback); 2515 } 2516 2517 /** 2518 * Validate that trying to update-subscribe on a publish session fails. 2519 */ 2520 @Test 2521 public void testSubscribeOnPublishSessionType() throws Exception { 2522 final int clientId = 188; 2523 final int uid = 1000; 2524 final int pid = 2000; 2525 final String callingPackage = "com.google.somePackage"; 2526 final int publishId = 25; 2527 2528 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2529 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2530 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2531 2532 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2533 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2534 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2535 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2536 IWifiAwareDiscoverySessionCallback.class); 2537 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2538 2539 mDut.enableUsage(); 2540 mMockLooper.dispatchAll(); 2541 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2542 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2543 mMockLooper.dispatchAll(); 2544 2545 // (1) connect 2546 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2547 mMockLooper.dispatchAll(); 2548 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest), 2549 eq(false), eq(true)); 2550 mDut.onConfigSuccessResponse(transactionId.getValue()); 2551 mMockLooper.dispatchAll(); 2552 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2553 2554 // (2) publish 2555 mDut.publish(clientId, publishConfig, mockSessionCallback); 2556 mMockLooper.dispatchAll(); 2557 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2558 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); 2559 mMockLooper.dispatchAll(); 2560 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2561 2562 // (3) update-subscribe -> failure 2563 mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); 2564 mMockLooper.dispatchAll(); 2565 inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 2566 2567 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2568 } 2569 2570 /** 2571 * Validate that trying to (re)subscribe on a publish session or (re)publish 2572 * on a subscribe session fails. 2573 */ 2574 @Test 2575 public void testPublishOnSubscribeSessionType() throws Exception { 2576 final int clientId = 188; 2577 final int uid = 1000; 2578 final int pid = 2000; 2579 final String callingPackage = "com.google.somePackage"; 2580 final int subscribeId = 25; 2581 2582 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2583 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2584 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); 2585 2586 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2587 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2588 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2589 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2590 IWifiAwareDiscoverySessionCallback.class); 2591 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2592 2593 mDut.enableUsage(); 2594 mMockLooper.dispatchAll(); 2595 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2596 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2597 mMockLooper.dispatchAll(); 2598 2599 // (1) connect 2600 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2601 mMockLooper.dispatchAll(); 2602 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2603 eq(configRequest), eq(false), eq(true)); 2604 mDut.onConfigSuccessResponse(transactionId.getValue()); 2605 mMockLooper.dispatchAll(); 2606 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2607 2608 // (2) subscribe 2609 mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); 2610 mMockLooper.dispatchAll(); 2611 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeConfig)); 2612 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); 2613 mMockLooper.dispatchAll(); 2614 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2615 2616 // (3) update-publish -> error 2617 mDut.updatePublish(clientId, sessionId.getValue(), publishConfig); 2618 mMockLooper.dispatchAll(); 2619 inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INTERNAL_FAILURE); 2620 2621 verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback); 2622 } 2623 2624 /** 2625 * Validate that the session ID increments monotonically 2626 */ 2627 @Test 2628 public void testSessionIdIncrement() throws Exception { 2629 final int clientId = 188; 2630 final int uid = 1000; 2631 final int pid = 2000; 2632 final String callingPackage = "com.google.somePackage"; 2633 int loopCount = 100; 2634 2635 ConfigRequest configRequest = new ConfigRequest.Builder().build(); 2636 PublishConfig publishConfig = new PublishConfig.Builder().build(); 2637 2638 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 2639 ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); 2640 IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); 2641 IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( 2642 IWifiAwareDiscoverySessionCallback.class); 2643 InOrder inOrder = inOrder(mMockNative, mockCallback, mockSessionCallback); 2644 2645 mDut.enableUsage(); 2646 mMockLooper.dispatchAll(); 2647 inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); 2648 mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); 2649 mMockLooper.dispatchAll(); 2650 2651 // (1) connect 2652 mDut.connect(clientId, uid, pid, callingPackage, mockCallback, configRequest, false); 2653 mMockLooper.dispatchAll(); 2654 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 2655 eq(configRequest), eq(false), eq(true)); 2656 mDut.onConfigSuccessResponse(transactionId.getValue()); 2657 mMockLooper.dispatchAll(); 2658 inOrder.verify(mockCallback).onConnectSuccess(clientId); 2659 2660 int prevId = 0; 2661 for (int i = 0; i < loopCount; ++i) { 2662 // (2) publish 2663 mDut.publish(clientId, publishConfig, mockSessionCallback); 2664 mMockLooper.dispatchAll(); 2665 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishConfig)); 2666 2667 // (3) publish-success 2668 mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, i + 1); 2669 mMockLooper.dispatchAll(); 2670 inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); 2671 2672 if (i != 0) { 2673 assertTrue("Session ID incrementing", sessionId.getValue() > prevId); 2674 } 2675 prevId = sessionId.getValue(); 2676 } 2677 } 2678 2679 /* 2680 * Tests of internal state of WifiAwareStateManager: very limited (not usually 2681 * a good idea). However, these test that the internal state is cleaned-up 2682 * appropriately. Alternatively would cause issues with memory leaks or 2683 * information leak between sessions. 2684 */ 2685 2686 /** 2687 * Utility routine used to validate that the internal state is cleaned-up 2688 * after a client is disconnected. To be used in every test which terminates 2689 * a client. 2690 * 2691 * @param clientId The ID of the client which should be deleted. 2692 */ 2693 private void validateInternalClientInfoCleanedUp(int clientId) throws Exception { 2694 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2695 collector.checkThat("Client record not cleared up for clientId=" + clientId, client, 2696 nullValue()); 2697 } 2698 2699 /** 2700 * Utility routine used to validate that the internal state is cleaned-up 2701 * (deleted) after a session is terminated through API (not callback!). To 2702 * be used in every test which terminates a session. 2703 * 2704 * @param clientId The ID of the client containing the session. 2705 * @param sessionId The ID of the terminated session. 2706 */ 2707 private void validateInternalSessionInfoCleanedUp(int clientId, int sessionId) 2708 throws Exception { 2709 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2710 collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); 2711 WifiAwareDiscoverySessionState session = getInternalSessionState(client, sessionId); 2712 collector.checkThat("Client record not cleaned-up for sessionId=" + sessionId, session, 2713 nullValue()); 2714 } 2715 2716 /** 2717 * Utility routine used to validate that the internal state is cleaned-up 2718 * (deleted) correctly. Checks that a specific client has no sessions 2719 * attached to it. 2720 * 2721 * @param clientId The ID of the client which we want to check. 2722 */ 2723 private void validateInternalNoSessions(int clientId) throws Exception { 2724 WifiAwareClientState client = getInternalClientState(mDut, clientId); 2725 collector.checkThat("Client record exists clientId=" + clientId, client, notNullValue()); 2726 2727 Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); 2728 field.setAccessible(true); 2729 @SuppressWarnings("unchecked") 2730 SparseArray<WifiAwareDiscoverySessionState> sessions = 2731 (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); 2732 2733 collector.checkThat("No sessions exist for clientId=" + clientId, sessions.size(), 2734 equalTo(0)); 2735 } 2736 2737 /** 2738 * Validates that the broadcast sent on Aware status change is correct. 2739 * 2740 * @param expectedEnabled The expected change status - i.e. are we expected 2741 * to announce that Aware is enabled (true) or disabled (false). 2742 */ 2743 private void validateCorrectAwareStatusChangeBroadcast(InOrder inOrder, 2744 boolean expectedEnabled) { 2745 ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); 2746 2747 inOrder.verify(mMockContext).sendBroadcastAsUser(intent.capture(), eq(UserHandle.ALL)); 2748 2749 collector.checkThat("intent action", intent.getValue().getAction(), 2750 equalTo(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED)); 2751 } 2752 2753 /* 2754 * Utilities 2755 */ 2756 private void dumpDut(String prefix) { 2757 StringWriter sw = new StringWriter(); 2758 mDut.dump(null, new PrintWriter(sw), null); 2759 Log.e("WifiAwareStateManagerTest", prefix + sw.toString()); 2760 } 2761 2762 private static void installMocksInStateManager(WifiAwareStateManager awareStateManager, 2763 WifiAwareRttStateManager mockRtt, WifiAwareDataPathStateManager mockDpMgr) 2764 throws Exception { 2765 Field field = WifiAwareStateManager.class.getDeclaredField("mRtt"); 2766 field.setAccessible(true); 2767 field.set(awareStateManager, mockRtt); 2768 2769 field = WifiAwareStateManager.class.getDeclaredField("mDataPathMgr"); 2770 field.setAccessible(true); 2771 field.set(awareStateManager, mockDpMgr); 2772 } 2773 2774 private static WifiAwareClientState getInternalClientState(WifiAwareStateManager dut, 2775 int clientId) throws Exception { 2776 Field field = WifiAwareStateManager.class.getDeclaredField("mClients"); 2777 field.setAccessible(true); 2778 @SuppressWarnings("unchecked") 2779 SparseArray<WifiAwareClientState> clients = (SparseArray<WifiAwareClientState>) field.get( 2780 dut); 2781 2782 return clients.get(clientId); 2783 } 2784 2785 private static WifiAwareDiscoverySessionState getInternalSessionState( 2786 WifiAwareClientState client, int sessionId) throws Exception { 2787 Field field = WifiAwareClientState.class.getDeclaredField("mSessions"); 2788 field.setAccessible(true); 2789 @SuppressWarnings("unchecked") 2790 SparseArray<WifiAwareDiscoverySessionState> sessions = 2791 (SparseArray<WifiAwareDiscoverySessionState>) field.get(client); 2792 2793 return sessions.get(sessionId); 2794 } 2795 2796 private void validateInternalSendMessageQueuesCleanedUp(int messageId) throws Exception { 2797 Field field = WifiAwareStateManager.class.getDeclaredField("mSm"); 2798 field.setAccessible(true); 2799 WifiAwareStateManager.WifiAwareStateMachine sm = 2800 (WifiAwareStateManager.WifiAwareStateMachine) field.get(mDut); 2801 2802 field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( 2803 "mHostQueuedSendMessages"); 2804 field.setAccessible(true); 2805 SparseArray<Message> hostQueuedSendMessages = (SparseArray<Message>) field.get(sm); 2806 2807 field = WifiAwareStateManager.WifiAwareStateMachine.class.getDeclaredField( 2808 "mFwQueuedSendMessages"); 2809 field.setAccessible(true); 2810 Map<Short, Message> fwQueuedSendMessages = (Map<Short, Message>) field.get(sm); 2811 2812 for (int i = 0; i < hostQueuedSendMessages.size(); ++i) { 2813 Message msg = hostQueuedSendMessages.valueAt(i); 2814 if (msg.getData().getInt("message_id") == messageId) { 2815 collector.checkThat( 2816 "Message not cleared-up from host queue. Message ID=" + messageId, msg, 2817 nullValue()); 2818 } 2819 } 2820 2821 for (Message msg: fwQueuedSendMessages.values()) { 2822 if (msg.getData().getInt("message_id") == messageId) { 2823 collector.checkThat( 2824 "Message not cleared-up from firmware queue. Message ID=" + messageId, msg, 2825 nullValue()); 2826 } 2827 } 2828 } 2829 2830 private static Capabilities getCapabilities() { 2831 Capabilities cap = new Capabilities(); 2832 cap.maxConcurrentAwareClusters = 1; 2833 cap.maxPublishes = 2; 2834 cap.maxSubscribes = 2; 2835 cap.maxServiceNameLen = 255; 2836 cap.maxMatchFilterLen = 255; 2837 cap.maxTotalMatchFilterLen = 255; 2838 cap.maxServiceSpecificInfoLen = 255; 2839 cap.maxExtendedServiceSpecificInfoLen = 255; 2840 cap.maxNdiInterfaces = 1; 2841 cap.maxNdpSessions = 1; 2842 cap.maxAppInfoLen = 255; 2843 cap.maxQueuedTransmitMessages = 6; 2844 return cap; 2845 } 2846} 2847 2848