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

Commit d0afa1e7 authored by Omair Kamil's avatar Omair Kamil Committed by Automerger Merge Worker
Browse files

Merge "Refactor advertiser functions out of ContextMap." into main am: 349ae1f2 am: 8c526249

parents 9cc6dbcd 8c526249
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