Home | History | Annotate | Download | only in testcase
      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 com.android.cts.verifier.wifiaware.testcase;
     18 
     19 import static com.android.cts.verifier.wifiaware.CallbackUtils.CALLBACK_TIMEOUT_SEC;
     20 
     21 import android.content.Context;
     22 import android.net.ConnectivityManager;
     23 import android.net.NetworkCapabilities;
     24 import android.net.NetworkRequest;
     25 import android.net.wifi.aware.PeerHandle;
     26 import android.net.wifi.aware.PublishConfig;
     27 import android.net.wifi.aware.PublishDiscoverySession;
     28 import android.net.wifi.aware.SubscribeConfig;
     29 import android.net.wifi.aware.SubscribeDiscoverySession;
     30 import android.net.wifi.aware.WifiAwareSession;
     31 import android.util.Log;
     32 import android.util.Pair;
     33 
     34 import com.android.cts.verifier.R;
     35 import com.android.cts.verifier.wifiaware.BaseTestCase;
     36 import com.android.cts.verifier.wifiaware.CallbackUtils;
     37 
     38 import java.util.ArrayList;
     39 import java.util.Arrays;
     40 import java.util.List;
     41 
     42 /**
     43  * Test case for data-path, in-band test cases:
     44  * open/passphrase * solicited/unsolicited * publish/subscribe.
     45  *
     46  * Subscribe test sequence:
     47  * 1. Attach
     48  *    wait for results (session)
     49  * 2. Subscribe
     50  *    wait for results (subscribe session)
     51  * 3. Wait for discovery
     52  * 4. Send message
     53  *    Wait for success
     54  * 5. Wait for rx message
     55  * 6. Request network
     56  *    Wait for network
     57  * 7. Destroy session
     58  *
     59  * Publish test sequence:
     60  * 1. Attach
     61  *    wait for results (session)
     62  * 2. Publish
     63  *    wait for results (publish session)
     64  * 3. Wait for rx message
     65  * 4. Request network
     66  * 5. Send message
     67  *    Wait for success
     68  * 6. Wait for network
     69  * 7. Destroy session
     70  */
     71 public class DataPathInBandTestCase extends BaseTestCase {
     72     private static final String TAG = "DataPathInBandTestCase";
     73     private static final boolean DBG = true;
     74 
     75     private static final String SERVICE_NAME = "CtsVerifierTestService";
     76     private static final byte[] MATCH_FILTER_BYTES = "bytes used for matching".getBytes();
     77     private static final byte[] PUB_SSI = "Extra bytes in the publisher discovery".getBytes();
     78     private static final byte[] SUB_SSI = "Arbitrary bytes for the subscribe discovery".getBytes();
     79     private static final byte[] MSG_SUB_TO_PUB = "Let's talk".getBytes();
     80     private static final byte[] MSG_PUB_TO_SUB = "Ready".getBytes();
     81     private static final String PASSPHRASE = "Some super secret password";
     82     private static final int MESSAGE_ID = 1234;
     83 
     84     private boolean mIsSecurityOpen;
     85     private boolean mIsPublish;
     86     private boolean mIsUnsolicited;
     87 
     88     private final Object mLock = new Object();
     89 
     90     private String mFailureReason;
     91     private WifiAwareSession mWifiAwareSession;
     92 
     93     public DataPathInBandTestCase(Context context, boolean isSecurityOpen, boolean isPublish,
     94             boolean isUnsolicited) {
     95         super(context);
     96         mIsSecurityOpen = isSecurityOpen;
     97         mIsPublish = isPublish;
     98         mIsUnsolicited = isUnsolicited;
     99     }
    100 
    101     @Override
    102     protected boolean executeTest() throws InterruptedException {
    103         if (DBG) {
    104             Log.d(TAG,
    105                     "executeTest: mIsSecurityOpen=" + mIsSecurityOpen + ", mIsPublish=" + mIsPublish
    106                             + ", mIsUnsolicited=" + mIsUnsolicited);
    107         }
    108 
    109         // 1. attach
    110         CallbackUtils.AttachCb attachCb = new CallbackUtils.AttachCb();
    111         mWifiAwareManager.attach(attachCb, mHandler);
    112         Pair<Integer, WifiAwareSession> results = attachCb.waitForAttach();
    113         switch (results.first) {
    114             case CallbackUtils.AttachCb.TIMEOUT:
    115                 setFailureReason(mContext.getString(R.string.aware_status_attach_timeout));
    116                 Log.e(TAG, "executeTest: attach TIMEOUT");
    117                 return false;
    118             case CallbackUtils.AttachCb.ON_ATTACH_FAILED:
    119                 setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
    120                 Log.e(TAG, "executeTest: attach ON_ATTACH_FAILED");
    121                 return false;
    122         }
    123         mWifiAwareSession = results.second;
    124         if (mWifiAwareSession == null) {
    125             setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
    126             Log.e(TAG, "executeTest: attach callback succeeded but null session returned!?");
    127             return false;
    128         }
    129         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_attached));
    130         if (DBG) {
    131             Log.d(TAG, "executeTest: attach succeeded");
    132         }
    133 
    134         if (mIsPublish) {
    135             return executeTestPublisher();
    136         } else {
    137             return executeTestSubscriber();
    138         }
    139     }
    140 
    141     private void setFailureReason(String reason) {
    142         synchronized (mLock) {
    143             mFailureReason = reason;
    144         }
    145     }
    146 
    147     @Override
    148     protected String getFailureReason() {
    149         synchronized (mLock) {
    150             return mFailureReason;
    151         }
    152     }
    153 
    154     @Override
    155     protected void tearDown() {
    156         if (mWifiAwareSession != null) {
    157             mWifiAwareSession.close();
    158             mWifiAwareSession = null;
    159         }
    160         super.tearDown();
    161     }
    162 
    163     private boolean executeTestSubscriber() throws InterruptedException {
    164         if (DBG) Log.d(TAG, "executeTestSubscriber");
    165         CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();
    166 
    167         // 2. subscribe
    168         List<byte[]> matchFilter = new ArrayList<>();
    169         matchFilter.add(MATCH_FILTER_BYTES);
    170         SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
    171                 SERVICE_NAME).setServiceSpecificInfo(SUB_SSI).setMatchFilter(
    172                 matchFilter).setSubscribeType(
    173                 mIsUnsolicited ? SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE
    174                         : SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE).setTerminateNotificationEnabled(
    175                 true).build();
    176         if (DBG) Log.d(TAG, "executeTestSubscriber: subscribeConfig=" + subscribeConfig);
    177         mWifiAwareSession.subscribe(subscribeConfig, discoveryCb, mHandler);
    178 
    179         //    wait for results - subscribe session
    180         CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
    181                 CallbackUtils.DiscoveryCb.ON_SUBSCRIBE_STARTED
    182                         | CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
    183         switch (callbackData.callback) {
    184             case CallbackUtils.DiscoveryCb.TIMEOUT:
    185                 setFailureReason(mContext.getString(R.string.aware_status_subscribe_timeout));
    186                 Log.e(TAG, "executeTestSubscriber: subscribe TIMEOUT");
    187                 return false;
    188             case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
    189                 setFailureReason(mContext.getString(R.string.aware_status_subscribe_failed));
    190                 Log.e(TAG, "executeTestSubscriber: subscribe ON_SESSION_CONFIG_FAILED");
    191                 return false;
    192         }
    193         SubscribeDiscoverySession discoverySession = callbackData.subscribeDiscoverySession;
    194         if (discoverySession == null) {
    195             setFailureReason(mContext.getString(R.string.aware_status_subscribe_null_session));
    196             Log.e(TAG, "executeTestSubscriber: subscribe succeeded but null session returned");
    197             return false;
    198         }
    199         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_subscribe_started));
    200         if (DBG) Log.d(TAG, "executeTestSubscriber: subscribe succeeded");
    201 
    202         // 3. wait for discovery
    203         callbackData = discoveryCb.waitForCallbacks(
    204                 CallbackUtils.DiscoveryCb.ON_SERVICE_DISCOVERED);
    205         switch (callbackData.callback) {
    206             case CallbackUtils.DiscoveryCb.TIMEOUT:
    207                 setFailureReason(mContext.getString(R.string.aware_status_discovery_timeout));
    208                 Log.e(TAG, "executeTestSubscriber: waiting for discovery TIMEOUT");
    209                 return false;
    210         }
    211         PeerHandle peerHandle = callbackData.peerHandle;
    212         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_discovery));
    213         if (DBG) Log.d(TAG, "executeTestSubscriber: discovery");
    214 
    215         //    validate discovery parameters match
    216         if (!Arrays.equals(PUB_SSI, callbackData.serviceSpecificInfo)) {
    217             setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
    218             Log.e(TAG, "executeTestSubscriber: discovery but SSI mismatch: rx='" + new String(
    219                     callbackData.serviceSpecificInfo) + "'");
    220             return false;
    221         }
    222         if (callbackData.matchFilter.size() != 1 || !Arrays.equals(MATCH_FILTER_BYTES,
    223                 callbackData.matchFilter.get(0))) {
    224             setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
    225             StringBuffer sb = new StringBuffer();
    226             sb.append("size=").append(callbackData.matchFilter.size());
    227             for (byte[] mf: callbackData.matchFilter) {
    228                 sb.append(", e='").append(new String(mf)).append("'");
    229             }
    230             Log.e(TAG, "executeTestSubscriber: discovery but matchFilter mismatch: "
    231                     + sb.toString());
    232             return false;
    233         }
    234         if (peerHandle == null) {
    235             setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
    236             Log.e(TAG, "executeTestSubscriber: discovery but null peerHandle");
    237             return false;
    238         }
    239 
    240         // 4. send message & wait for send status
    241         discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_SUB_TO_PUB);
    242         callbackData = discoveryCb.waitForCallbacks(
    243                 CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
    244                         | CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
    245         switch (callbackData.callback) {
    246             case CallbackUtils.DiscoveryCb.TIMEOUT:
    247                 setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
    248                 Log.e(TAG, "executeTestSubscriber: send message TIMEOUT");
    249                 return false;
    250             case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
    251                 setFailureReason(mContext.getString(R.string.aware_status_send_failed));
    252                 Log.e(TAG, "executeTestSubscriber: send message ON_MESSAGE_SEND_FAILED");
    253                 return false;
    254         }
    255         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
    256         if (DBG) Log.d(TAG, "executeTestSubscriber: send message succeeded");
    257 
    258         if (callbackData.messageId != MESSAGE_ID) {
    259             setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
    260             Log.e(TAG, "executeTestSubscriber: send message message ID mismatch: "
    261                     + callbackData.messageId);
    262             return false;
    263         }
    264 
    265         // 5. wait to receive message
    266         callbackData = discoveryCb.waitForCallbacks(CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
    267         switch (callbackData.callback) {
    268             case CallbackUtils.DiscoveryCb.TIMEOUT:
    269                 setFailureReason(mContext.getString(R.string.aware_status_receive_timeout));
    270                 Log.e(TAG, "executeTestSubscriber: receive message TIMEOUT");
    271                 return false;
    272         }
    273         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
    274         if (DBG) Log.d(TAG, "executeTestSubscriber: received message");
    275 
    276         //    validate that received the expected message
    277         if (!Arrays.equals(MSG_PUB_TO_SUB, callbackData.serviceSpecificInfo)) {
    278             setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
    279             Log.e(TAG, "executeTestSubscriber: receive message message content mismatch: rx='"
    280                     + new String(callbackData.serviceSpecificInfo) + "'");
    281             return false;
    282         }
    283 
    284         // 6. request network
    285         ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
    286                 Context.CONNECTIVITY_SERVICE);
    287         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
    288                 NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
    289                 mIsSecurityOpen ? discoverySession.createNetworkSpecifierOpen(peerHandle)
    290                         : discoverySession.createNetworkSpecifierPassphrase(peerHandle,
    291                                 PASSPHRASE)).build();
    292         CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
    293         cm.requestNetwork(nr, networkCb, CALLBACK_TIMEOUT_SEC * 1000);
    294         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
    295         if (DBG) Log.d(TAG, "executeTestSubscriber: requested network");
    296         boolean networkAvailable = networkCb.waitForNetwork();
    297         cm.unregisterNetworkCallback(networkCb);
    298         if (!networkAvailable) {
    299             setFailureReason(mContext.getString(R.string.aware_status_network_failed));
    300             Log.e(TAG, "executeTestSubscriber: network request rejected - ON_UNAVAILABLE");
    301             return false;
    302         }
    303         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
    304         if (DBG) Log.d(TAG, "executeTestSubscriber: network request granted - AVAILABLE");
    305 
    306         // 7. destroy session
    307         discoverySession.close();
    308 
    309         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
    310         return true;
    311     }
    312 
    313     private boolean executeTestPublisher() throws InterruptedException {
    314         if (DBG) Log.d(TAG, "executeTestPublisher");
    315         CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();
    316 
    317         // 2. publish
    318         List<byte[]> matchFilter = new ArrayList<>();
    319         matchFilter.add(MATCH_FILTER_BYTES);
    320         PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
    321                 SERVICE_NAME).setServiceSpecificInfo(PUB_SSI).setMatchFilter(
    322                 matchFilter).setPublishType(mIsUnsolicited ? PublishConfig.PUBLISH_TYPE_UNSOLICITED
    323                 : PublishConfig.PUBLISH_TYPE_SOLICITED).setTerminateNotificationEnabled(
    324                 true).build();
    325         if (DBG) Log.d(TAG, "executeTestPublisher: publishConfig=" + publishConfig);
    326         mWifiAwareSession.publish(publishConfig, discoveryCb, mHandler);
    327 
    328         //    wait for results - publish session
    329         CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
    330                 CallbackUtils.DiscoveryCb.ON_PUBLISH_STARTED
    331                         | CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
    332         switch (callbackData.callback) {
    333             case CallbackUtils.DiscoveryCb.TIMEOUT:
    334                 setFailureReason(mContext.getString(R.string.aware_status_publish_timeout));
    335                 Log.e(TAG, "executeTestPublisher: publish TIMEOUT");
    336                 return false;
    337             case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
    338                 setFailureReason(mContext.getString(R.string.aware_status_publish_failed));
    339                 Log.e(TAG, "executeTestPublisher: publish ON_SESSION_CONFIG_FAILED");
    340                 return false;
    341         }
    342         PublishDiscoverySession discoverySession = callbackData.publishDiscoverySession;
    343         if (discoverySession == null) {
    344             setFailureReason(mContext.getString(R.string.aware_status_publish_null_session));
    345             Log.e(TAG, "executeTestPublisher: publish succeeded but null session returned");
    346             return false;
    347         }
    348         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_publish_started));
    349         if (DBG) Log.d(TAG, "executeTestPublisher: publish succeeded");
    350 
    351         // 3. wait to receive message: no timeout since this depends on (human) operator starting
    352         //    the test on the subscriber device.
    353         callbackData = discoveryCb.waitForCallbacksNoTimeout(
    354                 CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
    355         PeerHandle peerHandle = callbackData.peerHandle;
    356         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
    357         if (DBG) Log.d(TAG, "executeTestPublisher: received message");
    358 
    359         //    validate that received the expected message
    360         if (!Arrays.equals(MSG_SUB_TO_PUB, callbackData.serviceSpecificInfo)) {
    361             setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
    362             Log.e(TAG, "executeTestPublisher: receive message message content mismatch: rx='"
    363                     + new String(callbackData.serviceSpecificInfo) + "'");
    364             return false;
    365         }
    366         if (peerHandle == null) {
    367             setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
    368             Log.e(TAG, "executeTestPublisher: received message but peerHandle is null!?");
    369             return false;
    370         }
    371 
    372         // 4. Request network
    373         ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
    374                 Context.CONNECTIVITY_SERVICE);
    375         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
    376                 NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
    377                 mIsSecurityOpen ? discoverySession.createNetworkSpecifierOpen(peerHandle)
    378                         : discoverySession.createNetworkSpecifierPassphrase(peerHandle,
    379                                 PASSPHRASE)).build();
    380         CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
    381         cm.requestNetwork(nr, networkCb, CALLBACK_TIMEOUT_SEC * 1000);
    382         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
    383         if (DBG) Log.d(TAG, "executeTestPublisher: requested network");
    384 
    385         // 5. send message & wait for send status
    386         discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_PUB_TO_SUB);
    387         callbackData = discoveryCb.waitForCallbacks(
    388                 CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
    389                         | CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
    390         switch (callbackData.callback) {
    391             case CallbackUtils.DiscoveryCb.TIMEOUT:
    392                 setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
    393                 Log.e(TAG, "executeTestPublisher: send message TIMEOUT");
    394                 return false;
    395             case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
    396                 setFailureReason(mContext.getString(R.string.aware_status_send_failed));
    397                 Log.e(TAG, "executeTestPublisher: send message ON_MESSAGE_SEND_FAILED");
    398                 return false;
    399         }
    400         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
    401         if (DBG) Log.d(TAG, "executeTestPublisher: send message succeeded");
    402 
    403         if (callbackData.messageId != MESSAGE_ID) {
    404             setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
    405             Log.e(TAG, "executeTestPublisher: send message succeeded but message ID mismatch : "
    406                     + callbackData.messageId);
    407             return false;
    408         }
    409 
    410         // 6. wait for network
    411         boolean networkAvailable = networkCb.waitForNetwork();
    412         cm.unregisterNetworkCallback(networkCb);
    413         if (!networkAvailable) {
    414             setFailureReason(mContext.getString(R.string.aware_status_network_failed));
    415             Log.e(TAG, "executeTestPublisher: request network rejected - ON_UNAVAILABLE");
    416             return false;
    417         }
    418         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
    419         if (DBG) Log.d(TAG, "executeTestPublisher: network request granted - AVAILABLE");
    420 
    421         // 7. destroy session
    422         discoverySession.close();
    423 
    424         mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
    425         return true;
    426 
    427     }
    428 }
    429