summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--framework/tests/bumble/AndroidTest.xml1
-rw-r--r--framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java301
2 files changed, 242 insertions, 60 deletions
diff --git a/framework/tests/bumble/AndroidTest.xml b/framework/tests/bumble/AndroidTest.xml
index 1b31b827e2..4855fec134 100644
--- a/framework/tests/bumble/AndroidTest.xml
+++ b/framework/tests/bumble/AndroidTest.xml
@@ -42,6 +42,7 @@
<option name="test-tag" value="BumbleBluetoothTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.bluetooth" />
+ <option name="hidden-api-checks" value="false" />
</test>
<!-- Only run if the Bluetooth Mainline module is installed. -->
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
index fe45f237ae..9e91d8a4e8 100644
--- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -53,7 +53,11 @@ public class HidHostTest {
private static final String TAG = "HidHostTest";
private SettableFuture<Integer> mFutureConnectionIntent,
mFutureAdapterStateIntent,
- mFutureBondIntent;
+ mFutureBondIntent,
+ mFutureHandShakeIntent,
+ mFutureProtocolModeIntent,
+ mFutureVirtualUnplugIntent,
+ mFutureReportIntent;
private SettableFuture<Boolean> mAclConnectionIntent;
private BluetoothDevice mDevice;
private BluetoothHidHost mHidService;
@@ -63,6 +67,12 @@ public class HidHostTest {
private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class);
private final BluetoothAdapter mAdapter = mManager.getAdapter();
private HIDGrpc.HIDBlockingStub mHidBlockingStub;
+ private byte mReportId;
+ private static final int KEYBD_RPT_ID = 1;
+ private static final int KEYBD_RPT_SIZE = 9;
+ private static final int MOUSE_RPT_ID = 2;
+ private static final int MOUSE_RPT_SIZE = 4;
+ private static final int INVALID_RPT_ID = 3;
private static final int CONNECTION_TIMEOUT_MS = 2_000;
@Rule(order = 0)
@@ -74,51 +84,98 @@ public class HidHostTest {
@Rule(order = 2)
public final PandoraDevice mBumble = new PandoraDevice();
- private BroadcastReceiver mConnectionStateReceiver =
+ private BroadcastReceiver mHidStateReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED.equals(
- intent.getAction())) {
- int state =
- intent.getIntExtra(
- BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
- Log.i(TAG, "Connection state change:" + state);
- if (state == BluetoothProfile.STATE_CONNECTED
- || state == BluetoothProfile.STATE_DISCONNECTED) {
- if (mFutureConnectionIntent != null) {
- mFutureConnectionIntent.set(state);
+ switch (intent.getAction()) {
+ case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED:
+ int state =
+ intent.getIntExtra(
+ BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
+ Log.i(TAG, "Connection state change:" + state);
+ if (state == BluetoothProfile.STATE_CONNECTED
+ || state == BluetoothProfile.STATE_DISCONNECTED) {
+ if (mFutureConnectionIntent != null) {
+ mFutureConnectionIntent.set(state);
+ }
}
- }
- } else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
- mBumble.getRemoteDevice().setPairingConfirmation(true);
- } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
- int adapterState =
- intent.getIntExtra(
- BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
- Log.i(TAG, "Adapter state change:" + adapterState);
- if (adapterState == BluetoothAdapter.STATE_ON
- || adapterState == BluetoothAdapter.STATE_OFF) {
- if (mFutureAdapterStateIntent != null) {
- mFutureAdapterStateIntent.set(adapterState);
+ break;
+ case BluetoothDevice.ACTION_PAIRING_REQUEST:
+ mBumble.getRemoteDevice().setPairingConfirmation(true);
+ break;
+ case BluetoothAdapter.ACTION_STATE_CHANGED:
+ int adapterState =
+ intent.getIntExtra(
+ BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+ Log.i(TAG, "Adapter state change:" + adapterState);
+ if (adapterState == BluetoothAdapter.STATE_ON
+ || adapterState == BluetoothAdapter.STATE_OFF) {
+ if (mFutureAdapterStateIntent != null) {
+ mFutureAdapterStateIntent.set(adapterState);
+ }
+ }
+ break;
+ case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
+ int bondState =
+ intent.getIntExtra(
+ BluetoothDevice.EXTRA_BOND_STATE,
+ BluetoothDevice.ERROR);
+ Log.i(TAG, "Bond state change:" + bondState);
+ if (bondState == BluetoothDevice.BOND_BONDED
+ || bondState == BluetoothDevice.BOND_NONE) {
+ if (mFutureBondIntent != null) {
+ mFutureBondIntent.set(bondState);
+ }
+ }
+ break;
+ case BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED:
+ int protocolMode =
+ intent.getIntExtra(
+ BluetoothHidHost.EXTRA_PROTOCOL_MODE,
+ BluetoothHidHost.PROTOCOL_UNSUPPORTED_MODE);
+ Log.i(TAG, "Protocol mode:" + protocolMode);
+ if (mFutureProtocolModeIntent != null) {
+ mFutureProtocolModeIntent.set(protocolMode);
+ }
+ break;
+ case BluetoothHidHost.ACTION_HANDSHAKE:
+ int handShake =
+ intent.getIntExtra(
+ BluetoothHidHost.EXTRA_STATUS,
+ BluetoothHidDevice.ERROR_RSP_UNKNOWN);
+ Log.i(TAG, "Handshake status:" + handShake);
+ if (mFutureHandShakeIntent != null) {
+ mFutureHandShakeIntent.set(handShake);
+ }
+ break;
+ case BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS:
+ int virtualUnplug =
+ intent.getIntExtra(
+ BluetoothHidHost.EXTRA_VIRTUAL_UNPLUG_STATUS,
+ BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_FAIL);
+ Log.i(TAG, "Virtual Unplug status:" + virtualUnplug);
+ if (mFutureVirtualUnplugIntent != null) {
+ mFutureVirtualUnplugIntent.set(virtualUnplug);
}
- }
- } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(
- intent.getAction())) {
- int bondState =
- intent.getIntExtra(
- BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
- Log.i(TAG, "Bond state change:" + bondState);
- if (bondState == BluetoothDevice.BOND_BONDED
- || bondState == BluetoothDevice.BOND_NONE) {
- if (mFutureBondIntent != null) {
- mFutureBondIntent.set(bondState);
+ break;
+ case BluetoothHidHost.ACTION_REPORT:
+ byte[] report = intent.getByteArrayExtra(BluetoothHidHost.EXTRA_REPORT);
+ int reportSize =
+ intent.getIntExtra(
+ BluetoothHidHost.EXTRA_REPORT_BUFFER_SIZE, 0);
+ mReportId = report[0];
+ if (mFutureReportIntent != null) {
+ mFutureReportIntent.set((reportSize - 1));
+ }
+ break;
+ case BluetoothDevice.ACTION_ACL_DISCONNECTED:
+ if (mAclConnectionIntent != null) {
+ mAclConnectionIntent.set(true);
}
- }
- } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction())) {
- if (mAclConnectionIntent != null) {
- mAclConnectionIntent.set(true);
- }
+ break;
+ default:
+ break;
}
}
};
@@ -150,17 +207,18 @@ public class HidHostTest {
@Before
public void setUp() throws Exception {
- mContext.registerReceiver(
- mConnectionStateReceiver,
- new IntentFilter(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED));
- mContext.registerReceiver(
- mConnectionStateReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST));
- mContext.registerReceiver(
- mConnectionStateReceiver,
- new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
- mContext.registerReceiver(
- mConnectionStateReceiver,
- new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
+ filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+ filter.addAction(BluetoothHidHost.ACTION_PROTOCOL_MODE_CHANGED);
+ filter.addAction(BluetoothHidHost.ACTION_HANDSHAKE);
+ filter.addAction(BluetoothHidHost.ACTION_VIRTUAL_UNPLUG_STATUS);
+ filter.addAction(BluetoothHidHost.ACTION_REPORT);
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+
+ mContext.registerReceiver(mHidStateReceiver, filter);
mAdapter.getProfileProxy(
mContext, mBluetoothProfileServiceListener, BluetoothProfile.HID_HOST);
mAdapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, BluetoothProfile.A2DP);
@@ -189,6 +247,7 @@ public class HidHostTest {
@After
public void tearDown() throws Exception {
+
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
mFutureBondIntent = SettableFuture.create();
mDevice.removeBond();
@@ -200,7 +259,8 @@ public class HidHostTest {
mDevice.disconnect();
assertThat(mAclConnectionIntent.get()).isTrue();
}
- mContext.unregisterReceiver(mConnectionStateReceiver);
+
+ mContext.unregisterReceiver(mHidStateReceiver);
}
/**
@@ -366,12 +426,136 @@ public class HidHostTest {
assertThat(mFutureConnectionIntent.get()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ mFutureBondIntent = SettableFuture.create();
mDevice.removeBond();
+ assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_NONE);
- mFutureConnectionIntent = SettableFuture.create();
- mHidBlockingStub.connectHost(Empty.getDefaultInstance());
- assertThat(mHidService.getConnectionState(mDevice))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ reconnectionFromRemoteAndVerifyDisconnectedState();
+ }
+
+ /**
+ * Test Virtual Unplug from Hid Host
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Android Virtual Unplug and verifies Bonding
+ * </ol>
+ */
+ @Test
+ public void hidVirtualUnplugFromHidHostTest() throws Exception {
+ mHidService.virtualUnplug(mDevice);
+ mFutureBondIntent = SettableFuture.create();
+ assertThat(mFutureBondIntent.get()).isEqualTo(BluetoothDevice.BOND_NONE);
+ }
+
+ /**
+ * Test Virtual Unplug from Hid Device
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Bumble Virtual Unplug and Android verifies Bonding
+ * </ol>
+ */
+ @Test
+ public void hidVirtualUnplugFromHidDeviceTest() throws Exception {
+ mHidBlockingStub.virtualCableUnplugHost(Empty.getDefaultInstance());
+ mFutureVirtualUnplugIntent = SettableFuture.create();
+ assertThat(mFutureVirtualUnplugIntent.get())
+ .isEqualTo(BluetoothHidHost.VIRTUAL_UNPLUG_STATUS_SUCCESS);
+ }
+
+ /**
+ * Test Get Protocol mode
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Android Gets the Protocol mode and verifies the mode
+ * </ol>
+ */
+ @Test
+ public void hidGetProtocolModeTest() throws Exception {
+ mHidService.getProtocolMode(mDevice);
+ mFutureProtocolModeIntent = SettableFuture.create();
+ assertThat(mFutureProtocolModeIntent.get())
+ .isEqualTo(BluetoothHidHost.PROTOCOL_REPORT_MODE);
+ }
+
+ /**
+ * Test Set Protocol mode
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Android Sets the Protocol mode and verifies the mode
+ * </ol>
+ */
+ @Test
+ public void hidSetProtocolModeTest() throws Exception {
+ mHidService.setProtocolMode(mDevice, BluetoothHidHost.PROTOCOL_BOOT_MODE);
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get())
+ .isEqualTo(BluetoothHidDevice.ERROR_RSP_UNSUPPORTED_REQ);
+ }
+
+ /**
+ * Test Get Report
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Android get report and verifies the report
+ * </ol>
+ */
+ @Test
+ public void hidGetReportTest() throws Exception {
+ // Keyboard report
+ byte id = KEYBD_RPT_ID;
+ mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0);
+ mFutureReportIntent = SettableFuture.create();
+ assertThat(mFutureReportIntent.get()).isEqualTo(KEYBD_RPT_SIZE);
+ assertThat(mReportId).isEqualTo(KEYBD_RPT_ID);
+
+ // Mouse report
+ id = MOUSE_RPT_ID;
+ mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0);
+ mFutureReportIntent = SettableFuture.create();
+ assertThat(mFutureReportIntent.get()).isEqualTo(MOUSE_RPT_SIZE);
+ assertThat(mReportId).isEqualTo(MOUSE_RPT_ID);
+
+ // Invalid report
+ id = INVALID_RPT_ID;
+ mHidService.getReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, id, (int) 0);
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get())
+ .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID);
+ }
+
+ /**
+ * Test Set Report
+ *
+ * <ol>
+ * <li>1. Android creates bonding and connect the HID Device
+ * <li>2. Android Set report and verifies the report
+ * </ol>
+ */
+ @Test
+ public void hidSetReportTest() throws Exception {
+ // Keyboard report
+ mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, "010203040506070809");
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get()).isEqualTo(BluetoothHidDevice.ERROR_RSP_SUCCESS);
+ // Keyboard report - Invalid param
+ mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, "0102030405");
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get())
+ .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_PARAM);
+ // Mouse report
+ mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, "02030405");
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get()).isEqualTo(BluetoothHidDevice.ERROR_RSP_SUCCESS);
+ // Invalid report id
+ mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, "0304");
+ mFutureHandShakeIntent = SettableFuture.create();
+ assertThat(mFutureHandShakeIntent.get())
+ .isEqualTo(BluetoothHidDevice.ERROR_RSP_INVALID_RPT_ID);
}
private void reconnectionFromRemoteAndVerifyDisconnectedState() throws Exception {
@@ -383,9 +567,6 @@ public class HidHostTest {
}
private void bluetoothRestart() throws Exception {
- mContext.registerReceiver(
- mConnectionStateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
-
mAdapter.disable();
mFutureAdapterStateIntent = SettableFuture.create();
assertThat(mFutureAdapterStateIntent.get()).isEqualTo(BluetoothAdapter.STATE_OFF);