package com.android.bluetooth.gatt;
import android.bluetooth.le.ScanSettings;
+import android.os.Binder;
+import android.os.WorkSource;
+import android.os.ServiceManager;
+import android.os.RemoteException;
+import com.android.internal.app.IBatteryStats;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
/* GattService is needed to add scan event protos to be dumped later */
GattService gattService;
+ /* Battery stats is used to keep track of scans and result stats */
+ IBatteryStats batteryStats;
+
class LastScan {
long duration;
long timestamp;
static final int SCAN_TIMEOUT_MS = 30 * 60 * 1000;
String appName;
+ WorkSource workSource; // Used for BatteryStats
int scansStarted = 0;
int scansStopped = 0;
boolean isScanning = false;
long stopTime = 0;
int results = 0;
- public AppScanStats(String name, ContextMap map, GattService service) {
+ public AppScanStats(String name, WorkSource source, ContextMap map, GattService service) {
appName = name;
contextMap = map;
gattService = service;
+ batteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batterystats"));
+
+ if (source == null) {
+ // Bill the caller if the work source isn't passed through
+ source = new WorkSource(Binder.getCallingUid(), appName);
+ }
+ workSource = source;
}
synchronized void addResult() {
scanEvent.setEventTimeMillis(System.currentTimeMillis());
scanEvent.setInitiator(truncateAppName(appName));
gattService.addScanEvent(scanEvent);
+
+ try {
+ batteryStats.noteBleScanStarted(workSource);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
}
synchronized void recordScanStop() {
scanEvent.setEventTimeMillis(System.currentTimeMillis());
scanEvent.setInitiator(truncateAppName(appName));
gattService.addScanEvent(scanEvent);
+
+ try {
+ batteryStats.noteBleScanStopped(workSource);
+ } catch (RemoteException e) {
+ /* ignore */
+ }
}
synchronized void setScanTimeout() {
import android.os.IBinder.DeathRecipient;
import android.os.IInterface;
import android.os.RemoteException;
+import android.os.WorkSource;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashSet;
/**
* Add an entry to the application context list.
*/
- void add(UUID uuid, C callback, T info, GattService service) {
+ void add(UUID uuid, WorkSource workSource, C callback, T info, GattService service) {
String appName = service.getPackageManager().getNameForUid(
Binder.getCallingUid());
if (appName == null) {
synchronized (mApps) {
AppScanStats appScanStats = mAppScanStats.get(appName);
if (appScanStats == null) {
- appScanStats = new AppScanStats(appName, this, service);
+ appScanStats = new AppScanStats(appName, workSource, this, service);
mAppScanStats.put(appName, appScanStats);
}
mApps.add(new App(uuid, callback, info, appName, appScanStats));
PendingIntent intent;
ScanSettings settings;
List<ScanFilter> filters;
- WorkSource workSource;
String callingPackage;
@Override
service.unregisterClient(clientIf);
}
- public void registerScanner(IScannerCallback callback) {
+ public void registerScanner(IScannerCallback callback, WorkSource workSource) {
GattService service = getService();
if (service == null) return;
- service.registerScanner(callback);
+ service.registerScanner(callback, workSource);
}
public void unregisterScanner(int scannerId) {
}
@Override
- public void startScan(int scannerId, ScanSettings settings,
- List<ScanFilter> filters, WorkSource workSource, List storages,
- String callingPackage) {
+ public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
+ List storages, String callingPackage) {
GattService service = getService();
if (service == null) return;
- service.startScan(scannerId, settings, filters, workSource, storages,
- callingPackage);
+ service.startScan(scannerId, settings, filters, storages, callingPackage);
}
@Override
return deviceList;
}
- void registerScanner(IScannerCallback callback) {
+ void registerScanner(IScannerCallback callback, WorkSource workSource) {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
UUID uuid = UUID.randomUUID();
if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid);
- mScannerMap.add(uuid, callback, null, this);
+
+ if (workSource != null) {
+ enforceImpersonatationPermission();
+ }
+
+ mScannerMap.add(uuid, workSource, callback, null, this);
mScanManager.registerScanner(uuid);
}
mScanManager.unregisterScanner(scannerId);
}
- void startScan(int scannerId, ScanSettings settings,
- List<ScanFilter> filters, WorkSource workSource,
+ void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
List<List<ResultStorageDescriptor>> storages, String callingPackage) {
if (DBG) Log.d(TAG, "start scan with filters");
enforceAdminPermission();
if (needsPrivilegedPermissionForScan(settings)) {
enforcePrivilegedPermission();
}
- if (workSource != null) {
- enforceImpersonatationPermission();
- } else {
- // Blame the caller if the work source is unspecified.
- workSource = new WorkSource(Binder.getCallingUid(), callingPackage);
- }
- final ScanClient scanClient = new ScanClient(scannerId, settings, filters, workSource,
- storages);
+ final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages);
scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps,
callingPackage);
scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission(
if (needsPrivilegedPermissionForScan(settings)) {
enforcePrivilegedPermission();
}
- // Blame the caller if the work source is unspecified.
- WorkSource workSource = new WorkSource(Binder.getCallingUid(), callingPackage);
UUID uuid = UUID.randomUUID();
if (DBG) Log.d(TAG, "startScan(PI) - UUID=" + uuid);
piInfo.intent = pendingIntent;
piInfo.settings = settings;
piInfo.filters = filters;
- piInfo.workSource = workSource;
piInfo.callingPackage = callingPackage;
- mScannerMap.add(uuid, null, piInfo, this);
+ mScannerMap.add(uuid, null, null, piInfo, this);
mScanManager.registerScanner(uuid);
}
void continuePiStartScan(int scannerId, PendingIntentInfo piInfo) {
final ScanClient scanClient =
- new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.workSource, null);
+ new ScanClient(scannerId, piInfo.settings, piInfo.filters, null);
scanClient.hasLocationPermission =
true; // Utils.checkCallerHasLocationPermission(this, mAppOps,
// piInfo.callingPackage);
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
- mClientMap.add(uuid, callback, null, this);
+ mClientMap.add(uuid, null, callback, null, this);
gattClientRegisterAppNative(uuid.getLeastSignificantBits(),
uuid.getMostSignificantBits());
}
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid);
- mServerMap.add(uuid, callback, null, this);
+ mServerMap.add(uuid, null, callback, null, this);
gattServerRegisterAppNative(uuid.getLeastSignificantBits(),
uuid.getMostSignificantBits());
}
import android.bluetooth.le.ResultStorageDescriptor;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
-import android.os.WorkSource;
import java.util.List;
import java.util.Objects;
// Pre-M apps are allowed to get scan results even if location is disabled
boolean legacyForegroundApp;
- // Who is responsible for this scan.
- WorkSource workSource;
-
AppScanStats stats = null;
private static final ScanSettings DEFAULT_SCAN_SETTINGS = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
ScanClient(int scannerId) {
- this(scannerId, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null, null);
+ this(scannerId, new UUID[0], DEFAULT_SCAN_SETTINGS, null, null);
}
ScanClient(int scannerId, UUID[] uuids) {
- this(scannerId, uuids, DEFAULT_SCAN_SETTINGS, null, null, null);
+ this(scannerId, uuids, DEFAULT_SCAN_SETTINGS, null, null);
}
ScanClient(int scannerId, ScanSettings settings,
List<ScanFilter> filters) {
- this(scannerId, new UUID[0], settings, filters, null, null);
- }
-
- ScanClient(int scannerId, ScanSettings settings,
- List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages) {
- this(scannerId, new UUID[0], settings, filters, null, storages);
+ this(scannerId, new UUID[0], settings, filters, null);
}
- ScanClient(int scannerId, ScanSettings settings,
- List<ScanFilter> filters, WorkSource workSource,
- List<List<ResultStorageDescriptor>> storages) {
- this(scannerId, new UUID[0], settings, filters, workSource, storages);
+ ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters,
+ List<List<ResultStorageDescriptor>> storages) {
+ this(scannerId, new UUID[0], settings, filters, storages);
}
- private ScanClient(int scannerId, UUID[] uuids, ScanSettings settings,
- List<ScanFilter> filters, WorkSource workSource,
+ private ScanClient(int scannerId, UUID[] uuids, ScanSettings settings, List<ScanFilter> filters,
List<List<ResultStorageDescriptor>> storages) {
this.scannerId = scannerId;
this.uuids = uuids;
this.settings = settings;
this.filters = filters;
- this.workSource = workSource;
this.storages = storages;
}
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.internal.app.IBatteryStats;
import java.util.ArrayDeque;
import java.util.Collections;
private Integer curUsedTrackableAdvertisements;
private GattService mService;
- private IBatteryStats mBatteryStats;
private BroadcastReceiver mBatchAlarmReceiver;
private boolean mBatchAlarmReceiverRegistered;
private ScanNative mScanNative;
}
void start() {
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batterystats"));
HandlerThread thread = new HandlerThread("BluetoothScanManager");
thread.start();
mHandler = new ClientHandler(thread.getLooper());
mHandler.sendMessageDelayed(msg, AppScanStats.SCAN_TIMEOUT_MS);
}
}
-
- // Update BatteryStats with this workload.
- try {
- mBatteryStats.noteBleScanStarted(client.workSource);
- } catch (RemoteException e) {
- /* ignore */
- }
}
}
if (client == null) return;
if (mRegularScanClients.contains(client)) {
- // Update BatteryStats with this workload.
- try {
- // The ScanClient passed in just holds the scannerId. We retrieve the real
- // client, which may have workSource set.
- ScanClient workClient = mScanNative.getRegularScanClient(client.scannerId);
- if (workClient != null) mBatteryStats.noteBleScanStopped(workClient.workSource);
- } catch (RemoteException e) {
- /* ignore */
- }
-
mScanNative.stopRegularScan(client);
if (mScanNative.numRegularScanClients() == 0) {