1 /* 2 * Copyright (C) 2017 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 17 package android.net.wifi.aware.cts; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.location.LocationManager; 24 import android.net.ConnectivityManager; 25 import android.net.MacAddress; 26 import android.net.NetworkCapabilities; 27 import android.net.NetworkRequest; 28 import android.net.wifi.WifiManager; 29 import android.net.wifi.aware.AttachCallback; 30 import android.net.wifi.aware.Characteristics; 31 import android.net.wifi.aware.DiscoverySessionCallback; 32 import android.net.wifi.aware.IdentityChangedListener; 33 import android.net.wifi.aware.PeerHandle; 34 import android.net.wifi.aware.PublishConfig; 35 import android.net.wifi.aware.PublishDiscoverySession; 36 import android.net.wifi.aware.SubscribeConfig; 37 import android.net.wifi.aware.SubscribeDiscoverySession; 38 import android.net.wifi.aware.WifiAwareManager; 39 import android.net.wifi.aware.WifiAwareSession; 40 import android.os.Handler; 41 import android.os.HandlerThread; 42 import android.test.AndroidTestCase; 43 44 import java.util.ArrayDeque; 45 import java.util.ArrayList; 46 import java.util.HashSet; 47 import java.util.List; 48 import java.util.Set; 49 import java.util.concurrent.CountDownLatch; 50 import java.util.concurrent.TimeUnit; 51 52 /** 53 * Wi-Fi Aware CTS test suite: single device testing. Performs tests on a single 54 * device to validate Wi-Fi Aware. 55 */ 56 public class SingleDeviceTest extends AndroidTestCase { 57 private static final String TAG = "WifiAwareCtsTests"; 58 59 // wait for Wi-Fi Aware to become available 60 static private final int WAIT_FOR_AWARE_CHANGE_SECS = 10; 61 62 private final Object mLock = new Object(); 63 private final HandlerThread mHandlerThread = new HandlerThread("SingleDeviceTest"); 64 private final Handler mHandler; 65 { 66 mHandlerThread.start(); 67 mHandler = new Handler(mHandlerThread.getLooper()); 68 } 69 70 private WifiAwareManager mWifiAwareManager; 71 private WifiManager mWifiManager; 72 private WifiManager.WifiLock mWifiLock; 73 private ConnectivityManager mConnectivityManager; 74 75 // used to store any WifiAwareSession allocated during tests - will clean-up after tests 76 private List<WifiAwareSession> mSessions = new ArrayList<>(); 77 78 private class WifiAwareBroadcastReceiver extends BroadcastReceiver { 79 private CountDownLatch mBlocker = new CountDownLatch(1); 80 81 @Override 82 public void onReceive(Context context, Intent intent) { 83 if (WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED.equals(intent.getAction())) { 84 mBlocker.countDown(); 85 } 86 } 87 88 boolean waitForStateChange() throws InterruptedException { 89 return mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS); 90 } 91 } 92 93 private class AttachCallbackTest extends AttachCallback { 94 static final int ATTACHED = 0; 95 static final int ATTACH_FAILED = 1; 96 static final int ERROR = 2; // no callback: timeout, interruption 97 98 private CountDownLatch mBlocker = new CountDownLatch(1); 99 private int mCallbackCalled = ERROR; // garbage init 100 private WifiAwareSession mSession = null; 101 102 @Override 103 public void onAttached(WifiAwareSession session) { 104 mCallbackCalled = ATTACHED; 105 mSession = session; 106 synchronized (mLock) { 107 mSessions.add(session); 108 } 109 mBlocker.countDown(); 110 } 111 112 @Override 113 public void onAttachFailed() { 114 mCallbackCalled = ATTACH_FAILED; 115 mBlocker.countDown(); 116 } 117 118 /** 119 * Waits for any of the callbacks to be called - or an error (timeout, interruption). 120 * Returns one of the ATTACHED, ATTACH_FAILED, or ERROR values. 121 */ 122 int waitForAnyCallback() { 123 try { 124 boolean noTimeout = mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS); 125 if (noTimeout) { 126 return mCallbackCalled; 127 } else { 128 return ERROR; 129 } 130 } catch (InterruptedException e) { 131 return ERROR; 132 } 133 } 134 135 /** 136 * Access the session created by a callback. Only useful to be called after calling 137 * waitForAnyCallback() and getting the ATTACHED code back. 138 */ 139 WifiAwareSession getSession() { 140 return mSession; 141 } 142 } 143 144 private class IdentityChangedListenerTest extends IdentityChangedListener { 145 private CountDownLatch mBlocker = new CountDownLatch(1); 146 private byte[] mMac = null; 147 148 @Override 149 public void onIdentityChanged(byte[] mac) { 150 mMac = mac; 151 mBlocker.countDown(); 152 } 153 154 /** 155 * Waits for the listener callback to be called - or an error (timeout, interruption). 156 * Returns true on callback called, false on error (timeout, interruption). 157 */ 158 boolean waitForListener() { 159 try { 160 return mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS); 161 } catch (InterruptedException e) { 162 return false; 163 } 164 } 165 166 /** 167 * Returns the MAC address of the discovery interface supplied to the triggered callback. 168 */ 169 byte[] getMac() { 170 return mMac; 171 } 172 } 173 174 private class DiscoverySessionCallbackTest extends DiscoverySessionCallback { 175 static final int ON_PUBLISH_STARTED = 0; 176 static final int ON_SUBSCRIBE_STARTED = 1; 177 static final int ON_SESSION_CONFIG_UPDATED = 2; 178 static final int ON_SESSION_CONFIG_FAILED = 3; 179 static final int ON_SESSION_TERMINATED = 4; 180 static final int ON_SERVICE_DISCOVERED = 5; 181 static final int ON_MESSAGE_SEND_SUCCEEDED = 6; 182 static final int ON_MESSAGE_SEND_FAILED = 7; 183 static final int ON_MESSAGE_RECEIVED = 8; 184 185 private final Object mLocalLock = new Object(); 186 187 private CountDownLatch mBlocker; 188 private int mCurrentWaitForCallback; 189 private ArrayDeque<Integer> mCallbackQueue = new ArrayDeque<>(); 190 191 private PublishDiscoverySession mPublishDiscoverySession; 192 private SubscribeDiscoverySession mSubscribeDiscoverySession; 193 194 private void processCallback(int callback) { 195 synchronized (mLocalLock) { 196 if (mBlocker != null && mCurrentWaitForCallback == callback) { 197 mBlocker.countDown(); 198 } else { 199 mCallbackQueue.addLast(callback); 200 } 201 } 202 } 203 204 @Override 205 public void onPublishStarted(PublishDiscoverySession session) { 206 mPublishDiscoverySession = session; 207 processCallback(ON_PUBLISH_STARTED); 208 } 209 210 @Override 211 public void onSubscribeStarted(SubscribeDiscoverySession session) { 212 mSubscribeDiscoverySession = session; 213 processCallback(ON_SUBSCRIBE_STARTED); 214 } 215 216 @Override 217 public void onSessionConfigUpdated() { 218 processCallback(ON_SESSION_CONFIG_UPDATED); 219 } 220 221 @Override 222 public void onSessionConfigFailed() { 223 processCallback(ON_SESSION_CONFIG_FAILED); 224 } 225 226 @Override 227 public void onSessionTerminated() { 228 processCallback(ON_SESSION_TERMINATED); 229 } 230 231 @Override 232 public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, 233 List<byte[]> matchFilter) { 234 processCallback(ON_SERVICE_DISCOVERED); 235 } 236 237 @Override 238 public void onMessageSendSucceeded(int messageId) { 239 processCallback(ON_MESSAGE_SEND_SUCCEEDED); 240 } 241 242 @Override 243 public void onMessageSendFailed(int messageId) { 244 processCallback(ON_MESSAGE_SEND_FAILED); 245 } 246 247 @Override 248 public void onMessageReceived(PeerHandle peerHandle, byte[] message) { 249 processCallback(ON_MESSAGE_RECEIVED); 250 } 251 252 /** 253 * Wait for the specified callback - any of the ON_* constants. Returns a true 254 * on success (specified callback triggered) or false on failure (timed-out or 255 * interrupted while waiting for the requested callback). 256 * 257 * Note: other callbacks happening while while waiting for the specified callback will 258 * be queued. 259 */ 260 boolean waitForCallback(int callback) { 261 return waitForCallback(callback, WAIT_FOR_AWARE_CHANGE_SECS); 262 } 263 264 /** 265 * Wait for the specified callback - any of the ON_* constants. Returns a true 266 * on success (specified callback triggered) or false on failure (timed-out or 267 * interrupted while waiting for the requested callback). 268 * 269 * Same as waitForCallback(int callback) execpt that allows specifying a custom timeout. 270 * The default timeout is a short value expected to be sufficient for all behaviors which 271 * should happen relatively quickly. Specifying a custom timeout should only be done for 272 * those cases which are known to take a specific longer period of time. 273 * 274 * Note: other callbacks happening while while waiting for the specified callback will 275 * be queued. 276 */ 277 boolean waitForCallback(int callback, int timeoutSec) { 278 synchronized (mLocalLock) { 279 boolean found = mCallbackQueue.remove(callback); 280 if (found) { 281 return true; 282 } 283 284 mCurrentWaitForCallback = callback; 285 mBlocker = new CountDownLatch(1); 286 } 287 288 try { 289 return mBlocker.await(timeoutSec, TimeUnit.SECONDS); 290 } catch (InterruptedException e) { 291 return false; 292 } 293 } 294 295 /** 296 * Indicates whether the specified callback (any of the ON_* constants) has already 297 * happened and in the queue. Useful when the order of events is important. 298 */ 299 boolean hasCallbackAlreadyHappened(int callback) { 300 synchronized (mLocalLock) { 301 return mCallbackQueue.contains(callback); 302 } 303 } 304 305 /** 306 * Returns the last created publish discovery session. 307 */ 308 PublishDiscoverySession getPublishDiscoverySession() { 309 PublishDiscoverySession session = mPublishDiscoverySession; 310 mPublishDiscoverySession = null; 311 return session; 312 } 313 314 /** 315 * Returns the last created subscribe discovery session. 316 */ 317 SubscribeDiscoverySession getSubscribeDiscoverySession() { 318 SubscribeDiscoverySession session = mSubscribeDiscoverySession; 319 mSubscribeDiscoverySession = null; 320 return session; 321 } 322 } 323 324 private class NetworkCallbackTest extends ConnectivityManager.NetworkCallback { 325 private CountDownLatch mBlocker = new CountDownLatch(1); 326 327 @Override 328 public void onUnavailable() { 329 mBlocker.countDown(); 330 } 331 332 /** 333 * Wait for the onUnavailable() callback to be triggered. Returns true if triggered, 334 * otherwise (timed-out, interrupted) returns false. 335 */ 336 boolean waitForOnUnavailable() { 337 try { 338 return mBlocker.await(WAIT_FOR_AWARE_CHANGE_SECS, TimeUnit.SECONDS); 339 } catch (InterruptedException e) { 340 return false; 341 } 342 } 343 } 344 345 @Override 346 protected void setUp() throws Exception { 347 super.setUp(); 348 349 if (!TestUtils.shouldTestWifiAware(getContext())) { 350 return; 351 } 352 353 assertTrue("Wi-Fi Aware requires Location to be Enabled", 354 ((LocationManager) getContext().getSystemService( 355 Context.LOCATION_SERVICE)).isLocationEnabled()); 356 357 mWifiAwareManager = (WifiAwareManager) getContext().getSystemService( 358 Context.WIFI_AWARE_SERVICE); 359 assertNotNull("Wi-Fi Aware Manager", mWifiAwareManager); 360 361 mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE); 362 assertNotNull("Wi-Fi Manager", mWifiManager); 363 mWifiLock = mWifiManager.createWifiLock(TAG); 364 mWifiLock.acquire(); 365 if (!mWifiManager.isWifiEnabled()) { 366 mWifiManager.setWifiEnabled(true); 367 } 368 369 mConnectivityManager = (ConnectivityManager) getContext().getSystemService( 370 Context.CONNECTIVITY_SERVICE); 371 assertNotNull("Connectivity Manager", mConnectivityManager); 372 373 IntentFilter intentFilter = new IntentFilter(); 374 intentFilter.addAction(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); 375 WifiAwareBroadcastReceiver receiver = new WifiAwareBroadcastReceiver(); 376 mContext.registerReceiver(receiver, intentFilter); 377 if (!mWifiAwareManager.isAvailable()) { 378 assertTrue("Timeout waiting for Wi-Fi Aware to change status", 379 receiver.waitForStateChange()); 380 assertTrue("Wi-Fi Aware is not available (should be)", mWifiAwareManager.isAvailable()); 381 } 382 } 383 384 @Override 385 protected void tearDown() throws Exception { 386 if (!TestUtils.shouldTestWifiAware(getContext())) { 387 super.tearDown(); 388 return; 389 } 390 391 synchronized (mLock) { 392 for (WifiAwareSession session : mSessions) { 393 // no damage from destroying twice (i.e. ok if test cleaned up after itself already) 394 session.close(); 395 } 396 mSessions.clear(); 397 } 398 399 super.tearDown(); 400 } 401 402 /** 403 * Validate: 404 * - Characteristics are available 405 * - Characteristics values are legitimate. Not in the CDD. However, the tested values are 406 * based on the Wi-Fi Aware protocol. 407 */ 408 public void testCharacteristics() { 409 if (!TestUtils.shouldTestWifiAware(getContext())) { 410 return; 411 } 412 413 Characteristics characteristics = mWifiAwareManager.getCharacteristics(); 414 assertNotNull("Wi-Fi Aware characteristics are null", characteristics); 415 assertEquals("Service Name Length", characteristics.getMaxServiceNameLength(), 255); 416 assertEquals("Service Specific Information Length", 417 characteristics.getMaxServiceSpecificInfoLength(), 255); 418 assertEquals("Match Filter Length", characteristics.getMaxMatchFilterLength(), 255); 419 } 420 421 /** 422 * Validate that on Wi-Fi Aware availability change we get a broadcast + the API returns 423 * correct status. 424 */ 425 public void testAvailabilityStatusChange() throws Exception { 426 if (!TestUtils.shouldTestWifiAware(getContext())) { 427 return; 428 } 429 430 IntentFilter intentFilter = new IntentFilter(); 431 intentFilter.addAction(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); 432 433 // 1. Disable Wi-Fi 434 WifiAwareBroadcastReceiver receiver1 = new WifiAwareBroadcastReceiver(); 435 mContext.registerReceiver(receiver1, intentFilter); 436 mWifiManager.setWifiEnabled(false); 437 438 assertTrue("Timeout waiting for Wi-Fi Aware to change status", 439 receiver1.waitForStateChange()); 440 assertFalse("Wi-Fi Aware is available (should not be)", mWifiAwareManager.isAvailable()); 441 442 // 2. Enable Wi-Fi 443 WifiAwareBroadcastReceiver receiver2 = new WifiAwareBroadcastReceiver(); 444 mContext.registerReceiver(receiver2, intentFilter); 445 mWifiManager.setWifiEnabled(true); 446 447 assertTrue("Timeout waiting for Wi-Fi Aware to change status", 448 receiver2.waitForStateChange()); 449 assertTrue("Wi-Fi Aware is not available (should be)", mWifiAwareManager.isAvailable()); 450 } 451 452 /** 453 * Validate that can attach to Wi-Fi Aware. 454 */ 455 public void testAttachNoIdentity() { 456 if (!TestUtils.shouldTestWifiAware(getContext())) { 457 return; 458 } 459 460 WifiAwareSession session = attachAndGetSession(); 461 session.close(); 462 } 463 464 /** 465 * Validate that can attach to Wi-Fi Aware and get identity information. Use the identity 466 * information to validate that MAC address changes on every attach. 467 * 468 * Note: relies on no other entity using Wi-Fi Aware during the CTS test. Since if it is used 469 * then the attach/destroy will not correspond to enable/disable and will not result in a new 470 * MAC address being generated. 471 */ 472 public void testAttachDiscoveryAddressChanges() { 473 if (!TestUtils.shouldTestWifiAware(getContext())) { 474 return; 475 } 476 477 final int numIterations = 10; 478 Set<TestUtils.MacWrapper> macs = new HashSet<>(); 479 480 for (int i = 0; i < numIterations; ++i) { 481 AttachCallbackTest attachCb = new AttachCallbackTest(); 482 IdentityChangedListenerTest identityL = new IdentityChangedListenerTest(); 483 mWifiAwareManager.attach(attachCb, identityL, mHandler); 484 assertEquals("Wi-Fi Aware attach: iteration " + i, AttachCallbackTest.ATTACHED, 485 attachCb.waitForAnyCallback()); 486 assertTrue("Wi-Fi Aware attach: iteration " + i, identityL.waitForListener()); 487 488 WifiAwareSession session = attachCb.getSession(); 489 assertNotNull("Wi-Fi Aware session: iteration " + i, session); 490 491 byte[] mac = identityL.getMac(); 492 assertNotNull("Wi-Fi Aware discovery MAC: iteration " + i, mac); 493 494 session.close(); 495 496 macs.add(new TestUtils.MacWrapper(mac)); 497 } 498 499 assertEquals("", numIterations, macs.size()); 500 } 501 502 /** 503 * Validate a successful publish discovery session lifetime: publish, update publish, destroy. 504 */ 505 public void testPublishDiscoverySuccess() { 506 if (!TestUtils.shouldTestWifiAware(getContext())) { 507 return; 508 } 509 510 final String serviceName = "ValidName"; 511 512 WifiAwareSession session = attachAndGetSession(); 513 514 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 515 serviceName).build(); 516 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 517 518 // 1. publish 519 session.publish(publishConfig, discoveryCb, mHandler); 520 assertTrue("Publish started", 521 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED)); 522 PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession(); 523 assertNotNull("Publish session", discoverySession); 524 525 // 2. update-publish 526 publishConfig = new PublishConfig.Builder().setServiceName( 527 serviceName).setServiceSpecificInfo("extras".getBytes()).build(); 528 discoverySession.updatePublish(publishConfig); 529 assertTrue("Publish update", discoveryCb.waitForCallback( 530 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 531 532 // 3. destroy 533 assertFalse("Publish not terminated", discoveryCb.hasCallbackAlreadyHappened( 534 DiscoverySessionCallbackTest.ON_SESSION_TERMINATED)); 535 discoverySession.close(); 536 537 // 4. try update post-destroy: should time-out waiting for cb 538 discoverySession.updatePublish(publishConfig); 539 assertFalse("Publish update post destroy", discoveryCb.waitForCallback( 540 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 541 542 session.close(); 543 } 544 545 /** 546 * Validate that publish with a Time To Live (TTL) setting expires within the specified 547 * time (and validates that the terminate callback is triggered). 548 */ 549 public void testPublishLimitedTtlSuccess() { 550 if (!TestUtils.shouldTestWifiAware(getContext())) { 551 return; 552 } 553 554 final String serviceName = "ValidName"; 555 final int ttlSec = 5; 556 557 WifiAwareSession session = attachAndGetSession(); 558 559 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 560 serviceName).setTtlSec(ttlSec).setTerminateNotificationEnabled(true).build(); 561 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 562 563 // 1. publish 564 session.publish(publishConfig, discoveryCb, mHandler); 565 assertTrue("Publish started", 566 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED)); 567 PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession(); 568 assertNotNull("Publish session", discoverySession); 569 570 // 2. wait for terminate within 'ttlSec'. 571 assertTrue("Publish terminated", 572 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SESSION_TERMINATED, 573 ttlSec + 5)); 574 575 // 3. try update post-termination: should time-out waiting for cb 576 publishConfig = new PublishConfig.Builder().setServiceName( 577 serviceName).setServiceSpecificInfo("extras".getBytes()).build(); 578 discoverySession.updatePublish(publishConfig); 579 assertFalse("Publish update post terminate", discoveryCb.waitForCallback( 580 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 581 582 session.close(); 583 } 584 585 /** 586 * Validate a successful subscribe discovery session lifetime: subscribe, update subscribe, 587 * destroy. 588 */ 589 public void testSubscribeDiscoverySuccess() { 590 if (!TestUtils.shouldTestWifiAware(getContext())) { 591 return; 592 } 593 594 final String serviceName = "ValidName"; 595 596 WifiAwareSession session = attachAndGetSession(); 597 598 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName( 599 serviceName).build(); 600 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 601 602 // 1. subscribe 603 session.subscribe(subscribeConfig, discoveryCb, mHandler); 604 assertTrue("Subscribe started", 605 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SUBSCRIBE_STARTED)); 606 SubscribeDiscoverySession discoverySession = discoveryCb.getSubscribeDiscoverySession(); 607 assertNotNull("Subscribe session", discoverySession); 608 609 // 2. update-subscribe 610 subscribeConfig = new SubscribeConfig.Builder().setServiceName( 611 serviceName).setServiceSpecificInfo("extras".getBytes()).build(); 612 discoverySession.updateSubscribe(subscribeConfig); 613 assertTrue("Subscribe update", discoveryCb.waitForCallback( 614 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 615 616 // 3. destroy 617 assertFalse("Subscribe not terminated", discoveryCb.hasCallbackAlreadyHappened( 618 DiscoverySessionCallbackTest.ON_SESSION_TERMINATED)); 619 discoverySession.close(); 620 621 // 4. try update post-destroy: should time-out waiting for cb 622 discoverySession.updateSubscribe(subscribeConfig); 623 assertFalse("Subscribe update post destroy", discoveryCb.waitForCallback( 624 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 625 626 session.close(); 627 } 628 629 /** 630 * Validate that subscribe with a Time To Live (TTL) setting expires within the specified 631 * time (and validates that the terminate callback is triggered). 632 */ 633 public void testSubscribeLimitedTtlSuccess() { 634 if (!TestUtils.shouldTestWifiAware(getContext())) { 635 return; 636 } 637 638 final String serviceName = "ValidName"; 639 final int ttlSec = 5; 640 641 WifiAwareSession session = attachAndGetSession(); 642 643 SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName( 644 serviceName).setTtlSec(ttlSec).setTerminateNotificationEnabled(true).build(); 645 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 646 647 // 1. subscribe 648 session.subscribe(subscribeConfig, discoveryCb, mHandler); 649 assertTrue("Subscribe started", 650 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SUBSCRIBE_STARTED)); 651 SubscribeDiscoverySession discoverySession = discoveryCb.getSubscribeDiscoverySession(); 652 assertNotNull("Subscribe session", discoverySession); 653 654 // 2. wait for terminate within 'ttlSec'. 655 assertTrue("Subscribe terminated", 656 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_SESSION_TERMINATED, 657 ttlSec + 5)); 658 659 // 3. try update post-termination: should time-out waiting for cb 660 subscribeConfig = new SubscribeConfig.Builder().setServiceName( 661 serviceName).setServiceSpecificInfo("extras".getBytes()).build(); 662 discoverySession.updateSubscribe(subscribeConfig); 663 assertFalse("Subscribe update post terminate", discoveryCb.waitForCallback( 664 DiscoverySessionCallbackTest.ON_SESSION_CONFIG_UPDATED)); 665 666 session.close(); 667 } 668 669 /** 670 * Test the send message flow. Since testing single device cannot send to a real peer - 671 * validate that sending to a bogus peer fails. 672 */ 673 public void testSendMessageFail() { 674 if (!TestUtils.shouldTestWifiAware(getContext())) { 675 return; 676 } 677 678 WifiAwareSession session = attachAndGetSession(); 679 680 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 681 "ValidName").build(); 682 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 683 684 // 1. publish 685 session.publish(publishConfig, discoveryCb, mHandler); 686 assertTrue("Publish started", 687 discoveryCb.waitForCallback(DiscoverySessionCallbackTest.ON_PUBLISH_STARTED)); 688 PublishDiscoverySession discoverySession = discoveryCb.getPublishDiscoverySession(); 689 assertNotNull("Publish session", discoverySession); 690 691 // 2. send a message with a null peer-handle - expect exception 692 try { 693 discoverySession.sendMessage(null, -1290, "some message".getBytes()); 694 fail("Expected IllegalArgumentException"); 695 } catch (IllegalArgumentException e) { 696 // empty 697 } 698 699 discoverySession.close(); 700 session.close(); 701 } 702 703 /** 704 * Request an Aware data-path (open) as a Responder with an arbitrary peer MAC address. Validate 705 * that times-out. 706 */ 707 public void testDataPathOpenOutOfBandFail() { 708 if (!TestUtils.shouldTestWifiAware(getContext())) { 709 return; 710 } 711 MacAddress mac = MacAddress.fromString("00:01:02:03:04:05"); 712 713 WifiAwareSession session = attachAndGetSession(); 714 715 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 716 "ValidName").build(); 717 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 718 NetworkCallbackTest networkCb = new NetworkCallbackTest(); 719 720 // 1. request an AWARE network 721 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 722 NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier( 723 session.createNetworkSpecifierOpen( 724 WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, 725 mac.toByteArray())).build(); 726 mConnectivityManager.requestNetwork(nr, networkCb, 2000); 727 assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable()); 728 729 session.close(); 730 } 731 732 /** 733 * Request an Aware data-path (encrypted) as a Responder with an arbitrary peer MAC address. 734 * Validate that times-out. 735 */ 736 public void testDataPathPassphraseOutOfBandFail() { 737 if (!TestUtils.shouldTestWifiAware(getContext())) { 738 return; 739 } 740 MacAddress mac = MacAddress.fromString("00:01:02:03:04:05"); 741 742 WifiAwareSession session = attachAndGetSession(); 743 744 PublishConfig publishConfig = new PublishConfig.Builder().setServiceName( 745 "ValidName").build(); 746 DiscoverySessionCallbackTest discoveryCb = new DiscoverySessionCallbackTest(); 747 NetworkCallbackTest networkCb = new NetworkCallbackTest(); 748 749 // 1. request an AWARE network 750 NetworkRequest nr = new NetworkRequest.Builder().addTransportType( 751 NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier( 752 session.createNetworkSpecifierPassphrase( 753 WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER, mac.toByteArray(), 754 "abcdefghihk")).build(); 755 mConnectivityManager.requestNetwork(nr, networkCb, 2000); 756 assertTrue("OnUnavailable received", networkCb.waitForOnUnavailable()); 757 758 session.close(); 759 } 760 761 // local utilities 762 763 private WifiAwareSession attachAndGetSession() { 764 AttachCallbackTest attachCb = new AttachCallbackTest(); 765 mWifiAwareManager.attach(attachCb, mHandler); 766 int cbCalled = attachCb.waitForAnyCallback(); 767 assertEquals("Wi-Fi Aware attach", AttachCallbackTest.ATTACHED, cbCalled); 768 769 WifiAwareSession session = attachCb.getSession(); 770 assertNotNull("Wi-Fi Aware session", session); 771 772 return session; 773 } 774 } 775