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

Commit 1270a7c6 authored by Omair Kamil's avatar Omair Kamil Committed by Gerrit Code Review
Browse files

Merge "Move forward with mechanical refactor of scanning code." into main

parents 799e1aa3 43eb6f0e
Loading
Loading
Loading
Loading
+0 −28
Original line number Diff line number Diff line
@@ -48,23 +48,6 @@ interface IBluetoothGatt {
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states, in AttributionSource attributionSource);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void registerScanner(in IScannerCallback callback, in WorkSource workSource, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void unregisterScanner(in int scannerId, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
                   in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
                            in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void stopScanForIntent(in PendingIntent intent, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void stopScan(in int scannerId, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void flushPendingBatchResults(in int scannerId, in AttributionSource attributionSource);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)")
    void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
                                in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
@@ -90,15 +73,6 @@ interface IBluetoothGatt {
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)")
    void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in AttributionSource attributionSource);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void unregisterSync(in IPeriodicAdvertisingCallback callback, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void transferSync(in BluetoothDevice bda, in int serviceData, in int syncHandle, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    void transferSetInfo(in BluetoothDevice bda, in int serviceData, in int advertisingHandle, in IPeriodicAdvertisingCallback callback,  in AttributionSource attributionSource);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback, boolean eatt_support, in AttributionSource attributionSource);

@@ -174,8 +148,6 @@ interface IBluetoothGatt {
                            in boolean confirm, in byte[] value, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void disconnectAll(in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
    int numHwTrackFiltersAvailable(in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)")
    int subrateModeRequest(in int clientIf, in BluetoothDevice device, in int subrateMode, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
+8 −2
Original line number Diff line number Diff line
@@ -6135,11 +6135,17 @@ public class AdapterService extends Service {
    }

    IBinder getBluetoothScan() {
        return mScanController == null ? null : mScanController.getBinder();
        ScanController controller = getBluetoothScanController();
        return controller == null ? null : controller.getBinder();
    }

    @Nullable
    public ScanController getBluetoothScanController() {
        if (Flags.scanManagerRefactor()) {
            return mScanController;
        } else {
            return mGattService == null ? null : mGattService.getScanController();
        }
    }

    @RequiresPermission(BLUETOOTH_CONNECT)
+25 −234
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@ import static com.android.bluetooth.Utils.checkCallerTargetSdk;

import static java.util.Objects.requireNonNull;

import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
@@ -50,12 +50,7 @@ import android.bluetooth.le.DistanceMeasurementMethod;
import android.bluetooth.le.DistanceMeasurementParams;
import android.bluetooth.le.IAdvertisingSetCallback;
import android.bluetooth.le.IDistanceMeasurementCallback;
import android.bluetooth.le.IPeriodicAdvertisingCallback;
import android.bluetooth.le.IScannerCallback;
import android.bluetooth.le.PeriodicAdvertisingParameters;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
import android.content.pm.PackageManager;
@@ -64,16 +59,11 @@ import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.WorkSource;
import android.provider.Settings;
import android.sysprop.BluetoothProperties;
import android.text.format.DateUtils;
import android.util.Log;

import com.android.bluetooth.BluetoothMetricsProto;
@@ -87,11 +77,9 @@ import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.hid.HidHostService;
import com.android.bluetooth.le_scan.TransitionalScanHelper;
import com.android.bluetooth.le_scan.ScanController;
import com.android.internal.annotations.VisibleForTesting;

import libcore.util.HexEncoding;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -135,23 +123,13 @@ public class GattService extends ProfileService {
        UUID.fromString("00001846-0000-1000-8000-00805F9B34FB"), // CSIS
    };

    /** Example raw beacons captured from a Blue Charm BC011 */
    private static final String[] TEST_MODE_BEACONS =
            new String[] {
                "020106",
                "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000",
                "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000",
                "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000",
                "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000",
            };

    private static final Integer GATT_MTU_MAX = 517;
    private static final Map<String, Integer> EARLY_MTU_EXCHANGE_PACKAGES =
            Map.of("com.teslamotors", GATT_MTU_MAX);

    @VisibleForTesting static final int GATT_CLIENT_LIMIT_PER_APP = 32;

    public final TransitionalScanHelper mTransitionalScanHelper;
    @Nullable public final ScanController mScanController;

    /** This is only used when Flags.scanManagerRefactor() is true. */
    private static GattService sGattService;
@@ -176,8 +154,6 @@ public class GattService extends ProfileService {
     */
    private final HashMap<String, Integer> mPermits = new HashMap<>();

    private final Object mTestModeLock = new Object();

    private final AdapterService mAdapterService;
    private final AdvertiseManager mAdvertiseManager;
    private final GattNativeInterface mNativeInterface;
@@ -185,9 +161,6 @@ public class GattService extends ProfileService {
    private final DistanceMeasurementManager mDistanceMeasurementManager;
    private final ActivityManager mActivityManager;
    private final PackageManager mPackageManager;
    private final HandlerThread mScanThread;

    private Handler mTestModeHandler;

    public GattService(AdapterService adapterService) {
        super(requireNonNull(adapterService));
@@ -196,9 +169,6 @@ public class GattService extends ProfileService {
        mPackageManager = requireNonNull(mAdapterService.getPackageManager());
        mCompanionDeviceManager = requireNonNull(getSystemService(CompanionDeviceManager.class));

        mTransitionalScanHelper =
                new TransitionalScanHelper(adapterService, this::isTestModeEnabled);

        Settings.Global.putInt(
                getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1);

@@ -207,11 +177,9 @@ public class GattService extends ProfileService {
        mAdvertiseManager = new AdvertiseManager(this);

        if (!Flags.scanManagerRefactor()) {
            mScanThread = new HandlerThread("BluetoothScanManager");
            mScanThread.start();
            mTransitionalScanHelper.start(mScanThread.getLooper());
            mScanController = new ScanController(adapterService);
        } else {
            mScanThread = null;
            mScanController = null;
        }
        mDistanceMeasurementManager =
                GattObjectsFactory.getInstance().createDistanceMeasurementManager(mAdapterService);
@@ -242,8 +210,9 @@ public class GattService extends ProfileService {
        }
        if (Flags.scanManagerRefactor()) {
            setGattService(null);
        } else {
            mTransitionalScanHelper.stop();
        }
        if (mScanController != null) {
            mScanController.stop();
        }
        mAdvertiseManager.clear();
        mClientMap.clear();
@@ -257,15 +226,9 @@ public class GattService extends ProfileService {
    @Override
    public void cleanup() {
        Log.d(TAG, "cleanup()");
        if (!Flags.scanManagerRefactor()) {
            mScanThread.quitSafely();
        }
        mNativeInterface.cleanup();
        mAdvertiseManager.cleanup();
        mDistanceMeasurementManager.cleanup();
        if (!Flags.scanManagerRefactor()) {
            mTransitionalScanHelper.cleanup();
        }
    }

    /** This is only used when Flags.scanManagerRefactor() is true. */
@@ -286,50 +249,15 @@ public class GattService extends ProfileService {
        sGattService = instance;
    }

    public TransitionalScanHelper getTransitionalScanHelper() {
        return mTransitionalScanHelper;
    @Nullable
    public ScanController getScanController() {
        return mScanController;
    }

    // While test mode is enabled, pretend as if the underlying stack
    // discovered a specific set of well-known beacons every second
    @Override
    protected void setTestModeEnabled(boolean enableTestMode) {
        synchronized (mTestModeLock) {
            if (mTestModeHandler == null) {
                mTestModeHandler =
                        new Handler(getMainLooper()) {
                            public void handleMessage(Message msg) {
                                synchronized (mTestModeLock) {
                                    if (!GattService.this.isTestModeEnabled()
                                            || Flags.scanManagerRefactor()) {
                                        return;
                                    }
                                    for (String test : TEST_MODE_BEACONS) {
                                        mTransitionalScanHelper.onScanResultInternal(
                                                0x1b,
                                                0x1,
                                                "DD:34:02:05:5C:4D",
                                                1,
                                                0,
                                                0xff,
                                                127,
                                                -54,
                                                0x0,
                                                HexEncoding.decode(test),
                                                "DD:34:02:05:5C:4E");
                                    }
                                    sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS);
                                }
                            }
                        };
            }
            if (enableTestMode == isTestModeEnabled()) {
                return;
            }
            super.setTestModeEnabled(enableTestMode);
            mTestModeHandler.removeMessages(0);
            mTestModeHandler.sendEmptyMessageDelayed(
                    0, enableTestMode ? DateUtils.SECOND_IN_MILLIS : 0);
        if (mScanController != null) {
            mScanController.setTestModeEnabled(enableTestMode);
        }
    }

@@ -358,7 +286,9 @@ public class GattService extends ProfileService {

    /** Notify Scan manager of bluetooth profile connection state changes */
    public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) {
        mTransitionalScanHelper.notifyProfileConnectionStateChange(profile, fromState, toState);
        if (mScanController != null) {
            mScanController.notifyProfileConnectionStateChange(profile, fromState, toState);
        }
    }

    class ServerDeathRecipient implements IBinder.DeathRecipient {
@@ -455,85 +385,6 @@ public class GattService extends ProfileService {
            service.unregisterClient(clientIf, attributionSource);
        }

        @Override
        public void registerScanner(
                IScannerCallback callback,
                WorkSource workSource,
                AttributionSource attributionSource)
                throws RemoteException {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .registerScanner(callback, workSource, attributionSource);
        }

        @Override
        public void unregisterScanner(int scannerId, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper().unregisterScanner(scannerId, attributionSource);
        }

        @Override
        public void startScan(
                int scannerId,
                ScanSettings settings,
                List<ScanFilter> filters,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .startScan(scannerId, settings, filters, attributionSource);
        }

        @Override
        public void startScanForIntent(
                PendingIntent intent,
                ScanSettings settings,
                List<ScanFilter> filters,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .registerPiAndStartScan(intent, settings, filters, attributionSource);
        }

        @Override
        public void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper().stopScan(intent, attributionSource);
        }

        @Override
        public void stopScan(int scannerId, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper().stopScan(scannerId, attributionSource);
        }

        @Override
        public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .flushPendingBatchResults(scannerId, attributionSource);
        }

        @Override
        public void clientConnect(
                int clientIf,
@@ -1108,60 +959,6 @@ public class GattService extends ProfileService {
            service.setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource);
        }

        @Override
        public void registerSync(
                ScanResult scanResult,
                int skip,
                int timeout,
                IPeriodicAdvertisingCallback callback,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .registerSync(scanResult, skip, timeout, callback, attributionSource);
        }

        @Override
        public void transferSync(
                BluetoothDevice bda,
                int serviceData,
                int syncHandle,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .transferSync(bda, serviceData, syncHandle, attributionSource);
        }

        @Override
        public void transferSetInfo(
                BluetoothDevice bda,
                int serviceData,
                int advHandle,
                IPeriodicAdvertisingCallback callback,
                AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper()
                    .transferSetInfo(bda, serviceData, advHandle, callback, attributionSource);
        }

        @Override
        public void unregisterSync(
                IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
            }
            service.getTransitionalScanHelper().unregisterSync(callback, attributionSource);
        }

        @Override
        public void disconnectAll(AttributionSource attributionSource) {
            GattService service = getService();
@@ -1171,16 +968,6 @@ public class GattService extends ProfileService {
            service.disconnectAll(attributionSource);
        }

        @Override
        public int numHwTrackFiltersAvailable(AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return 0;
            }
            return service.getTransitionalScanHelper()
                    .numHwTrackFiltersAvailable(attributionSource);
        }

        @Override
        public List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods(
                AttributionSource attributionSource) {
@@ -3702,8 +3489,9 @@ public class GattService extends ProfileService {
    }

    void dumpRegisterId(StringBuilder sb) {
        sb.append("  Scanner:\n");
        mTransitionalScanHelper.getScannerMap().dumpApps(sb, ProfileService::println);
        if (mScanController != null) {
            mScanController.dumpRegisterId(sb);
        }
        sb.append("  Client:\n");
        for (Integer appId : mClientMap.getAllAppsIds()) {
            ContextMap.App app = mClientMap.getById(appId);
@@ -3735,8 +3523,9 @@ public class GattService extends ProfileService {
        sb.append("\nRegistered App\n");
        dumpRegisterId(sb);

        sb.append("GATT Scanner Map\n");
        mTransitionalScanHelper.getScannerMap().dump(sb);
        if (mScanController != null) {
            mScanController.dump(sb);
        }

        sb.append("GATT Advertiser Map\n");
        mAdvertiseManager.dump(sb);
@@ -3796,7 +3585,9 @@ public class GattService extends ProfileService {

    @Override
    public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) {
        mTransitionalScanHelper.dumpProto(builder);
        if (mScanController != null) {
            mScanController.dumpProto(builder);
        }
    }

    private BluetoothDevice getDevice(String address) {
+16 −42
Original line number Diff line number Diff line
@@ -2034,17 +2034,10 @@ public class LeAudioService extends ProfileService {
                Log.d(TAG, "Scanner is already registered with id " + mScannerId);
                return;
            }
            if (Flags.scanManagerRefactor()) {
            mAdapterService
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
                    .registerScannerInternal(this, getAttributionSource(), null);
            } else {
                mAdapterService
                        .getBluetoothGattService()
                        .getTransitionalScanHelper()
                        .registerScannerInternal(this, getAttributionSource(), null);
            }
        }

        synchronized void stopBackgroundScan() {
@@ -2052,7 +2045,6 @@ public class LeAudioService extends ProfileService {
                Log.d(TAG, "Scanner is already unregistered");
                return;
            }
            if (Flags.scanManagerRefactor()) {
            mAdapterService
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
@@ -2062,17 +2054,6 @@ public class LeAudioService extends ProfileService {
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
                    .unregisterScannerInternal(mScannerId);
            } else {
                mAdapterService
                        .getBluetoothGattService()
                        .getTransitionalScanHelper()
                        .stopScanInternal(mScannerId);

                mAdapterService
                        .getBluetoothGattService()
                        .getTransitionalScanHelper()
                        .unregisterScannerInternal(mScannerId);
            }
            mScannerId = 0;
        }

@@ -2096,17 +2077,10 @@ public class LeAudioService extends ProfileService {
                            .setPhy(BluetoothDevice.PHY_LE_1M)
                            .build();

            if (Flags.scanManagerRefactor()) {
            mAdapterService
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
                    .startScanInternal(scannerId, settings, List.of(filter));
            } else {
                mAdapterService
                        .getBluetoothGattService()
                        .getTransitionalScanHelper()
                        .startScanInternal(scannerId, settings, List.of(filter));
            }
        }

        // Eventually we should be able to start scan from native when b/276350722 is done
+16 −0
Original line number Diff line number Diff line
@@ -36,7 +36,9 @@ import android.os.WorkSource;
import android.text.format.DateUtils;
import android.util.Log;

import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;

import libcore.util.HexEncoding;

@@ -139,6 +141,20 @@ public class ScanController {
        }
    }

    public void dumpRegisterId(StringBuilder sb) {
        sb.append("  Scanner:\n");
        mTransitionalScanHelper.getScannerMap().dumpApps(sb, ProfileService::println);
    }

    public void dump(StringBuilder sb) {
        sb.append("GATT Scanner Map\n");
        mTransitionalScanHelper.getScannerMap().dump(sb);
    }

    public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) {
        mTransitionalScanHelper.dumpProto(builder);
    }

    static class BluetoothScanBinder extends IBluetoothScan.Stub {
        private ScanController mScanController;

Loading