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

Commit 401c208d authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Add WorkSource to BLE scanning API

This will allow apps that do work on behalf of others to correctly blame
those apps for the power implications of BLE scanning.

Bug:22718669
Change-Id: I1cbca8cf7bbe1ec5b804228f466fd9dd6fc68183
parent 53ff75bb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -7302,6 +7302,8 @@ package android.bluetooth.le {
    method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
    method public void startScan(android.bluetooth.le.ScanCallback);
    method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
    method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
    method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
    method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
    method public void stopScan(android.bluetooth.le.ScanCallback);
  }
+3 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import android.bluetooth.le.ResultStorageDescriptor;
import android.os.ParcelUuid;
import android.os.WorkSource;

import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
@@ -36,8 +37,8 @@ interface IBluetoothGatt {
    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);

    void startScan(in int appIf, in boolean isServer, in ScanSettings settings,
                   in List<ScanFilter> filters,
                   in List scanStorages, in String callingPackage);
                   in List<ScanFilter> filters, in WorkSource workSource, in List scanStorages,
                   in String callingPackage);
    void stopScan(in int appIf, in boolean isServer);
    void flushPendingBatchResults(in int appIf, in boolean isServer);
    void startMultiAdvertising(in int appIf,
+53 −11
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.WorkSource;
import android.util.Log;

import java.util.ArrayList;
@@ -89,9 +90,6 @@ public final class BluetoothLeScanner {
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public void startScan(final ScanCallback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback is null");
        }
        startScan(null, new ScanSettings.Builder().build(), callback);
    }

@@ -112,14 +110,53 @@ public final class BluetoothLeScanner {
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public void startScan(List<ScanFilter> filters, ScanSettings settings,
            final ScanCallback callback) {
        startScan(filters, settings, callback, null);
        startScan(filters, settings, null, callback, null);
    }

    /**
     * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to
     * specify on behalf of which application(s) the work is being done.
     *
     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
     *                   the scan.
     * @param callback Callback used to deliver scan results.
     * @hide
     */
    @SystemApi
    @RequiresPermission(allOf = {
            Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
    public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) {
        startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback);
    }

    /**
     * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but
     * allows the caller to specify on behalf of which application(s) the work is being done.
     *
     * @param filters {@link ScanFilter}s for finding exact BLE devices.
     * @param settings Settings for the scan.
     * @param workSource {@link WorkSource} identifying the application(s) for which to blame for
     *                   the scan.
     * @param callback Callback used to deliver scan results.
     * @hide
     */
    @SystemApi
    @RequiresPermission(allOf = {
            Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
    public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
                                    final WorkSource workSource, final ScanCallback callback) {
        startScan(filters, settings, workSource, callback, null);
    }

    private void startScan(List<ScanFilter> filters, ScanSettings settings,
            final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
                           final WorkSource workSource, final ScanCallback callback,
                           List<List<ResultStorageDescriptor>> resultStorages) {
        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
        if (settings == null || callback == null) {
            throw new IllegalArgumentException("settings or callback is null");
        if (callback == null) {
            throw new IllegalArgumentException("callback is null");
        }
        if (settings == null) {
            throw new IllegalArgumentException("settings is null");
        }
        synchronized (mLeScanClients) {
            if (mLeScanClients.containsKey(callback)) {
@@ -152,7 +189,7 @@ public final class BluetoothLeScanner {
                return;
            }
            BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
                    settings, callback, resultStorages);
                    settings, workSource, callback, resultStorages);
            wrapper.startRegisteration();
        }
    }
@@ -215,7 +252,7 @@ public final class BluetoothLeScanner {
            scanFilters.add(filter.getFilter());
            scanStorages.add(filter.getStorageDescriptors());
        }
        startScan(scanFilters, settings, callback, scanStorages);
        startScan(scanFilters, settings, null, callback, scanStorages);
    }

    /**
@@ -235,6 +272,7 @@ public final class BluetoothLeScanner {

        private final ScanCallback mScanCallback;
        private final List<ScanFilter> mFilters;
        private final WorkSource mWorkSource;
        private ScanSettings mSettings;
        private IBluetoothGatt mBluetoothGatt;
        private List<List<ResultStorageDescriptor>> mResultStorages;
@@ -246,10 +284,12 @@ public final class BluetoothLeScanner {

        public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt,
                List<ScanFilter> filters, ScanSettings settings,
                ScanCallback scanCallback, List<List<ResultStorageDescriptor>> resultStorages) {
                WorkSource workSource, ScanCallback scanCallback,
                List<List<ResultStorageDescriptor>> resultStorages) {
            mBluetoothGatt = bluetoothGatt;
            mFilters = filters;
            mSettings = settings;
            mWorkSource = workSource;
            mScanCallback = scanCallback;
            mClientIf = 0;
            mResultStorages = resultStorages;
@@ -322,7 +362,9 @@ public final class BluetoothLeScanner {
                    mClientIf = clientIf;
                    try {
                        mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters,
                                mResultStorages, ActivityThread.currentOpPackageName());
                                mWorkSource, mResultStorages,
                                ActivityThread.currentOpPackageName());

                    } catch (RemoteException e) {
                        Log.e(TAG, "fail to start le scan: " + e);
                        mClientIf = -1;
+4 −0
Original line number Diff line number Diff line
@@ -121,4 +121,8 @@ interface IBatteryStats {
    void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
    long getAwakeTimeBattery();
    long getAwakeTimePlugged();

    void noteBleScanStarted(in WorkSource ws);
    void noteBleScanStopped(in WorkSource ws);
    void noteResetBleScan();
}
+18 −0
Original line number Diff line number Diff line
@@ -855,6 +855,24 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        }
    }

    @Override
    public void noteBleScanStarted(WorkSource ws) {
        enforceCallingPermission();
        Slog.d(TAG, "BLE scan started for " + ws);
    }

    @Override
    public void noteBleScanStopped(WorkSource ws) {
        enforceCallingPermission();
        Slog.d(TAG, "BLE scan stopped for " + ws);
    }

    @Override
    public void noteResetBleScan() {
        enforceCallingPermission();
        Slog.d(TAG, "BLE scan stats reset");
    }

    public boolean isOnBattery() {
        return mStats.isOnBattery();
    }