From 6771d629b5ad0b9296f0febaa2300fdaf1f90515 Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Fri, 15 Jan 2016 18:14:47 -0800 Subject: [PATCH] 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: Ib64af0b6a5d37721a6067ac4e5c39c01f921b56b --- api/system-current.txt | 2 + core/java/android/bluetooth/IBluetoothGatt.aidl | 5 +- .../android/bluetooth/le/BluetoothLeScanner.java | 64 ++++++++++++++++++---- .../com/android/internal/app/IBatteryStats.aidl | 3 + .../com/android/server/am/BatteryStatsService.java | 12 ++++ 5 files changed, 73 insertions(+), 13 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 12b9b325c759..6972a796b0e6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7514,6 +7514,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.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.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback); method public void startTruncatedScan(java.util.List, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback); method public void stopScan(android.bluetooth.le.ScanCallback); } diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index 3660be7c8eb5..6b5f77faacd3 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -23,6 +23,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; @@ -35,8 +36,8 @@ interface IBluetoothGatt { List getDevicesMatchingConnectionStates(in int[] states); void startScan(in int appIf, in boolean isServer, in ScanSettings settings, - in List filters, - in List scanStorages, in String callingPackage); + in List 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, diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 2ba87744d087..03449ccec355 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -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 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 filters, ScanSettings settings, + final WorkSource workSource, final ScanCallback callback) { + startScan(filters, settings, workSource, callback, null); } private void startScan(List filters, ScanSettings settings, - final ScanCallback callback, List> resultStorages) { + final WorkSource workSource, final ScanCallback callback, + List> 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 mFilters; + private final WorkSource mWorkSource; private ScanSettings mSettings; private IBluetoothGatt mBluetoothGatt; private List> mResultStorages; @@ -246,10 +284,12 @@ public final class BluetoothLeScanner { public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt, List filters, ScanSettings settings, - ScanCallback scanCallback, List> resultStorages) { + WorkSource workSource, ScanCallback scanCallback, + List> 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; diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 3b9b8dbd4c71..ec53a2ec6366 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -121,4 +121,7 @@ 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); } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 82862e8a1935..0f7dff27b4fc 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -855,6 +855,18 @@ 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); + } + public boolean isOnBattery() { return mStats.isOnBattery(); } -- 2.11.0