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

Commit 5e4a29fd authored by Vinay Kalia's avatar Vinay Kalia
Browse files

Revert "Revert "Improve BLE scan attribution to facilitate debugging power issues""

This reverts commit 545e8b38.

BUG: 62389939
Test: Tested a few BLE scanning applications which included misbehaving
Change-Id: I5e0884159e8e95ae15b591d16eb85ce150ce86bb
parent 9fdf6e35
Loading
Loading
Loading
Loading
+98 −66
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;

import com.android.bluetooth.btservice.BluetoothProto;
/**
@@ -55,15 +56,17 @@ import com.android.bluetooth.btservice.BluetoothProto;
        boolean background;
        boolean filtered;
        int results;
        int scannerId;

        public LastScan(long timestamp, long duration, boolean opportunistic, boolean background,
                boolean filtered) {
                boolean filtered, int scannerId) {
            this.duration = duration;
            this.timestamp = timestamp;
            this.opportunistic = opportunistic;
            this.background = background;
            this.filtered = filtered;
            this.results = 0;
            this.scannerId = scannerId;
        }
    }

@@ -82,12 +85,13 @@ import com.android.bluetooth.btservice.BluetoothProto;
    WorkSource workSource; // Used for BatteryStats
    int scansStarted = 0;
    int scansStopped = 0;
    boolean isScanning = false;
    boolean isRegistered = false;
    long minScanTime = Long.MAX_VALUE;
    long maxScanTime = 0;
    long totalScanTime = 0;
    List<LastScan> lastScans = new ArrayList<LastScan>(NUM_SCAN_DURATIONS_KEPT + 1);
    long mScanStartTime = 0;
    long mTotalScanTime = 0;
    List<LastScan> lastScans = new ArrayList<LastScan>(NUM_SCAN_DURATIONS_KEPT);
    HashMap<Integer, LastScan> ongoingScans = new HashMap<Integer, LastScan>();
    long startTime = 0;
    long stopTime = 0;
    int results = 0;
@@ -105,9 +109,10 @@ import com.android.bluetooth.btservice.BluetoothProto;
        workSource = source;
    }

    synchronized void addResult() {
        if (!lastScans.isEmpty()) {
            int batteryStatsResults = ++lastScans.get(lastScans.size() - 1).results;
    synchronized void addResult(int scannerId) {
        LastScan scan = getScanFromScannerId(scannerId);
        if (scan != null) {
            int batteryStatsResults = ++scan.results;

            // Only update battery stats after receiving 100 new results in order
            // to lower the cost of the binder transaction
@@ -123,20 +128,27 @@ import com.android.bluetooth.btservice.BluetoothProto;
        results++;
    }

    synchronized void recordScanStart(ScanSettings settings, boolean filtered) {
        if (isScanning)
            return;
    boolean isScanning() {
        return !ongoingScans.isEmpty();
    }

    LastScan getScanFromScannerId(int scannerId) {
        return ongoingScans.get(scannerId);
    }

    synchronized void recordScanStart(ScanSettings settings, boolean filtered, int scannerId) {
        LastScan existingScan = getScanFromScannerId(scannerId);
        if (existingScan != null) {
            return;
        }
        this.scansStarted++;
        isScanning = true;
        startTime = SystemClock.elapsedRealtime();

        LastScan scan = new LastScan(startTime, 0, false, false, filtered);
        LastScan scan = new LastScan(startTime, 0, false, false, filtered, scannerId);
        if (settings != null) {
          scan.opportunistic = settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC;
          scan.background = (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0;
        }
        lastScans.add(scan);

        BluetoothProto.ScanEvent scanEvent = new BluetoothProto.ScanEvent();
        scanEvent.setScanEventType(BluetoothProto.ScanEvent.SCAN_EVENT_START);
@@ -145,33 +157,33 @@ import com.android.bluetooth.btservice.BluetoothProto;
        scanEvent.setInitiator(truncateAppName(appName));
        gattService.addScanEvent(scanEvent);

        if (!isScanning()) {
            try {
                boolean isUnoptimized = !(scan.filtered || scan.background || scan.opportunistic);
                mScanStartTime = startTime;
                batteryStats.noteBleScanStarted(workSource, isUnoptimized);
            } catch (RemoteException e) {
                /* ignore */
            }
        }

    synchronized void recordScanStop() {
        if (!isScanning)
          return;
        ongoingScans.put(scannerId, scan);
    }

    synchronized void recordScanStop(int scannerId) {
        LastScan scan = getScanFromScannerId(scannerId);
        if (scan == null) {
            return;
        }
        this.scansStopped++;
        isScanning = false;
        stopTime = SystemClock.elapsedRealtime();
        long scanDuration = stopTime - startTime;

        minScanTime = Math.min(scanDuration, minScanTime);
        maxScanTime = Math.max(scanDuration, maxScanTime);
        totalScanTime += scanDuration;

        LastScan curr = lastScans.get(lastScans.size() - 1);
        curr.duration = scanDuration;

        if (lastScans.size() > NUM_SCAN_DURATIONS_KEPT) {
        long scanDuration = stopTime - scan.timestamp;
        scan.duration = scanDuration;
        ongoingScans.remove(scannerId);
        if (lastScans.size() >= NUM_SCAN_DURATIONS_KEPT) {
            lastScans.remove(0);
        }
        lastScans.add(scan);

        BluetoothProto.ScanEvent scanEvent = new BluetoothProto.ScanEvent();
        scanEvent.setScanEventType(BluetoothProto.ScanEvent.SCAN_EVENT_STOP);
@@ -180,23 +192,28 @@ import com.android.bluetooth.btservice.BluetoothProto;
        scanEvent.setInitiator(truncateAppName(appName));
        gattService.addScanEvent(scanEvent);

        if (!isScanning()) {
            try {
                long totalDuration = stopTime - mScanStartTime;
                mTotalScanTime += totalDuration;
                minScanTime = Math.min(totalDuration, minScanTime);
                maxScanTime = Math.max(totalDuration, maxScanTime);
                // Inform battery stats of any results it might be missing on
                // scan stop
            batteryStats.noteBleScanResults(workSource, curr.results % 100);
                batteryStats.noteBleScanResults(workSource, scan.results % 100);
                batteryStats.noteBleScanStopped(workSource);
            } catch (RemoteException e) {
                /* ignore */
            }
        }
    }

    synchronized void setScanTimeout() {
        if (!isScanning)
          return;
    synchronized void setScanTimeout(int scannerId) {
        if (!isScanning()) return;

        if (!lastScans.isEmpty()) {
            LastScan curr = lastScans.get(lastScans.size() - 1);
            curr.timeout = true;
        LastScan scan = getScanFromScannerId(scannerId);
        if (scan != null) {
            scan.timeout = true;
        }
    }

@@ -210,11 +227,10 @@ import com.android.bluetooth.btservice.BluetoothProto;
    }

    synchronized boolean isScanningTooLong() {
        if (lastScans.isEmpty() || !isScanning) {
        if (!isScanning()) {
            return false;
        }

        return (SystemClock.elapsedRealtime() - startTime) > SCAN_TIMEOUT_MS;
        return (SystemClock.elapsedRealtime() - mScanStartTime) > SCAN_TIMEOUT_MS;
    }

    // This function truncates the app name for privacy reasons. Apps with
@@ -243,19 +259,24 @@ import com.android.bluetooth.btservice.BluetoothProto;
        long minScan = minScanTime;
        long scanDuration = 0;

        if (isScanning) {
            scanDuration = currTime - startTime;
        if (isScanning()) {
            scanDuration = currTime - mScanStartTime;
        }
        minScan = Math.min(scanDuration, minScan);
        maxScan = Math.max(scanDuration, maxScan);
        }

        if (minScan == Long.MAX_VALUE) {
            minScan = 0;
        }

        /*TODO: Average scan time can be skewed for
         * multiple scan clients. It will show less than
         * actual value.
         * */
        long avgScan = 0;
        long totalScanTime = mTotalScanTime + scanDuration;
        if (scansStarted > 0) {
            avgScan = (totalScanTime + scanDuration) / scansStarted;
            avgScan = totalScanTime / scansStarted;
        }

        sb.append("  " + appName);
@@ -281,16 +302,14 @@ import com.android.bluetooth.btservice.BluetoothProto;
        sb.append("  Total number of results            : " +
                  results + "\n");

        long currentTime = System.currentTimeMillis();
        long elapsedRt = SystemClock.elapsedRealtime();
        if (!lastScans.isEmpty()) {
            int lastScansSize = scansStopped < NUM_SCAN_DURATIONS_KEPT ?
                                scansStopped : NUM_SCAN_DURATIONS_KEPT;
            sb.append("  Last " + lastScansSize +
                      " scans                       :\n");
            sb.append("  Last " + lastScans.size() + " scans                       :\n");

            for (int i = 0; i < lastScansSize; i++) {
            for (int i = 0; i < lastScans.size(); i++) {
                LastScan scan = lastScans.get(i);
                Date timestamp = new Date(System.currentTimeMillis() - SystemClock.elapsedRealtime()
                        + scan.timestamp);
                Date timestamp = new Date(currentTime - elapsedRt + scan.timestamp);
                sb.append("    " + dateFormat.format(timestamp) + " - ");
                sb.append(scan.duration + "ms ");
                if (scan.opportunistic) sb.append("Opp ");
@@ -298,6 +317,24 @@ import com.android.bluetooth.btservice.BluetoothProto;
                if (scan.timeout) sb.append("Forced ");
                if (scan.filtered) sb.append("Filter ");
                sb.append(scan.results + " results");
                sb.append(" (" + scan.scannerId + ")");
                sb.append("\n");
            }
        }

        if (!ongoingScans.isEmpty()) {
            sb.append("  Ongoing scans                      :\n");
            for (Integer key : ongoingScans.keySet()) {
                LastScan scan = ongoingScans.get(key);
                Date timestamp = new Date(currentTime - elapsedRt + scan.timestamp);
                sb.append("    " + dateFormat.format(timestamp) + " - ");
                sb.append((elapsedRt - scan.timestamp) + "ms ");
                if (scan.opportunistic) sb.append("Opp ");
                if (scan.background) sb.append("Back ");
                if (scan.timeout) sb.append("Forced ");
                if (scan.filtered) sb.append("Filter ");
                sb.append(scan.results + " results");
                sb.append(" (" + scan.scannerId + ")");
                sb.append("\n");
            }
        }
@@ -309,11 +346,6 @@ import com.android.bluetooth.btservice.BluetoothProto;
            sb.append("  UUID                               : " +
                      appEntry.uuid + "\n");

            if (isScanning) {
                sb.append("  Current scan duration in ms        : " +
                          scanDuration + "\n");
            }

            List<ContextMap.Connection> connections =
              contextMap.getConnectionByApp(appEntry.id);

+4 −4
Original line number Diff line number Diff line
@@ -781,7 +781,7 @@ public class GattService extends ProfileService {
            }

            try {
                app.appScanStats.addResult();
                app.appScanStats.addResult(client.scannerId);
                if (app.callback != null) {
                    app.callback.onScanResult(result);
                } else {
@@ -1596,7 +1596,7 @@ public class GattService extends ProfileService {
            scanClient.stats = app;

            boolean isFilteredScan = (filters != null) && !filters.isEmpty();
            app.recordScanStart(settings, isFilteredScan);
            app.recordScanStart(settings, isFilteredScan, scannerId);
        }

        mScanManager.startScan(scanClient);
@@ -1644,7 +1644,7 @@ public class GattService extends ProfileService {
            scanClient.stats = app;

            boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
            app.recordScanStart(piInfo.settings, isFilteredScan);
            app.recordScanStart(piInfo.settings, isFilteredScan, scannerId);
        }

        mScanManager.startScan(scanClient);
@@ -1663,7 +1663,7 @@ public class GattService extends ProfileService {

        AppScanStats app = null;
        app = mScannerMap.getAppScanStatsById(client.scannerId);
        if (app != null) app.recordScanStop();
        if (app != null) app.recordScanStop(client.scannerId);

        mScanManager.stopScan(client);
    }
+1 −1
Original line number Diff line number Diff line
@@ -686,7 +686,7 @@ public class ScanManager {
                        "Moving scan client to opportunistic (scannerId " + client.scannerId + ")");
                setOpportunisticScanClient(client);
                removeScanFilters(client.scannerId);
                client.stats.setScanTimeout();
                client.stats.setScanTimeout(client.scannerId);
            }

            // The scan should continue for background scans