blob: 91e056450efde158a664a9a00f5c893d342570b8 [file] [log] [blame]
/*
* Copyright (C) 2017 Google Inc.
*
* 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.google.android.mobly.snippet.bundled;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.test.InstrumentationRegistry;
import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.bundled.utils.JsonSerializer;
import com.google.android.mobly.snippet.bundled.utils.Utils;
import com.google.android.mobly.snippet.rpc.Rpc;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
/** Snippet class exposing Android APIs in BluetoothAdapter. */
public class BluetoothAdapterSnippet implements Snippet {
private static class BluetoothAdapterSnippetException extends Exception {
public BluetoothAdapterSnippetException(String msg) {
super(msg);
}
}
private final Context mContext;
private final BluetoothAdapter mBluetoothAdapter;
private final JsonSerializer mJsonSerializer = new JsonSerializer();
private final ArrayList<BluetoothDevice> mDiscoveryResults = new ArrayList<>();
private volatile boolean mIsScanResultAvailable = false;
public BluetoothAdapterSnippet() {
mContext = InstrumentationRegistry.getContext();
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
@Rpc(description = "Enable bluetooth with a 30s timeout.")
public void btEnable() throws BluetoothAdapterSnippetException, InterruptedException {
if (!mBluetoothAdapter.enable()) {
throw new BluetoothAdapterSnippetException("Failed to start enabling bluetooth");
}
if (!Utils.waitUntil(() -> mBluetoothAdapter.isEnabled(), 30)) {
throw new BluetoothAdapterSnippetException("Bluetooth did not turn on within 30s.");
}
}
@Rpc(description = "Disable bluetooth with a 30s timeout.")
public void btDisable() throws BluetoothAdapterSnippetException, InterruptedException {
if (!mBluetoothAdapter.disable()) {
throw new BluetoothAdapterSnippetException("Failed to start disabling bluetooth");
}
if (!Utils.waitUntil(() -> !mBluetoothAdapter.isEnabled(), 30)) {
throw new BluetoothAdapterSnippetException("Bluetooth did not turn off within 30s.");
}
}
@Rpc(
description =
"Get bluetooth discovery results, which is a list of serialized BluetoothDevice objects."
)
public JSONArray btGetCachedScanResults() throws JSONException {
JSONArray results = new JSONArray();
for (BluetoothDevice result : mDiscoveryResults) {
results.put(mJsonSerializer.toJson(result));
}
return results;
}
@Rpc(
description =
"Start discovery, wait for discovery to complete, and return results, which is a list of "
+ "serialized BluetoothDevice objects."
)
public JSONArray btDiscoveryAndGetResults()
throws InterruptedException, JSONException, BluetoothAdapterSnippetException {
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mDiscoveryResults.clear();
mIsScanResultAvailable = false;
BroadcastReceiver receiver = new BluetoothScanReceiver();
mContext.registerReceiver(receiver, filter);
try {
if (!mBluetoothAdapter.startDiscovery()) {
throw new BluetoothAdapterSnippetException(
"Failed to initiate Bluetooth Discovery.");
}
if (!Utils.waitUntil(() -> mIsScanResultAvailable, 60)) {
throw new BluetoothAdapterSnippetException(
"Failed to get discovery results after 1 min, timeout!");
}
} finally {
mContext.unregisterReceiver(receiver);
}
return btGetCachedScanResults();
}
@Rpc(description = "Get the list of paired bluetooth devices")
public JSONArray btGetPairedDevices()
throws BluetoothAdapterSnippetException, InterruptedException, JSONException {
JSONArray pairedDevices = new JSONArray();
for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) {
pairedDevices.put(mJsonSerializer.toJson(device));
}
return pairedDevices;
}
@Override
public void shutdown() {}
private class BluetoothScanReceiver extends BroadcastReceiver {
/**
* The receiver gets an ACTION_FOUND intent whenever a new device is found.
* ACTION_DISCOVERY_FINISHED intent is received when the discovery process ends.
*/
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
mIsScanResultAvailable = true;
} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device =
(BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDiscoveryResults.add(device);
}
}
}
}