Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create BluetoothHeadsetSnippet #175

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
com.google.android.mobly.snippet.bundled.bluetooth.BluetoothGattClientSnippet,
com.google.android.mobly.snippet.bundled.bluetooth.BluetoothGattServerSnippet,
com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothA2dpSnippet,
com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothHeadsetSnippet,
com.google.android.mobly.snippet.bundled.bluetooth.profiles.BluetoothHearingAidSnippet,
com.google.android.mobly.snippet.bundled.BluetoothLeAdvertiserSnippet,
com.google.android.mobly.snippet.bundled.BluetoothLeScannerSnippet,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.google.android.mobly.snippet.bundled.bluetooth.profiles;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import androidx.test.platform.app.InstrumentationRegistry;
import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.bundled.bluetooth.BluetoothAdapterSnippet;
import com.google.android.mobly.snippet.bundled.bluetooth.PairingBroadcastReceiver;
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 com.google.android.mobly.snippet.rpc.RpcMinSdk;
import java.util.ArrayList;

/** */
public class BluetoothHeadsetSnippet implements Snippet {

private static class BluetoothHeadsetSnippetException extends Exception {
private static final long serialVersionUID = 1;

BluetoothHeadsetSnippetException(String message) {
super(message);
}
}

private Context mContext;
private static boolean sIsHeadsetProfileReady = false;
private static BluetoothHeadset sHeadsetProfile;
private final JsonSerializer mJsonSerializer = new JsonSerializer();

public BluetoothHeadsetSnippet() {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.getProfileProxy(
mContext, new HeadsetServiceListener(), BluetoothProfile.HEADSET);
Utils.waitUntil(() -> sIsHeadsetProfileReady, 60);
}

private static class HeadsetServiceListener implements BluetoothProfile.ServiceListener {

public void onServiceConnected(int var1, BluetoothProfile profile) {
sHeadsetProfile = (BluetoothHeadset) profile;
sIsHeadsetProfileReady = true;
}

public void onServiceDisconnected(int var1) {
sIsHeadsetProfileReady = false;
}
}

@TargetApi(Build.VERSION_CODES.KITKAT)
@RpcMinSdk(Build.VERSION_CODES.KITKAT)
@Rpc(
description =
"Connects to a paired or discovered device with Headset profile."
+ "If a device has been discovered but not paired, this will pair it.")
public void btHeadsetConnect(String deviceAddress) throws Throwable {
BluetoothDevice device = BluetoothAdapterSnippet.getKnownDeviceByAddress(deviceAddress);
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
mContext.registerReceiver(new PairingBroadcastReceiver(mContext), filter);
Utils.invokeByReflection(sHeadsetProfile, "connect", device);
if (!Utils.waitUntil(
() -> sHeadsetProfile.getConnectionState(device) == BluetoothHeadset.STATE_CONNECTED,
120)) {
throw new BluetoothHeadsetSnippetException(
"Failed to connect to device "
+ device.getName()
+ "|"
+ device.getAddress()
+ " with Headset profile within 2min.");
}
}

@Rpc(description = "Disconnects a device from Headset profile.")
public void btHeadsetDisconnect(String deviceAddress) throws Throwable {
BluetoothDevice device = getConnectedBluetoothDevice(deviceAddress);
Utils.invokeByReflection(sHeadsetProfile, "disconnect", device);
if (!Utils.waitUntil(
() -> sHeadsetProfile.getConnectionState(device) == BluetoothHeadset.STATE_DISCONNECTED,
120)) {
throw new BluetoothHeadsetSnippetException(
"Failed to disconnect device "
+ device.getName()
+ "|"
+ device.getAddress()
+ " from A2DP profile within 2min.");
}
}

@Rpc(description = "Gets all the devices currently connected via Headset profile.")
public ArrayList<Bundle> btHeadsetGetConnectedDevices() {
return mJsonSerializer.serializeBluetoothDeviceList(sHeadsetProfile.getConnectedDevices());
}

@Rpc(description = "Checks if a device supports noise reduction.")
public boolean btHeadsetIsNoiseReductionSupported(String deviceAddress) throws Throwable {
BluetoothDevice device = getConnectedBluetoothDevice(deviceAddress);
return sHeadsetProfile.isNoiseReductionSupported(device);
}

@Rpc(description = "Checks if a device supports voice recognition.")
public boolean btHeadsetIsVoiceRecognitionSupported(String deviceAddress) throws Throwable {
BluetoothDevice device = getConnectedBluetoothDevice(deviceAddress);
return sHeadsetProfile.isVoiceRecognitionSupported(device);
}

private BluetoothDevice getConnectedBluetoothDevice(String deviceAddress)
throws BluetoothHeadsetSnippetException {
for (BluetoothDevice device : sHeadsetProfile.getConnectedDevices()) {
if (device.getAddress().equalsIgnoreCase(deviceAddress)) {
return device;
}
}
throw new BluetoothHeadsetSnippetException(
"No device with address " + deviceAddress + " is connected via Headset.");
}

@Override
public void shutdown() {}
}