Home | History | Annotate | Download | only in cts
      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