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

Commit 1c978e0b authored by Steven Liu's avatar Steven Liu
Browse files

Gate channel sounding feature with feature flag.

Flag: com.android.bluetooth.flags.channel_sounding_25q2_apis
Bug: 367409858
Bug: 371095923
Test: m com.android.btservices
Change-Id: Ic51673564e73919a5ecce811c1fdbceddc04cf01
parent b659e911
Loading
Loading
Loading
Loading
+37 −8
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.bluetooth.gatt;

import static android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUtils;
@@ -29,6 +31,7 @@ import android.os.RemoteException;
import android.util.Log;

import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
@@ -50,12 +53,13 @@ public class DistanceMeasurementManager {
    private static final int CS_HIGH_FREQUENCY_INTERVAL_MS = 200;

    private final AdapterService mAdapterService;
    private HandlerThread mHandlerThread;
    private final HandlerThread mHandlerThread;
    DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface;
    private final ConcurrentHashMap<String, CopyOnWriteArraySet<DistanceMeasurementTracker>>
            mRssiTrackers = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, CopyOnWriteArraySet<DistanceMeasurementTracker>>
            mCsTrackers = new ConcurrentHashMap<>();
    private final boolean mHasChannelSoundingFeature;

    /** Constructor of {@link DistanceMeasurementManager}. */
    DistanceMeasurementManager(AdapterService adapterService) {
@@ -66,6 +70,14 @@ public class DistanceMeasurementManager {
        mHandlerThread.start();
        mDistanceMeasurementNativeInterface = DistanceMeasurementNativeInterface.getInstance();
        mDistanceMeasurementNativeInterface.init(this);
        if (Flags.channelSounding25q2Apis()) {
            mHasChannelSoundingFeature =
                    adapterService
                            .getPackageManager()
                            .hasSystemFeature(FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING);
        } else {
            mHasChannelSoundingFeature = true;
        }
    }

    void cleanup() {
@@ -78,14 +90,14 @@ public class DistanceMeasurementManager {
                new DistanceMeasurementMethod.Builder(
                                DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI)
                        .build());
        if (mAdapterService.isLeChannelSoundingSupported()) {
        if (mHasChannelSoundingFeature && mAdapterService.isLeChannelSoundingSupported()) {
            methods.add(
                    new DistanceMeasurementMethod.Builder(
                                    DistanceMeasurementMethod
                                            .DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING)
                            .build());
        }
        return methods.toArray(new DistanceMeasurementMethod[methods.size()]);
        return methods.toArray(new DistanceMeasurementMethod[0]);
    }

    void startDistanceMeasurement(
@@ -121,8 +133,16 @@ public class DistanceMeasurementManager {
                startRssiTracker(tracker);
                break;
            case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING:
                if (!mAdapterService.isLeChannelSoundingSupported()
                        || !mAdapterService.isConnected(params.getDevice())) {
                if (!mHasChannelSoundingFeature
                        || !mAdapterService.isLeChannelSoundingSupported()) {
                    Log.e(TAG, "Channel Sounding is not supported.");
                    invokeStartFail(
                            callback,
                            params.getDevice(),
                            BluetoothStatusCodes.FEATURE_NOT_SUPPORTED);
                    return;
                }
                if (!mAdapterService.isConnected(params.getDevice())) {
                    Log.e(TAG, "Device " + params.getDevice() + " is not connected");
                    invokeStartFail(
                            callback,
@@ -196,17 +216,26 @@ public class DistanceMeasurementManager {
    }

    int getChannelSoundingMaxSupportedSecurityLevel(BluetoothDevice remoteDevice) {
        if (mHasChannelSoundingFeature && mAdapterService.isLeChannelSoundingSupported()) {
            return ChannelSoundingParams.CS_SECURITY_LEVEL_ONE;
        }
        return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN;
    }

    int getLocalChannelSoundingMaxSupportedSecurityLevel() {
        if (mHasChannelSoundingFeature && mAdapterService.isLeChannelSoundingSupported()) {
            return ChannelSoundingParams.CS_SECURITY_LEVEL_ONE;
        }
        return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN;
    }

    Set<Integer> getChannelSoundingSupportedSecurityLevels() {
        // TODO(b/378685103): get it from the HAL when level 4 is supported and HAL v2 is available.
        if (mHasChannelSoundingFeature && mAdapterService.isLeChannelSoundingSupported()) {
            return Set.of(ChannelSoundingParams.CS_SECURITY_LEVEL_ONE);
        }
        throw new UnsupportedOperationException("Channel Sounding is not supported.");
    }

    private synchronized int stopRssiTracker(UUID uuid, String identityAddress, boolean timeout) {
        CopyOnWriteArraySet<DistanceMeasurementTracker> set = mRssiTrackers.get(identityAddress);
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.bluetooth.gatt;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
@@ -30,6 +31,7 @@ import android.bluetooth.le.DistanceMeasurementMethod;
import android.bluetooth.le.DistanceMeasurementParams;
import android.bluetooth.le.DistanceMeasurementResult;
import android.bluetooth.le.IDistanceMeasurementCallback;
import android.content.pm.PackageManager;
import android.os.RemoteException;

import androidx.test.filters.SmallTest;
@@ -57,6 +59,7 @@ public class DistanceMeasurementManagerTest {

    @Mock private DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface;
    @Mock private AdapterService mAdapterService;
    @Mock private PackageManager mPackageManager;
    @Mock private IDistanceMeasurementCallback mCallback;
    private DistanceMeasurementManager mDistanceMeasurementManager;
    private UUID mUuid;
@@ -67,6 +70,8 @@ public class DistanceMeasurementManagerTest {

    @Before
    public void setUp() throws Exception {
        doReturn(mPackageManager).when(mAdapterService).getPackageManager();
        doReturn(true).when(mPackageManager).hasSystemFeature(any());
        doReturn(IDENTITY_ADDRESS).when(mAdapterService).getIdentityAddress(IDENTITY_ADDRESS);
        DistanceMeasurementNativeInterface.setInstance(mDistanceMeasurementNativeInterface);
        mDistanceMeasurementManager = new DistanceMeasurementManager(mAdapterService);