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

Commit d4a5f29b authored by Omair Kamil's avatar Omair Kamil
Browse files

Refactor advertiser functions out of ContextMap.

Bug: 327849650
Flag: EXEMPT, mechanical refactor
Test: atest BluetoothInstrumentationTests, atest BumbleBluetoothTests, atest pts-bot:GATT
Change-Id: Ib887c178f3ec2c9f8c836a78599af08babbe02bc
parent 0a72614a
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -44,9 +44,6 @@ import android.provider.Telephony;
import android.util.Log;

import com.android.bluetooth.bass_client.BassClientPeriodicAdvertisingManager;
import com.android.bluetooth.gatt.AppAdvertiseStats;
import com.android.bluetooth.gatt.ContextMap;
import com.android.bluetooth.gatt.GattService;
import com.android.internal.annotations.VisibleForTesting;
import com.android.obex.HeaderSet;

@@ -264,12 +261,6 @@ public class BluetoothMethodProxy {
        manager.transferSetInfo(bda, serviceData, advHandle, callback);
    }

    /** Proxies {@link AppAdvertiseStats}. */
    public AppAdvertiseStats createAppAdvertiseStats(
            int appUid, int id, String name, ContextMap map, GattService service) {
        return new AppAdvertiseStats(appUid, id, name, map, service);
    }

    /** Proxies {@link Thread#start()}. */
    public void threadStart(Thread thread) {
        thread.start();
+16 −3
Original line number Diff line number Diff line
@@ -32,7 +32,6 @@ import android.os.RemoteException;
import android.util.Log;

import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.gatt.GattService.AdvertiserMap;
import com.android.internal.annotations.VisibleForTesting;

import java.util.Collections;
@@ -53,7 +52,11 @@ public class AdvertiseManager {
    Map<IBinder, AdvertiserInfo> mAdvertisers = Collections.synchronizedMap(new HashMap<>());
    static int sTempRegistrationId = -1;

    /** Constructor of {@link AdvertiseManager}. */
    AdvertiseManager(GattService service) {
        this(service, AdvertiseManagerNativeInterface.getInstance(), new AdvertiserMap());
    }

    @VisibleForTesting
    AdvertiseManager(
            GattService service,
            AdvertiseManagerNativeInterface nativeInterface,
@@ -70,6 +73,12 @@ public class AdvertiseManager {
        mHandler = new Handler(thread.getLooper());
    }

    // TODO(b/327849650): We shouldn't need this, it should be safe to do in the cleanup method. But
    //                    it would be a logic change.
    void clear() {
        mAdvertiserMap.clear();
    }

    void cleanup() {
        Log.d(TAG, "cleanup()");
        mNativeInterface.cleanup();
@@ -87,6 +96,10 @@ public class AdvertiseManager {
        }
    }

    void dump(StringBuilder sb) {
        mAdvertiserMap.dump(sb);
    }

    static class AdvertiserInfo {
        /* When id is negative, the registration is ongoing. When the registration finishes, id
         * becomes equal to advertiser_id */
@@ -263,7 +276,7 @@ public class AdvertiseManager {

            Log.d(TAG, "startAdvertisingSet() - reg_id=" + cbId + ", callback: " + binder);

            mAdvertiserMap.add(cbId, callback, mService);
            mAdvertiserMap.addAppAdvertiseStats(cbId, mService);
            mAdvertiserMap.recordAdvertiseStart(
                    cbId,
                    parameters,
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ public class AdvertiseManagerNativeInterface {
    private AdvertiseManager mManager;

    /** Get singleton instance. */
    public static AdvertiseManagerNativeInterface getInstance() {
    static AdvertiseManagerNativeInterface getInstance() {
        synchronized (INSTANCE_LOCK) {
            if (sInstance == null) {
                sInstance = new AdvertiseManagerNativeInterface();
+213 −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.gatt;

import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.PeriodicAdvertisingParameters;
import android.content.Context;
import android.os.Binder;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.internal.annotations.GuardedBy;

import com.google.common.collect.EvictingQueue;

import java.util.HashMap;

/** Helper class that keeps track of advertiser stats. */
class AdvertiserMap {
    private static final String TAG = GattServiceConfig.TAG_PREFIX + "AdvertiserMap";

    /** Internal map to keep track of logging information by advertise id */
    @GuardedBy("this")
    private final HashMap<Integer, AppAdvertiseStats> mAppAdvertiseStats = new HashMap<>();

    private static final int ADVERTISE_STATE_MAX_SIZE = 5;

    @GuardedBy("this")
    private final EvictingQueue<AppAdvertiseStats> mLastAdvertises =
            EvictingQueue.create(ADVERTISE_STATE_MAX_SIZE);

    /** Add an entry to the stats map if it doesn't already exist. */
    void addAppAdvertiseStats(int id, Context context) {
        int appUid = Binder.getCallingUid();
        String appName = context.getPackageManager().getNameForUid(appUid);
        if (appName == null) {
            // Assign an app name if one isn't found
            appName = "Unknown App (UID: " + appUid + ")";
        }

        synchronized (this) {
            if (!mAppAdvertiseStats.containsKey(id)) {
                addAppAdvertiseStats(id, new AppAdvertiseStats(appUid, id, appName));
            }
        }
    }

    @VisibleForTesting
    synchronized void addAppAdvertiseStats(int id, AppAdvertiseStats stats) {
        mAppAdvertiseStats.put(id, stats);
    }

    /** Remove the context for a given application ID. */
    synchronized void removeAppAdvertiseStats(int id) {
        mAppAdvertiseStats.remove(id);
    }

    /** Get Logging info by ID */
    synchronized AppAdvertiseStats getAppAdvertiseStatsById(int id) {
        return mAppAdvertiseStats.get(id);
    }

    /** update the advertiser ID by the regiseter ID */
    synchronized void setAdvertiserIdByRegId(int regId, int advertiserId) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(regId);
        if (stats == null) {
            return;
        }
        stats.setId(advertiserId);
        mAppAdvertiseStats.remove(regId);
        mAppAdvertiseStats.put(advertiserId, stats);
    }

    synchronized void recordAdvertiseStart(
            int id,
            AdvertisingSetParameters parameters,
            AdvertiseData advertiseData,
            AdvertiseData scanResponse,
            PeriodicAdvertisingParameters periodicParameters,
            AdvertiseData periodicData,
            int duration,
            int maxExtAdvEvents) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        int advertiseInstanceCount = mAppAdvertiseStats.size();
        Log.d(TAG, "advertiseInstanceCount is " + advertiseInstanceCount);
        AppAdvertiseStats.recordAdvertiseInstanceCount(advertiseInstanceCount);
        stats.recordAdvertiseStart(
                parameters,
                advertiseData,
                scanResponse,
                periodicParameters,
                periodicData,
                duration,
                maxExtAdvEvents,
                advertiseInstanceCount);
    }

    synchronized void recordAdvertiseStop(int id) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.recordAdvertiseStop(mAppAdvertiseStats.size());
        mAppAdvertiseStats.remove(id);
        mLastAdvertises.add(stats);
    }

    synchronized void enableAdvertisingSet(
            int id, boolean enable, int duration, int maxExtAdvEvents) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.enableAdvertisingSet(enable, duration, maxExtAdvEvents, mAppAdvertiseStats.size());
    }

    synchronized void setAdvertisingData(int id, AdvertiseData data) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.setAdvertisingData(data);
    }

    synchronized void setScanResponseData(int id, AdvertiseData data) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.setScanResponseData(data);
    }

    synchronized void setAdvertisingParameters(int id, AdvertisingSetParameters parameters) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.setAdvertisingParameters(parameters);
    }

    synchronized void setPeriodicAdvertisingParameters(
            int id, PeriodicAdvertisingParameters parameters) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.setPeriodicAdvertisingParameters(parameters);
    }

    synchronized void setPeriodicAdvertisingData(int id, AdvertiseData data) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.setPeriodicAdvertisingData(data);
    }

    synchronized void onPeriodicAdvertiseEnabled(int id, boolean enable) {
        AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
        if (stats == null) {
            return;
        }
        stats.onPeriodicAdvertiseEnabled(enable);
    }

    /** Erases all entries. */
    synchronized void clear() {
        mAppAdvertiseStats.clear();
        mLastAdvertises.clear();
    }

    /** Logs advertiser debug information. */
    synchronized void dump(StringBuilder sb) {
        if (!mLastAdvertises.isEmpty()) {
            sb.append("\n  last " + mLastAdvertises.size() + " advertising:");
            for (AppAdvertiseStats stats : mLastAdvertises) {
                AppAdvertiseStats.dumpToString(sb, stats);
            }
            sb.append("\n");
        }

        if (!mAppAdvertiseStats.isEmpty()) {
            sb.append(
                    "  Total number of ongoing advertising                   : "
                            + mAppAdvertiseStats.size());
            sb.append("\n  Ongoing advertising:");
            for (Integer key : mAppAdvertiseStats.keySet()) {
                AppAdvertiseStats stats = mAppAdvertiseStats.get(key);
                AppAdvertiseStats.dumpToString(sb, stats);
            }
        }
        sb.append("\n");
        Log.d(TAG, sb.toString());
    }
}
+3 −13
Original line number Diff line number Diff line
@@ -39,8 +39,7 @@ import java.util.List;
import java.util.Map;

/** AdvStats class helps keep track of information about advertising on a per application basis. */
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public class AppAdvertiseStats {
class AppAdvertiseStats {
    private static final String TAG = AppAdvertiseStats.class.getSimpleName();

    private static DateTimeFormatter sDateFormat =
@@ -49,12 +48,6 @@ public class AppAdvertiseStats {
    static final String[] PHY_LE_STRINGS = {"LE_1M", "LE_2M", "LE_CODED"};
    static final int UUID_STRING_FILTER_LEN = 8;

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

    // GattService is needed to add scan event protos to be dumped later
    GattService mGattService;

    static class AppAdvertiserData {
        public boolean includeDeviceName = false;
        public boolean includeTxPowerLevel = false;
@@ -88,7 +81,7 @@ public class AppAdvertiseStats {
    }

    private int mAppUid;
    private String mAppName;
    @VisibleForTesting String mAppName;
    private int mId;
    private boolean mAdvertisingEnabled = false;
    private boolean mPeriodicAdvertisingEnabled = false;
@@ -107,13 +100,10 @@ public class AppAdvertiseStats {
    private int mPeriodicInterval = 0;
    public ArrayList<AppAdvertiserRecord> mAdvertiserRecords = new ArrayList<AppAdvertiserRecord>();

    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
    public AppAdvertiseStats(int appUid, int id, String name, ContextMap map, GattService service) {
    AppAdvertiseStats(int appUid, int id, String name) {
        this.mAppUid = appUid;
        this.mId = id;
        this.mAppName = name;
        this.mContextMap = map;
        this.mGattService = service;
    }

    void recordAdvertiseStart(
Loading