Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd3675b5 authored by Gopi Sakshihally Bhuthaiah's avatar Gopi Sakshihally Bhuthaiah Committed by Gopi Sakshihally Bhuthaiah (xWF)
Browse files

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
parent 742cfda9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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. -->
+241 −60
Original line number Diff line number Diff line
/*
 * 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,12 +84,12 @@ 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())) {
                    switch (intent.getAction()) {
                        case BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED:
                            int state =
                                    intent.getIntExtra(
                                            BluetoothProfile.EXTRA_STATE, BluetoothAdapter.ERROR);
@@ -90,9 +100,11 @@ public class HidHostTest {
                                    mFutureConnectionIntent.set(state);
                                }
                            }
                    } else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
                            break;
                        case BluetoothDevice.ACTION_PAIRING_REQUEST:
                            mBumble.getRemoteDevice().setPairingConfirmation(true);
                    } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
                            break;
                        case BluetoothAdapter.ACTION_STATE_CHANGED:
                            int adapterState =
                                    intent.getIntExtra(
                                            BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
@@ -103,11 +115,12 @@ public class HidHostTest {
                                    mFutureAdapterStateIntent.set(adapterState);
                                }
                            }
                    } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(
                            intent.getAction())) {
                            break;
                        case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                            int bondState =
                                    intent.getIntExtra(
                                        BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
                                            BluetoothDevice.EXTRA_BOND_STATE,
                                            BluetoothDevice.ERROR);
                            Log.i(TAG, "Bond state change:" + bondState);
                            if (bondState == BluetoothDevice.BOND_BONDED
                                    || bondState == BluetoothDevice.BOND_NONE) {
@@ -115,10 +128,54 @@ public class HidHostTest {
                                    mFutureBondIntent.set(bondState);
                                }
                            }
                    } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction())) {
                            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);
                            }
                            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);
                            }
                            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);