diff options
author | 2024-06-12 09:09:34 +0000 | |
---|---|---|
committer | 2024-07-31 07:03:33 +0000 | |
commit | cd3675b5d7743886fcd01e5ea5fb4a25a841a3ae (patch) | |
tree | 249dc58573e083f3311d0e2d11268432c5a34de5 | |
parent | 742cfda900780f17ca9af480d1246bcc3cae1c3b (diff) |
Bumble Java HID Test cases
1. virtual unplug test
2. getProtocolMode test
3. setProtocolMode test
4. getReport test
5. setReport test
Bug: 340549544
Test: atest -v HidHostTest
Flag: EXEMPT Test case
Change-Id: I788c1f6b3c255bb171128e3361da2f44bbed3a74
-rw-r--r-- | framework/tests/bumble/AndroidTest.xml | 1 | ||||
-rw-r--r-- | framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java | 301 |
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); |