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

Commit cf8aad28 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add tests for BluetoothHapClientBinder"

parents 96fbabdb 65010da7
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1209,6 +1209,8 @@ public class HapClientService extends ProfileService {
    @VisibleForTesting
    static class BluetoothHapClientBinder extends IBluetoothHapClient.Stub
            implements IProfileServiceBinder {
        @VisibleForTesting
        boolean mIsTesting = false;
        private HapClientService mService;

        BluetoothHapClientBinder(HapClientService svc) {
@@ -1216,6 +1218,9 @@ public class HapClientService extends ProfileService {
        }

        private HapClientService getService(AttributionSource source) {
            if (mIsTesting) {
                return mService;
            }
            if (!Utils.checkCallerIsSystemOrActiveUser(TAG)
                    || !Utils.checkServiceAvailable(mService, TAG)
                    || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) {
+149 −34
Original line number Diff line number Diff line
@@ -17,9 +17,26 @@

package com.android.bluetooth.hap;

import static org.mockito.Mockito.*;

import android.bluetooth.*;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHapPresetInfo;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothHapClientCallback;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -28,32 +45,32 @@ import android.os.Binder;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver;

import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -77,6 +94,8 @@ public class HapClientTest {
    private BluetoothDevice mDevice3;
    private Context mTargetContext;
    private HapClientService mService;
    private HapClientService.BluetoothHapClientBinder mServiceBinder;
    private AttributionSource mAttributionSource;
    private HasIntentReceiver mHasIntentReceiver;
    private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mIntentQueue;

@@ -116,11 +135,14 @@ public class HapClientTest {
        doReturn(true, false).when(mAdapterService).isStartedProfile(anyString());

        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAttributionSource = mAdapter.getAttributionSource();

        startService();
        mService.mHapClientNativeInterface = mNativeInterface;
        mService.mFactory = mServiceFactory;
        doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService();
        mServiceBinder = (HapClientService.BluetoothHapClientBinder) mService.initBinder();
        mServiceBinder.mIsTesting = true;

        // Set up the State Changed receiver
        IntentFilter filter = new IntentFilter();
@@ -260,7 +282,7 @@ public class HapClientTest {
     * Test get/set policy for BluetoothDevice
     */
    @Test
    public void testGetSetPolicy() {
    public void testGetSetPolicy() throws Exception {
        when(mDatabaseManager
                .getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
@@ -278,9 +300,14 @@ public class HapClientTest {
        when(mDatabaseManager
                .getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
        // call getConnectionPolicy via binder
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        mServiceBinder.getConnectionPolicy(mDevice, mAttributionSource, recv);
        int policy = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue);
        Assert.assertEquals("Setting device policy to POLICY_ALLOWED",
                BluetoothProfile.CONNECTION_POLICY_ALLOWED,
                mService.getConnectionPolicy(mDevice));
                BluetoothProfile.CONNECTION_POLICY_ALLOWED, policy);
    }

    /**
@@ -398,7 +425,7 @@ public class HapClientTest {
     * Test that an outgoing connection times out
     */
    @Test
    public void testOutgoingConnectTimeout() {
    public void testOutgoingConnectTimeout() throws Exception {
        // Update the device policy so okToConnect() returns true
        when(mDatabaseManager
                .getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
@@ -415,19 +442,22 @@ public class HapClientTest {
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTING,
                mService.getConnectionState(mDevice));

        // Verify the connection state broadcast, and that we are in Disconnected state
        // Verify the connection state broadcast, and that we are in Disconnected state via binder
        verifyConnectionStateIntent(HapClientStateMachine.sConnectTimeoutMs * 2,
                mDevice, BluetoothProfile.STATE_DISCONNECTED,
                BluetoothProfile.STATE_CONNECTING);
        Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED,
                mService.getConnectionState(mDevice));
                mDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING);
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        mServiceBinder.getConnectionState(mDevice, mAttributionSource, recv);
        int state = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue);
        Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, state);
    }

    /**
     * Test that an outgoing connection to two device that have HAS UUID is successful
     */
    @Test
    public void testConnectTwo() {
    public void testConnectTwo() throws Exception {
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));

@@ -438,7 +468,12 @@ public class HapClientTest {
        BluetoothDevice Device2 = TestUtils.getTestDevice(mAdapter, 1);
        testConnectingDevice(Device2);

        List<BluetoothDevice> devices = mService.getConnectedDevices();
        // indirect call of mService.getConnectedDevices to test BluetoothHearingAidBinder
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
                SynchronousResultReceiver.get();
        mServiceBinder.getConnectedDevices(mAttributionSource, recv);
        List<BluetoothDevice> devices = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(null);
        Assert.assertTrue(devices.contains(mDevice));
        Assert.assertTrue(devices.contains(Device2));
        Assert.assertNotEquals(mDevice, Device2);
@@ -457,7 +492,7 @@ public class HapClientTest {
     * Test getting HAS coordinated sets.
     */
    @Test
    public void testGetHapGroupCoordinatedOps() {
    public void testGetHapGroupCoordinatedOps() throws Exception {
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
@@ -482,7 +517,12 @@ public class HapClientTest {
        Assert.assertEquals(3, mService.getHapGroup(mDevice3));

        /* Third one has no coordinated operations support but is part of the group */
        Assert.assertEquals(2, mService.getHapGroup(mDevice2));
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        mServiceBinder.getHapGroup(mDevice2, mAttributionSource, recv);
        int hapGroup = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue);
        Assert.assertEquals(2, hapGroup);
    }

    /**
@@ -505,7 +545,7 @@ public class HapClientTest {
            throw e.rethrowFromSystemServer();
        }

        mService.selectPreset(mDevice, 0x01);
        mServiceBinder.selectPreset(mDevice, 0x01, mAttributionSource);
        verify(mNativeInterface, times(1))
                .selectActivePreset(eq(mDevice), eq(0x01));
    }
@@ -531,7 +571,7 @@ public class HapClientTest {
            throw e.rethrowFromSystemServer();
        }

        mService.selectPresetForGroup(0x03, 0x01);
        mServiceBinder.selectPresetForGroup(0x03, 0x01, mAttributionSource);
        verify(mNativeInterface, times(1))
                .groupSelectActivePreset(eq(0x03), eq(0x01));
    }
@@ -546,7 +586,7 @@ public class HapClientTest {
        testConnectingDevice(mDevice);

        // Verify Native Interface call
        mService.switchToNextPreset(mDevice);
        mServiceBinder.switchToNextPreset(mDevice, mAttributionSource);
        verify(mNativeInterface, times(1))
                .nextActivePreset(eq(mDevice));
    }
@@ -563,7 +603,7 @@ public class HapClientTest {
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice3), flags);

        // Verify Native Interface call
        mService.switchToNextPresetForGroup(0x03);
        mServiceBinder.switchToNextPresetForGroup(0x03, mAttributionSource);
        verify(mNativeInterface, times(1)).groupNextActivePreset(eq(0x03));
    }

@@ -577,7 +617,7 @@ public class HapClientTest {
        testConnectingDevice(mDevice);

        // Verify Native Interface call
        mService.switchToPreviousPreset(mDevice);
        mServiceBinder.switchToPreviousPreset(mDevice, mAttributionSource);
        verify(mNativeInterface, times(1))
                .previousActivePreset(eq(mDevice));
    }
@@ -596,7 +636,7 @@ public class HapClientTest {
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);

        // Verify Native Interface call
        mService.switchToPreviousPresetForGroup(0x02);
        mServiceBinder.switchToPreviousPresetForGroup(0x02, mAttributionSource);
        verify(mNativeInterface, times(1)).groupPreviousActivePreset(eq(0x02));
    }

@@ -604,26 +644,45 @@ public class HapClientTest {
     * Test that getActivePresetIndex returns cached value.
     */
    @Test
    public void testGetActivePresetIndex() {
    public void testGetActivePresetIndex() throws Exception {
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);
        testOnPresetSelected(mDevice, 0x01);

        // Verify cached value
        Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice));
        // Verify cached value via binder
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        mServiceBinder.getActivePresetIndex(mDevice, mAttributionSource, recv);
        int presetIndex = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue);
        Assert.assertEquals(0x01, presetIndex);
    }

    /**
     * Test that getActivePresetInfo returns cached value for valid parameters.
     */
    @Test
    public void testGetActivePresetInfo() {
    public void testGetPresetInfoAndActivePresetInfo() throws Exception {
        doReturn(new ParcelUuid[]{BluetoothUuid.HAS}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice2);

        // Check when active preset is not known yet
        final SynchronousResultReceiver<List<BluetoothHapPresetInfo>> presetListRecv =
                SynchronousResultReceiver.get();
        mServiceBinder.getAllPresetInfo(mDevice2, mAttributionSource, presetListRecv);
        List<BluetoothHapPresetInfo> presetList = presetListRecv.awaitResultNoInterrupt(
                Duration.ofMillis(TIMEOUT_MS)).getValue(null);

        final SynchronousResultReceiver<BluetoothHapPresetInfo> presetRecv =
                SynchronousResultReceiver.get();
        mServiceBinder.getPresetInfo(mDevice2, 0x01, mAttributionSource, presetRecv);
        BluetoothHapPresetInfo presetInfo = presetRecv.awaitResultNoInterrupt(
                Duration.ofMillis(TIMEOUT_MS)).getValue(null);
        Assert.assertTrue(presetList.contains(presetInfo));
        Assert.assertEquals(0x01, presetInfo.getIndex());

        Assert.assertEquals(BluetoothHapClient.PRESET_INDEX_UNAVAILABLE,
                mService.getActivePresetIndex(mDevice2));
        Assert.assertEquals(null, mService.getActivePresetInfo(mDevice2));
@@ -633,9 +692,13 @@ public class HapClientTest {

        // Check when active preset is known
        Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice2));
        BluetoothHapPresetInfo info = mService.getActivePresetInfo(mDevice2);
        final SynchronousResultReceiver<BluetoothHapPresetInfo> recv =
                SynchronousResultReceiver.get();
        mServiceBinder.getActivePresetInfo(mDevice2, mAttributionSource, recv);
        BluetoothHapPresetInfo info = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(null);
        Assert.assertNotNull(info);
        Assert.assertEquals(0x01, info.getIndex());
        Assert.assertEquals("One", info.getName());
    }

    /**
@@ -647,7 +710,7 @@ public class HapClientTest {
                .getRemoteUuids(any(BluetoothDevice.class));
        testConnectingDevice(mDevice);

        mService.setPresetName(mDevice, 0x00, "ExamplePresetName");
        mServiceBinder.setPresetName(mDevice, 0x00, "ExamplePresetName", mAttributionSource);
        verify(mNativeInterface, times(0))
                .setPresetName(eq(mDevice), eq(0x00), eq("ExamplePresetName"));
        try {
@@ -678,7 +741,8 @@ public class HapClientTest {
        int flags = 0x21;
        mNativeInterface.onFeaturesUpdate(getByteAddress(mDevice), flags);

        mService.setPresetNameForGroup(test_group, 0x00, "ExamplePresetName");
        mServiceBinder.setPresetNameForGroup(
                test_group, 0x00, "ExamplePresetName", mAttributionSource);
        try {
            verify(mCallback, after(TIMEOUT_MS).times(1)).onSetPresetNameForGroupFailed(eq(test_group),
                    eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX));
@@ -937,6 +1001,57 @@ public class HapClientTest {
        }
    }

    @Test
    public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception {
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
                SynchronousResultReceiver.get();
        mServiceBinder.getDevicesMatchingConnectionStates(null, mAttributionSource, recv);
        List<BluetoothDevice> devices = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(null);
        Assert.assertEquals(0, devices.size());
    }

    @Test
    public void testServiceBinderSetConnectionPolicy() throws Exception {
        final SynchronousResultReceiver<Boolean> recv = SynchronousResultReceiver.get();
        boolean defaultRecvValue = false;
        mServiceBinder.setConnectionPolicy(
                mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, mAttributionSource, recv);
        Assert.assertTrue(recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue));
        verify(mDatabaseManager).setProfileConnectionPolicy(
                mDevice, BluetoothProfile.HAP_CLIENT, BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
    }

    @Test
    public void testServiceBinderGetFeatures() throws Exception {
        final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
        int defaultRecvValue = -1000;
        mServiceBinder.getFeatures(mDevice, mAttributionSource, recv);
        int features = recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS))
                .getValue(defaultRecvValue);
        Assert.assertEquals(0x00, features);
    }

    @Test
    public void testServiceBinderRegisterUnregisterCallback() throws Exception {
        IBluetoothHapClientCallback callback = Mockito.mock(IBluetoothHapClientCallback.class);
        Binder binder = Mockito.mock(Binder.class);
        when(callback.asBinder()).thenReturn(binder);

        int size = mService.mCallbacks.getRegisteredCallbackCount();
        SynchronousResultReceiver<Void> recv = SynchronousResultReceiver.get();
        mServiceBinder.registerCallback(callback, mAttributionSource, recv);
        recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)).getValue(null);
        Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount());

        recv = SynchronousResultReceiver.get();
        mServiceBinder.unregisterCallback(callback, mAttributionSource, recv);
        recv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS)).getValue(null);
        Assert.assertEquals(size, mService.mCallbacks.getRegisteredCallbackCount());

    }

    /**
     * Helper function to test device connecting
     */