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

Commit 6ea19557 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add tests for BluetoothHapClientBinder" am: cf8aad28

parents 715b2dd3 cf8aad28
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
     */