blob: 5f64f02cd52ad06a1ee82754f44b2b618487e4cf [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.verifier.wifiaware.testcase;
import static com.android.cts.verifier.wifiaware.CallbackUtils.CALLBACK_TIMEOUT_SEC;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.aware.DiscoverySession;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.PublishDiscoverySession;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.SubscribeDiscoverySession;
import android.net.wifi.aware.WifiAwareSession;
import android.util.Log;
import android.util.Pair;
import com.android.cts.verifier.R;
import com.android.cts.verifier.wifiaware.BaseTestCase;
import com.android.cts.verifier.wifiaware.CallbackUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Test case for data-path, in-band test cases:
* open/passphrase * solicited/unsolicited * publish/subscribe.
*
* Subscribe test sequence:
* 1. Attach
* wait for results (session)
* 2. Subscribe
* wait for results (subscribe session)
* 3. Wait for discovery
* 4. Send message
* Wait for success
* 5. Wait for rx message
* 6. Request network
* Wait for network
* 7. Destroy session
*
* Publish test sequence:
* 1. Attach
* wait for results (session)
* 2. Publish
* wait for results (publish session)
* 3. Wait for rx message
* 4. Request network
* 5. Send message
* Wait for success
* 6. Wait for network
* 7. Destroy session
*/
public class DataPathInBandTestCase extends BaseTestCase {
private static final String TAG = "DataPathInBandTestCase";
private static final boolean DBG = true;
private static final String SERVICE_NAME = "CtsVerifierTestService";
private static final byte[] MATCH_FILTER_BYTES = "bytes used for matching".getBytes();
private static final byte[] PUB_SSI = "Extra bytes in the publisher discovery".getBytes();
private static final byte[] SUB_SSI = "Arbitrary bytes for the subscribe discovery".getBytes();
private static final byte[] MSG_SUB_TO_PUB = "Let's talk".getBytes();
private static final byte[] MSG_PUB_TO_SUB = "Ready".getBytes();
private static final String PASSPHRASE = "Some super secret password";
private static final int MESSAGE_ID = 1234;
private boolean mIsSecurityOpen;
private boolean mIsPublish;
private boolean mIsUnsolicited;
private final Object mLock = new Object();
private String mFailureReason;
private WifiAwareSession mWifiAwareSession;
private DiscoverySession mWifiAwareDiscoverySession;
public DataPathInBandTestCase(Context context, boolean isSecurityOpen, boolean isPublish,
boolean isUnsolicited) {
super(context);
mIsSecurityOpen = isSecurityOpen;
mIsPublish = isPublish;
mIsUnsolicited = isUnsolicited;
}
@Override
protected boolean executeTest() throws InterruptedException {
if (DBG) {
Log.d(TAG,
"executeTest: mIsSecurityOpen=" + mIsSecurityOpen + ", mIsPublish=" + mIsPublish
+ ", mIsUnsolicited=" + mIsUnsolicited);
}
// 1. attach
CallbackUtils.AttachCb attachCb = new CallbackUtils.AttachCb();
mWifiAwareManager.attach(attachCb, mHandler);
Pair<Integer, WifiAwareSession> results = attachCb.waitForAttach();
switch (results.first) {
case CallbackUtils.AttachCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_attach_timeout));
Log.e(TAG, "executeTest: attach TIMEOUT");
return false;
case CallbackUtils.AttachCb.ON_ATTACH_FAILED:
setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
Log.e(TAG, "executeTest: attach ON_ATTACH_FAILED");
return false;
}
mWifiAwareSession = results.second;
if (mWifiAwareSession == null) {
setFailureReason(mContext.getString(R.string.aware_status_attach_fail));
Log.e(TAG, "executeTest: attach callback succeeded but null session returned!?");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_attached));
if (DBG) {
Log.d(TAG, "executeTest: attach succeeded");
}
if (mIsPublish) {
return executeTestPublisher();
} else {
return executeTestSubscriber();
}
}
private void setFailureReason(String reason) {
synchronized (mLock) {
mFailureReason = reason;
}
}
@Override
protected String getFailureReason() {
synchronized (mLock) {
return mFailureReason;
}
}
@Override
protected void tearDown() {
if (mWifiAwareDiscoverySession != null) {
mWifiAwareDiscoverySession.close();
mWifiAwareDiscoverySession = null;
}
if (mWifiAwareSession != null) {
mWifiAwareSession.close();
mWifiAwareSession = null;
}
super.tearDown();
}
private boolean executeTestSubscriber() throws InterruptedException {
if (DBG) Log.d(TAG, "executeTestSubscriber");
CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();
// 2. subscribe
List<byte[]> matchFilter = new ArrayList<>();
matchFilter.add(MATCH_FILTER_BYTES);
SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(
SERVICE_NAME).setServiceSpecificInfo(SUB_SSI).setMatchFilter(
matchFilter).setSubscribeType(
mIsUnsolicited ? SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE
: SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE).setTerminateNotificationEnabled(
true).build();
if (DBG) Log.d(TAG, "executeTestSubscriber: subscribeConfig=" + subscribeConfig);
mWifiAwareSession.subscribe(subscribeConfig, discoveryCb, mHandler);
// wait for results - subscribe session
CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
CallbackUtils.DiscoveryCb.ON_SUBSCRIBE_STARTED
| CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_subscribe_timeout));
Log.e(TAG, "executeTestSubscriber: subscribe TIMEOUT");
return false;
case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
setFailureReason(mContext.getString(R.string.aware_status_subscribe_failed));
Log.e(TAG, "executeTestSubscriber: subscribe ON_SESSION_CONFIG_FAILED");
return false;
}
SubscribeDiscoverySession discoverySession = callbackData.subscribeDiscoverySession;
mWifiAwareDiscoverySession = discoverySession;
if (discoverySession == null) {
setFailureReason(mContext.getString(R.string.aware_status_subscribe_null_session));
Log.e(TAG, "executeTestSubscriber: subscribe succeeded but null session returned");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_subscribe_started));
if (DBG) Log.d(TAG, "executeTestSubscriber: subscribe succeeded");
// 3. wait for discovery
callbackData = discoveryCb.waitForCallbacks(
CallbackUtils.DiscoveryCb.ON_SERVICE_DISCOVERED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_discovery_timeout));
Log.e(TAG, "executeTestSubscriber: waiting for discovery TIMEOUT");
return false;
}
PeerHandle peerHandle = callbackData.peerHandle;
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_discovery));
if (DBG) Log.d(TAG, "executeTestSubscriber: discovery");
// validate discovery parameters match
if (!Arrays.equals(PUB_SSI, callbackData.serviceSpecificInfo)) {
setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
Log.e(TAG, "executeTestSubscriber: discovery but SSI mismatch: rx='" + new String(
callbackData.serviceSpecificInfo) + "'");
return false;
}
if (callbackData.matchFilter.size() != 1 || !Arrays.equals(MATCH_FILTER_BYTES,
callbackData.matchFilter.get(0))) {
setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
StringBuffer sb = new StringBuffer();
sb.append("size=").append(callbackData.matchFilter.size());
for (byte[] mf: callbackData.matchFilter) {
sb.append(", e='").append(new String(mf)).append("'");
}
Log.e(TAG, "executeTestSubscriber: discovery but matchFilter mismatch: "
+ sb.toString());
return false;
}
if (peerHandle == null) {
setFailureReason(mContext.getString(R.string.aware_status_discovery_fail));
Log.e(TAG, "executeTestSubscriber: discovery but null peerHandle");
return false;
}
// 4. send message & wait for send status
discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_SUB_TO_PUB);
callbackData = discoveryCb.waitForCallbacks(
CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
| CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
Log.e(TAG, "executeTestSubscriber: send message TIMEOUT");
return false;
case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
setFailureReason(mContext.getString(R.string.aware_status_send_failed));
Log.e(TAG, "executeTestSubscriber: send message ON_MESSAGE_SEND_FAILED");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
if (DBG) Log.d(TAG, "executeTestSubscriber: send message succeeded");
if (callbackData.messageId != MESSAGE_ID) {
setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
Log.e(TAG, "executeTestSubscriber: send message message ID mismatch: "
+ callbackData.messageId);
return false;
}
// 5. wait to receive message
callbackData = discoveryCb.waitForCallbacks(CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_receive_timeout));
Log.e(TAG, "executeTestSubscriber: receive message TIMEOUT");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
if (DBG) Log.d(TAG, "executeTestSubscriber: received message");
// validate that received the expected message
if (!Arrays.equals(MSG_PUB_TO_SUB, callbackData.serviceSpecificInfo)) {
setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
Log.e(TAG, "executeTestSubscriber: receive message message content mismatch: rx='"
+ new String(callbackData.serviceSpecificInfo) + "'");
return false;
}
// 6. request network
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
mIsSecurityOpen ? discoverySession.createNetworkSpecifierOpen(peerHandle)
: discoverySession.createNetworkSpecifierPassphrase(peerHandle,
PASSPHRASE)).build();
CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
cm.requestNetwork(nr, networkCb, CALLBACK_TIMEOUT_SEC * 1000);
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
if (DBG) Log.d(TAG, "executeTestSubscriber: requested network");
boolean networkAvailable = networkCb.waitForNetwork();
cm.unregisterNetworkCallback(networkCb);
if (!networkAvailable) {
setFailureReason(mContext.getString(R.string.aware_status_network_failed));
Log.e(TAG, "executeTestSubscriber: network request rejected - ON_UNAVAILABLE");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
if (DBG) Log.d(TAG, "executeTestSubscriber: network request granted - AVAILABLE");
// 7. destroy session
discoverySession.close();
mWifiAwareDiscoverySession = null;
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
return true;
}
private boolean executeTestPublisher() throws InterruptedException {
if (DBG) Log.d(TAG, "executeTestPublisher");
CallbackUtils.DiscoveryCb discoveryCb = new CallbackUtils.DiscoveryCb();
// 2. publish
List<byte[]> matchFilter = new ArrayList<>();
matchFilter.add(MATCH_FILTER_BYTES);
PublishConfig publishConfig = new PublishConfig.Builder().setServiceName(
SERVICE_NAME).setServiceSpecificInfo(PUB_SSI).setMatchFilter(
matchFilter).setPublishType(mIsUnsolicited ? PublishConfig.PUBLISH_TYPE_UNSOLICITED
: PublishConfig.PUBLISH_TYPE_SOLICITED).setTerminateNotificationEnabled(
true).build();
if (DBG) Log.d(TAG, "executeTestPublisher: publishConfig=" + publishConfig);
mWifiAwareSession.publish(publishConfig, discoveryCb, mHandler);
// wait for results - publish session
CallbackUtils.DiscoveryCb.CallbackData callbackData = discoveryCb.waitForCallbacks(
CallbackUtils.DiscoveryCb.ON_PUBLISH_STARTED
| CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_publish_timeout));
Log.e(TAG, "executeTestPublisher: publish TIMEOUT");
return false;
case CallbackUtils.DiscoveryCb.ON_SESSION_CONFIG_FAILED:
setFailureReason(mContext.getString(R.string.aware_status_publish_failed));
Log.e(TAG, "executeTestPublisher: publish ON_SESSION_CONFIG_FAILED");
return false;
}
PublishDiscoverySession discoverySession = callbackData.publishDiscoverySession;
mWifiAwareDiscoverySession = discoverySession;
if (discoverySession == null) {
setFailureReason(mContext.getString(R.string.aware_status_publish_null_session));
Log.e(TAG, "executeTestPublisher: publish succeeded but null session returned");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_publish_started));
if (DBG) Log.d(TAG, "executeTestPublisher: publish succeeded");
// 3. wait to receive message: no timeout since this depends on (human) operator starting
// the test on the subscriber device.
callbackData = discoveryCb.waitForCallbacksNoTimeout(
CallbackUtils.DiscoveryCb.ON_MESSAGE_RECEIVED);
PeerHandle peerHandle = callbackData.peerHandle;
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_received));
if (DBG) Log.d(TAG, "executeTestPublisher: received message");
// validate that received the expected message
if (!Arrays.equals(MSG_SUB_TO_PUB, callbackData.serviceSpecificInfo)) {
setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
Log.e(TAG, "executeTestPublisher: receive message message content mismatch: rx='"
+ new String(callbackData.serviceSpecificInfo) + "'");
return false;
}
if (peerHandle == null) {
setFailureReason(mContext.getString(R.string.aware_status_receive_failure));
Log.e(TAG, "executeTestPublisher: received message but peerHandle is null!?");
return false;
}
// 4. Request network
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI_AWARE).setNetworkSpecifier(
mIsSecurityOpen ? discoverySession.createNetworkSpecifierOpen(peerHandle)
: discoverySession.createNetworkSpecifierPassphrase(peerHandle,
PASSPHRASE)).build();
CallbackUtils.NetworkCb networkCb = new CallbackUtils.NetworkCb();
cm.requestNetwork(nr, networkCb, CALLBACK_TIMEOUT_SEC * 1000);
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_requested));
if (DBG) Log.d(TAG, "executeTestPublisher: requested network");
// 5. send message & wait for send status
discoverySession.sendMessage(peerHandle, MESSAGE_ID, MSG_PUB_TO_SUB);
callbackData = discoveryCb.waitForCallbacks(
CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_SUCCEEDED
| CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED);
switch (callbackData.callback) {
case CallbackUtils.DiscoveryCb.TIMEOUT:
setFailureReason(mContext.getString(R.string.aware_status_send_timeout));
Log.e(TAG, "executeTestPublisher: send message TIMEOUT");
return false;
case CallbackUtils.DiscoveryCb.ON_MESSAGE_SEND_FAILED:
setFailureReason(mContext.getString(R.string.aware_status_send_failed));
Log.e(TAG, "executeTestPublisher: send message ON_MESSAGE_SEND_FAILED");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_send_success));
if (DBG) Log.d(TAG, "executeTestPublisher: send message succeeded");
if (callbackData.messageId != MESSAGE_ID) {
setFailureReason(mContext.getString(R.string.aware_status_send_fail_parameter));
Log.e(TAG, "executeTestPublisher: send message succeeded but message ID mismatch : "
+ callbackData.messageId);
return false;
}
// 6. wait for network
boolean networkAvailable = networkCb.waitForNetwork();
cm.unregisterNetworkCallback(networkCb);
if (!networkAvailable) {
setFailureReason(mContext.getString(R.string.aware_status_network_failed));
Log.e(TAG, "executeTestPublisher: request network rejected - ON_UNAVAILABLE");
return false;
}
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_network_success));
if (DBG) Log.d(TAG, "executeTestPublisher: network request granted - AVAILABLE");
// 7. destroy session
discoverySession.close();
mWifiAwareDiscoverySession = null;
mListener.onTestMsgReceived(mContext.getString(R.string.aware_status_lifecycle_ok));
return true;
}
}