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

Commit 1396bb3c authored by Ömer Faruk Yılmaz's avatar Ömer Faruk Yılmaz
Browse files

Move scannerMap from GattService to the new TransitionalScanHelper

See go/scan-manager-refactor for more details.

Test: m com.android.btservices
Bug: 313335632
Bug: 267361243
Change-Id: Ic6d9910a641a4a3e7d1c0f5ec059464dc9aa16a3
parent c020543f
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ public class ContextMap<C, T> {
    private final Object mConnectionsLock = new Object();

    /** Add an entry to the application context list. */
    App add(
    protected App add(
            UUID uuid,
            WorkSource workSource,
            C callback,
@@ -292,7 +292,7 @@ public class ContextMap<C, T> {
    /**
     * Remove the context for a given application ID.
     */
    void remove(int id) {
    protected void remove(int id) {
        boolean find = false;
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
@@ -312,7 +312,7 @@ public class ContextMap<C, T> {
        }
    }

    List<Integer> getAllAppsIds() {
    protected List<Integer> getAllAppsIds() {
        List<Integer> appIds = new ArrayList();
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
@@ -370,7 +370,7 @@ public class ContextMap<C, T> {
    /**
     * Get an application context by ID.
     */
    App getById(int id) {
    protected App getById(int id) {
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
            while (i.hasNext()) {
@@ -387,7 +387,7 @@ public class ContextMap<C, T> {
    /**
     * Get an application context by UUID.
     */
    App getByUuid(UUID uuid) {
    protected App getByUuid(UUID uuid) {
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
            while (i.hasNext()) {
@@ -421,7 +421,7 @@ public class ContextMap<C, T> {
    /**
     * Get an application context by the context info object.
     */
    App getByContextInfo(T contextInfo) {
    protected App getByContextInfo(T contextInfo) {
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
            while (i.hasNext()) {
@@ -438,7 +438,7 @@ public class ContextMap<C, T> {
    /**
     * Get Logging info by ID
     */
    AppScanStats getAppScanStatsById(int id) {
    protected AppScanStats getAppScanStatsById(int id) {
        App temp = getById(id);
        if (temp != null) {
            return temp.appScanStats;
@@ -674,7 +674,7 @@ public class ContextMap<C, T> {
    /**
     * Erases all application context entries.
     */
    void clear() {
    protected void clear() {
        synchronized (mAppsLock) {
            Iterator<App> i = mApps.iterator();
            while (i.hasNext()) {
@@ -713,7 +713,7 @@ public class ContextMap<C, T> {
    /**
     * Logs debug information.
     */
    void dump(StringBuilder sb) {
    protected void dump(StringBuilder sb) {
        sb.append("  Entries: " + mAppScanStats.size() + "\n\n");

        Iterator<Map.Entry<Integer, AppScanStats>> it = mAppScanStats.entrySet().iterator();
+43 −33
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ import com.android.bluetooth.le_scan.AppScanStats;
import com.android.bluetooth.le_scan.PeriodicScanManager;
import com.android.bluetooth.le_scan.ScanClient;
import com.android.bluetooth.le_scan.ScanManager;
import com.android.bluetooth.le_scan.TransitionalScanHelper;
import com.android.bluetooth.util.NumberUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.SynchronousResultReceiver;
@@ -213,7 +214,7 @@ public class GattService extends ProfileService {
    /**
     * Keep the arguments passed in for the PendingIntent.
     */
    class PendingIntentInfo {
    public static class PendingIntentInfo {
        public PendingIntent intent;
        public ScanSettings settings;
        public List<ScanFilter> filters;
@@ -237,12 +238,7 @@ public class GattService extends ProfileService {
                }
            };

    /**
     * List of our registered scanners.
     */
    public static class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {}

    public ScannerMap mScannerMap = new ScannerMap();
    public final TransitionalScanHelper mTransitionalScanHelper = new TransitionalScanHelper();

    /**
     * List of our registered advertisers.
@@ -394,7 +390,7 @@ public class GattService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "stop()");
        }
        mScannerMap.clear();
        mTransitionalScanHelper.getScannerMap().clear();
        mAdvertiserMap.clear();
        mClientMap.clear();
        if (Flags.gattCleanupRestrictedHandles()) {
@@ -2020,7 +2016,8 @@ public class GattService extends ProfileService {
        byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62);

        for (ScanClient client : mScanManager.getRegularScanQueue()) {
            ScannerMap.App app = mScannerMap.getById(client.scannerId);
            TransitionalScanHelper.ScannerMap.App app =
                    mTransitionalScanHelper.getScannerMap().getById(client.scannerId);
            if (app == null) {
                if (VDBG) {
                    Log.d(TAG, "App is null; skip.");
@@ -2112,7 +2109,7 @@ public class GattService extends ProfileService {
                if (Flags.leScanFixRemoteException()) {
                    handleDeadScanClient(client);
                } else {
                    mScannerMap.remove(client.scannerId);
                    mTransitionalScanHelper.getScannerMap().remove(client.scannerId);
                    mScanManager.stopScan(client.scannerId);
                }
            }
@@ -2161,7 +2158,8 @@ public class GattService extends ProfileService {
        }

        // First check the callback map
        ScannerMap.App cbApp = mScannerMap.getByUuid(uuid);
        TransitionalScanHelper.ScannerMap.App cbApp =
                mTransitionalScanHelper.getScannerMap().getByUuid(uuid);
        if (cbApp != null) {
            if (status == 0) {
                cbApp.id = scannerId;
@@ -2173,7 +2171,7 @@ public class GattService extends ProfileService {
                    continuePiStartScan(scannerId, cbApp);
                }
            } else {
                mScannerMap.remove(scannerId);
                mTransitionalScanHelper.getScannerMap().remove(scannerId);
            }
            if (cbApp.callback != null) {
                cbApp.callback.onScannerRegistered(status, scannerId);
@@ -2802,7 +2800,8 @@ public class GattService extends ProfileService {
        Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData);
        if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
            // We only support single client for truncated mode.
            ScannerMap.App app = mScannerMap.getById(scannerId);
            TransitionalScanHelper.ScannerMap.App app =
                    mTransitionalScanHelper.getScannerMap().getById(scannerId);
            if (app == null) {
                return;
            }
@@ -2853,7 +2852,7 @@ public class GattService extends ProfileService {
        mScanManager.callbackDone(scannerId, status);
    }

    private void sendBatchScanResults(ScannerMap.App app, ScanClient client,
    private void sendBatchScanResults(TransitionalScanHelper.ScannerMap.App app, ScanClient client,
            ArrayList<ScanResult> results) {
        try {
            if (app.callback != null) {
@@ -2880,7 +2879,7 @@ public class GattService extends ProfileService {
            if (Flags.leScanFixRemoteException()) {
                handleDeadScanClient(client);
            } else {
                mScannerMap.remove(client.scannerId);
                mTransitionalScanHelper.getScannerMap().remove(client.scannerId);
                mScanManager.stopScan(client.scannerId);
            }
        }
@@ -2889,7 +2888,8 @@ public class GattService extends ProfileService {
    // Check and deliver scan results for different scan clients.
    private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults)
            throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(client.scannerId);
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().getById(client.scannerId);
        if (app == null) {
            return;
        }
@@ -3050,7 +3050,8 @@ public class GattService extends ProfileService {
                    + trackingInfo.getAdvState());
        }

        ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf());
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().getById(trackingInfo.getClientIf());
        if (app == null || (app.callback == null && app.info == null)) {
            Log.e(TAG, "app or callback is null");
            return;
@@ -3096,7 +3097,8 @@ public class GattService extends ProfileService {
    }

    void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(scannerId);
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().getById(scannerId);
        if (app == null || app.callback == null) {
            Log.e(TAG, "Advertise app or callback is null");
            return;
@@ -3108,7 +3110,8 @@ public class GattService extends ProfileService {

    // callback from ScanManager for dispatch of errors apps.
    public void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException {
        ScannerMap.App app = mScannerMap.getById(scannerId);
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().getById(scannerId);
        if (app == null || (app.callback == null && app.info == null)) {
            Log.e(TAG, "App or callback is null");
            return;
@@ -3225,7 +3228,8 @@ public class GattService extends ProfileService {

        enforceImpersonatationPermissionIfNeeded(workSource);

        AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid());
        AppScanStats app = mTransitionalScanHelper.getScannerMap()
                    .getAppScanStatsByUid(Binder.getCallingUid());
        if (app != null && app.isScanningTooFrequently()
                && !Utils.checkCallerHasPrivilegedPermission(this)) {
            Log.e(TAG, "App '" + app.appName + "' is scanning too frequently");
@@ -3233,7 +3237,8 @@ public class GattService extends ProfileService {
            return;
        }

        mScannerMap.add(uuid, workSource, callback, null, this);
        mTransitionalScanHelper
            .getScannerMap().add(uuid, workSource, callback, null, this);
        mScanManager.registerScanner(uuid);
    }

@@ -3247,7 +3252,7 @@ public class GattService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId);
        }
        mScannerMap.remove(scannerId);
        mTransitionalScanHelper.getScannerMap().remove(scannerId);
        mScanManager.unregisterScanner(scannerId);
    }

@@ -3319,8 +3324,9 @@ public class GattService extends ProfileService {
                Utils.checkCallerHasScanWithoutLocationPermission(this);
        scanClient.associatedDevices = getAssociatedDevices(callingPackage);

        AppScanStats app = mScannerMap.getAppScanStatsById(scannerId);
        ScannerMap.App cbApp = mScannerMap.getById(scannerId);
        AppScanStats app = mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId);
        TransitionalScanHelper.ScannerMap.App cbApp =
                mTransitionalScanHelper.getScannerMap().getById(scannerId);
        if (app != null) {
            scanClient.stats = app;
            boolean isFilteredScan = (filters != null) && !filters.isEmpty();
@@ -3367,12 +3373,13 @@ public class GattService extends ProfileService {
        }

        // Don't start scan if the Pi scan already in mScannerMap.
        if (mScannerMap.getByContextInfo(piInfo) != null) {
        if (mTransitionalScanHelper.getScannerMap().getByContextInfo(piInfo) != null) {
            Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap.");
            return;
        }

        ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this);
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().add(uuid, null, null, piInfo, this);

        app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid());
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
@@ -3412,7 +3419,7 @@ public class GattService extends ProfileService {
        }
    }

    void continuePiStartScan(int scannerId, ScannerMap.App app) {
    void continuePiStartScan(int scannerId, TransitionalScanHelper.ScannerMap.App app) {
        final PendingIntentInfo piInfo = app.info;
        final ScanClient scanClient =
                new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid);
@@ -3427,7 +3434,8 @@ public class GattService extends ProfileService {
        scanClient.associatedDevices = app.mAssociatedDevices;
        scanClient.hasDisavowedLocation = app.mHasDisavowedLocation;

        AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId);
        AppScanStats scanStats =
                mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId);
        if (scanStats != null) {
            scanClient.stats = scanStats;
            boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
@@ -3463,7 +3471,7 @@ public class GattService extends ProfileService {
        }

        AppScanStats app = null;
        app = mScannerMap.getAppScanStatsById(scannerId);
        app = mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId);
        if (app != null) {
            app.recordScanStop(scannerId);
        }
@@ -3479,7 +3487,8 @@ public class GattService extends ProfileService {
        }
        PendingIntentInfo pii = new PendingIntentInfo();
        pii.intent = intent;
        ScannerMap.App app = mScannerMap.getByContextInfo(pii);
        TransitionalScanHelper.ScannerMap.App app =
                mTransitionalScanHelper.getScannerMap().getByContextInfo(pii);
        if (VDBG) {
            Log.d(TAG, "stopScan(PendingIntent): app found = " + app);
        }
@@ -5102,8 +5111,9 @@ public class GattService extends ProfileService {

    void dumpRegisterId(StringBuilder sb) {
        sb.append("  Scanner:\n");
        for (Integer appId : mScannerMap.getAllAppsIds()) {
            println(sb, "    app_if: " + appId + ", appName: " + mScannerMap.getById(appId).name);
        for (Integer appId : mTransitionalScanHelper.getScannerMap().getAllAppsIds()) {
            println(sb, "    app_if: " + appId + ", appName: " +
                    mTransitionalScanHelper.getScannerMap().getById(appId).name);
        }
        sb.append("  Client:\n");
        for (Integer appId : mClientMap.getAllAppsIds()) {
@@ -5130,7 +5140,7 @@ public class GattService extends ProfileService {
        dumpRegisterId(sb);

        sb.append("GATT Scanner Map\n");
        mScannerMap.dump(sb);
        mTransitionalScanHelper.getScannerMap().dump(sb);

        sb.append("GATT Advertiser Map\n");
        mAdvertiserMap.dumpAdvertiser(sb);
+2 −1
Original line number Diff line number Diff line
@@ -1922,7 +1922,8 @@ public class ScanManager {
            new ActivityManager.OnUidImportanceListener() {
                @Override
                public void onUidImportance(final int uid, final int importance) {
                    if (mService.mScannerMap.getAppScanStatsByUid(uid) != null) {
                    if (mService.mTransitionalScanHelper.getScannerMap().getAppScanStatsByUid(uid)
                            != null) {
                        Message message = new Message();
                        message.what = MSG_IMPORTANCE_CHANGE;
                        message.obj = new UidImportance(uid, importance);
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.le_scan;

import android.bluetooth.le.IScannerCallback;

import com.android.bluetooth.gatt.ContextMap;
import com.android.bluetooth.gatt.GattService;
import com.android.internal.annotations.VisibleForTesting;

/**
 * A helper class which contains all scan related functions extracted from {@link
 * com.android.bluetooth.gatt.GattService}. The purpose of this class is to preserve scan
 * functionality within GattService and provide the same functionality in a new scan dedicated
 * {@link com.android.bluetooth.btservice.ProfileService} when introduced.
 *
 * @hide
 */
public class TransitionalScanHelper {

    /** List of our registered scanners. */
    public static class ScannerMap
            extends ContextMap<IScannerCallback, GattService.PendingIntentInfo> {}

    private ScannerMap mScannerMap = new ScannerMap();

    public ScannerMap getScannerMap() {
        return mScannerMap;
    }

    @VisibleForTesting
    public void setScannerMap(ScannerMap scannerMap) {
        mScannerMap = scannerMap;
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -61,8 +61,10 @@ import com.android.bluetooth.le_scan.AppScanStats;
import com.android.bluetooth.le_scan.PeriodicScanManager;
import com.android.bluetooth.le_scan.ScanClient;
import com.android.bluetooth.le_scan.ScanManager;
import com.android.bluetooth.le_scan.TransitionalScanHelper;

import com.android.bluetooth.flags.Flags;

import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
@@ -97,8 +99,8 @@ public class GattServiceTest {
    private Context mTargetContext;
    private GattService mService;
    @Mock private GattService.ClientMap mClientMap;
    @Mock private GattService.ScannerMap mScannerMap;
    @Mock private GattService.ScannerMap.App mApp;
    @Mock private TransitionalScanHelper.ScannerMap mScannerMap;
    @Mock private TransitionalScanHelper.ScannerMap.App mApp;
    @Mock private GattService.PendingIntentInfo mPiInfo;
    @Mock private PeriodicScanManager mPeriodicScanManager;
    @Mock private ScanManager mScanManager;
@@ -158,7 +160,7 @@ public class GattServiceTest {
        mService.start();

        mService.mClientMap = mClientMap;
        mService.mScannerMap = mScannerMap;
        mService.mTransitionalScanHelper.setScannerMap(mScannerMap);
        mService.mReliableQueue = mReliableQueue;
        mService.mServerMap = mServerMap;
    }
@@ -246,7 +248,7 @@ public class GattServiceTest {
        mService.connectionParameterUpdate(clientIf, address, connectionPriority,
                mAttributionSource);

        connectionPriority = BluetoothGatt.CONNECTION_PRIORITY_BALANCED;;
        connectionPriority = BluetoothGatt.CONNECTION_PRIORITY_BALANCED;
        mService.connectionParameterUpdate(clientIf, address, connectionPriority,
                mAttributionSource);