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

Commit 43eb6f0e authored by Omair Kamil's avatar Omair Kamil
Browse files

Move forward with mechanical refactor of scanning code.

Bug: 385780869
Flag: EXEMPT, mechanical refactor
Test: atest BluetoothInstrumentationTests, atest BumbleBluetoothTests
Change-Id: I1a3280975e8bd3b8d8d5cc2f64f5d4e4605e24ee
parent 9ba73fdf
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) {
@@ -3692,8 +3479,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);
@@ -3725,8 +3513,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);
@@ -3786,7 +3575,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
@@ -1970,17 +1970,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() {
@@ -1988,7 +1981,6 @@ public class LeAudioService extends ProfileService {
                Log.d(TAG, "Scanner is already unregistered");
                return;
            }
            if (Flags.scanManagerRefactor()) {
            mAdapterService
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
@@ -1998,17 +1990,6 @@ public class LeAudioService extends ProfileService {
                    .getBluetoothScanController()
                    .getTransitionalScanHelper()
                    .unregisterScannerInternal(mScannerId);
            } else {
                mAdapterService
                        .getBluetoothGattService()
                        .getTransitionalScanHelper()
                        .stopScanInternal(mScannerId);

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

@@ -2032,17 +2013,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