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

Commit 4292d792 authored by Steven Liu's avatar Steven Liu Committed by Gerrit Code Review
Browse files

Merge "Gate channel sounding feature with feature flag." into main

parents 6b5b65a3 1c978e0b
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);