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

Commit 529d622d authored by Kai Shi's avatar Kai Shi
Browse files

BLE scan time optimization

BLE scan time optimization to reduce scan latency:
1)Reduce scan interval and window for low power, balanced and ambient scan modes. Balanced and ambient modes now have effectively the same settings.
2)Add screen off and screen off balanced modes with longer interval  for the internal use.
3)For regular apps:
   Foregroud: original scan mode.
   Background + screen on: low power mode.
   Screen off: screen off mode.
  For foreground service:
   Screen on: original scan mode.
   Scree off: fall back to screen off/screen off balanced mode unless it
   requests low latency mode.
4)When App requests a new scan without recent request, its scan mode is
upgraded temporarily for 6 seconds (configurable).

Tag: #feature
Bug: 214595841
Test: Run scan in low power, low latency and balanced scan modes with filtered and unfiltered settings both continuously and periodically.

Make sure the scan mode is set correctly during screen on/off transition and background/foreground transition.

Tested with multiple scan clients from both test app and other service apps.

Change-Id: I291a1a80f24d431b681aae485692241dfb474c5a
parent 0ade88c6
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -3966,6 +3966,9 @@ public class AdapterService extends Service {
    private long mScanQuotaWindowMillis = DeviceConfigListener.DEFAULT_SCAN_QUOTA_WINDOW_MILLIS;
    @GuardedBy("mDeviceConfigLock")
    private long mScanTimeoutMillis = DeviceConfigListener.DEFAULT_SCAN_TIMEOUT_MILLIS;
    @GuardedBy("mDeviceConfigLock")
    private int mScanUpgradeDurationMillis =
            DeviceConfigListener.DEFAULT_SCAN_UPGRADE_DURATION_MILLIS;

    public @NonNull Predicate<String> getLocationDenylistName() {
        synchronized (mDeviceConfigLock) {
@@ -4003,6 +4006,15 @@ public class AdapterService extends Service {
        }
    }

    /**
     * Returns scan upgrade duration in millis.
     */
    public long getScanUpgradeDurationMillis() {
        synchronized (mDeviceConfigLock) {
            return mScanUpgradeDurationMillis;
        }
    }

    private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener();

    private class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener {
@@ -4018,6 +4030,8 @@ public class AdapterService extends Service {
                "scan_quota_window_millis";
        private static final String SCAN_TIMEOUT_MILLIS =
                "scan_timeout_millis";
        private static final String SCAN_UPGRADE_DURATION_MILLIS =
                "scan_upgrade_duration_millis";

        /**
         * Default denylist which matches Eddystone and iBeacon payloads.
@@ -4028,6 +4042,7 @@ public class AdapterService extends Service {
        private static final int DEFAULT_SCAN_QUOTA_COUNT = 5;
        private static final long DEFAULT_SCAN_QUOTA_WINDOW_MILLIS = 30 * SECOND_IN_MILLIS;
        private static final long DEFAULT_SCAN_TIMEOUT_MILLIS = 30 * MINUTE_IN_MILLIS;
        private static final int DEFAULT_SCAN_UPGRADE_DURATION_MILLIS = (int) SECOND_IN_MILLIS * 6;

        public void start() {
            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BLUETOOTH,
@@ -4053,6 +4068,8 @@ public class AdapterService extends Service {
                        DEFAULT_SCAN_QUOTA_WINDOW_MILLIS);
                mScanTimeoutMillis = properties.getLong(SCAN_TIMEOUT_MILLIS,
                        DEFAULT_SCAN_TIMEOUT_MILLIS);
                mScanUpgradeDurationMillis = properties.getInt(SCAN_UPGRADE_DURATION_MILLIS,
                        DEFAULT_SCAN_UPGRADE_DURATION_MILLIS);
            }
        }
    }
+16 −0
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ import java.util.Objects;
    static final int BALANCED_WEIGHT = 25;
    static final int LOW_LATENCY_WEIGHT = 100;

    static final int LARGE_SCAN_TIME_GAP_MS = 24000;

    // ContextMap here is needed to grab Apps and Connections
    ContextMap mContextMap;

@@ -119,6 +121,11 @@ import java.util.Objects;
        return AdapterService.getAdapterService().getScanTimeoutMillis();
    }

    // Scan mode upgrade duration after scanStart()
    static long getScanUpgradeDurationMillis() {
        return AdapterService.getAdapterService().getScanUpgradeDurationMillis();
    }

    public String appName;
    public WorkSource mWorkSource; // Used for BatteryStatsManager
    public final WorkSourceUtil mWorkSourceUtil; // Used for BluetoothStatsLog
@@ -363,6 +370,15 @@ import java.util.Objects;
        return (SystemClock.elapsedRealtime() - mScanStartTime) > getScanTimeoutMillis();
    }

    synchronized boolean hasRecentScan() {
        if (!isScanning() || mLastScans.isEmpty()) {
            return false;
        }
        LastScan lastScan = mLastScans.get(mLastScans.size() - 1);
        return ((SystemClock.elapsedRealtime() - lastScan.duration - lastScan.timestamp)
                < LARGE_SCAN_TIME_GAP_MS);
    }

    // This function truncates the app name for privacy reasons. Apps with
    // four part package names or more get truncated to three parts, and apps
    // with three part package names names get truncated to two. Apps with two
+36 −2
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ import java.util.Objects;
/* package */class ScanClient {
    public int scannerId;
    public ScanSettings settings;
    public ScanSettings passiveSettings;
    public int scanModeApp;
    public boolean started = false;
    public int appUid;
    public List<ScanFilter> filters;
    // App associated with the scan client died.
@@ -59,7 +60,7 @@ import java.util.Objects;
    ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters) {
        this.scannerId = scannerId;
        this.settings = settings;
        this.passiveSettings = null;
        this.scanModeApp = settings.getScanMode();
        this.filters = filters;
        this.appUid = Binder.getCallingUid();
    }
@@ -80,4 +81,37 @@ import java.util.Objects;
    public int hashCode() {
        return Objects.hash(scannerId);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(" [ScanClient")
                .append(" scanModeApp ").append(scanModeApp)
                .append(" scanModeUsed ").append(settings.getScanMode());
        if (stats != null && stats.appName != null) {
            sb.append(" [appScanStats ").append(stats.appName).append("]");
        }
        sb.append("]");
        return sb.toString();
    }

    /**
     * Update scan settings with the new scan mode.
     * @param newScanMode
     * @return true if scan settings are updated, false otherwise.
     */
    public boolean updateScanMode(int newScanMode) {
        if (settings.getScanMode() == newScanMode) {
            return false;
        }

        ScanSettings.Builder builder = new ScanSettings.Builder();
        settings = builder.setScanMode(newScanMode)
                .setCallbackType(settings.getCallbackType())
                .setScanResultType(settings.getScanResultType())
                .setReportDelay(settings.getReportDelayMillis())
                .setNumOfMatches(settings.getNumOfMatches())
                .build();
        return true;
    }
}
+261 −84

File changed.

Preview size limit exceeded, changes collapsed.

+19 −0
Original line number Diff line number Diff line
@@ -61,6 +61,23 @@ public final class ScanSettings implements Parcelable {
    @SystemApi
    public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3;

    /**
     * Default Bluetooth LE scan mode when the screen is off.
     * This mode has the low duty cycle and long scan interval which results in the lowest
     * power consumption among all modes. It is for the framework internal use only.
     *
     * @hide
     */
    public static final int SCAN_MODE_SCREEN_OFF = 4;

    /**
     * Balanced Bluetooth LE scan mode for foreground service when the screen is off.
     * It is for the framework internal use only.
     *
     * @hide
     */
    public static final int SCAN_MODE_SCREEN_OFF_BALANCED = 5;

    /**
     * Trigger a callback for every Bluetooth advertisement found that matches the filter criteria.
     * If no filter is active, all advertisement packets are reported.
@@ -292,6 +309,8 @@ public final class ScanSettings implements Parcelable {
                case SCAN_MODE_BALANCED:
                case SCAN_MODE_LOW_LATENCY:
                case SCAN_MODE_AMBIENT_DISCOVERY:
                case SCAN_MODE_SCREEN_OFF:
                case SCAN_MODE_SCREEN_OFF_BALANCED:
                    mScanMode = scanMode;
                    break;
                default: