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

Commit 6eaf15e6 authored by Jayden Kim's avatar Jayden Kim
Browse files

Adds LE Advertise Counter

Bug: 236321914
Test: atest BluetoothInstrumentationTests and device test
Tag: #feature
Change-Id: I0908fb106dc9766cc99512d87fab5175a8b65545
parent 68054644
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.bluetooth.gatt;

import static android.bluetooth.BluetoothProtoEnums.LE_ADV_ERROR_ON_START_COUNT;

import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
@@ -175,6 +177,7 @@ public class AdvertiseManager {
                stats.recordAdvertiseStop();
            }
            mAdvertiserMap.removeAppAdvertiseStats(regId);
            AppAdvertiseStats.recordAdvertiseErrorCount(LE_ADV_ERROR_ON_START_COUNT);
        }

        callback.onAdvertisingSetStarted(advertiserId, txPower, status);
+114 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.bluetooth.gatt;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.PeriodicAdvertisingParameters;
@@ -24,6 +25,8 @@ import android.util.SparseArray;

import androidx.annotation.VisibleForTesting;

import com.android.bluetooth.btservice.MetricsLogger;

import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
@@ -164,6 +167,7 @@ public class AppAdvertiseStats {
            mPeriodicIncludeTxPower = periodicParameters.getIncludeTxPower();
            mPeriodicInterval = periodicParameters.getInterval();
        }
        recordAdvertiseEnableCount(true, mConnectable, mPeriodicAdvertisingEnabled);
    }

    void recordAdvertiseStart(int duration, int maxExtAdvEvents) {
@@ -171,14 +175,37 @@ public class AppAdvertiseStats {
    }

    void recordAdvertiseStop() {
        mAdvertisingEnabled = false;
        mPeriodicAdvertisingEnabled = false;
        recordAdvertiseEnableCount(false, mConnectable, mPeriodicAdvertisingEnabled);
        if (!mAdvertiserRecords.isEmpty()) {
            AppAdvertiserRecord record = mAdvertiserRecords.get(mAdvertiserRecords.size() - 1);
            record.stopTime = Instant.now();
            Duration duration = Duration.between(record.startTime, record.stopTime);
            recordAdvertiseDurationCount(duration, mConnectable, mPeriodicAdvertisingEnabled);
        }
        mAdvertisingEnabled = false;
        mPeriodicAdvertisingEnabled = false;
    }

    static void recordAdvertiseInstanceCount(int instanceCount) {
        if (instanceCount < 5) {
            MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_INSTANCE_COUNT_5, 1);
        } else if (instanceCount < 10) {
            MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_INSTANCE_COUNT_10, 1);
        } else if (instanceCount < 15) {
            MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_INSTANCE_COUNT_15, 1);
        } else {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_INSTANCE_COUNT_15P, 1);
        }
    }

    static void recordAdvertiseErrorCount(int key) {
        if (key != BluetoothProtoEnums.LE_ADV_ERROR_ON_START_COUNT) {
            return;
        }
        MetricsLogger.getInstance().cacheCount(key, 1);
    }

    void enableAdvertisingSet(boolean enable, int duration, int maxExtAdvEvents) {
        if (enable) {
            //if the advertisingSet have not been disabled, skip enabling.
@@ -269,6 +296,91 @@ public class AppAdvertiseStats {
        this.mId = id;
    }

    private static void recordAdvertiseDurationCount(Duration duration, boolean isConnectable,
            boolean inPeriodic) {
        if (duration.compareTo(Duration.ofMinutes(1)) < 0) {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_1M, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_1M, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_1M, 1);
            }
        } else if (duration.compareTo(Duration.ofMinutes(30)) < 0) {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_30M, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_30M, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_30M, 1);
            }
        } else if (duration.compareTo(Duration.ofHours(1)) < 0) {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_1H, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_1H, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_1H, 1);
            }
        } else if (duration.compareTo(Duration.ofHours(3)) < 0) {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_3H, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_3H, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_3H, 1);
            }
        } else {
            MetricsLogger.getInstance().cacheCount(
                    BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_3HP, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_3HP, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_3HP, 1);
            }
        }
    }

    private static void recordAdvertiseEnableCount(boolean enable, boolean isConnectable,
            boolean inPeriodic) {
        if (enable) {
            MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_COUNT_ENABLE, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_ENABLE, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_ENABLE, 1);
            }
        } else {
            MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_COUNT_DISABLE, 1);
            if (isConnectable) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_DISABLE, 1);
            }
            if (inPeriodic) {
                MetricsLogger.getInstance().cacheCount(
                        BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_DISABLE, 1);
            }
        }
    }

    private static String printByteArrayInHex(byte[] data) {
        final StringBuilder hex = new StringBuilder();
        for (byte b : data) {
+3 −0
Original line number Diff line number Diff line
@@ -486,6 +486,9 @@ public class ContextMap<C, T> {
            }
            stats.recordAdvertiseStart(parameters, advertiseData, scanResponse,
                    periodicParameters, periodicData, duration, maxExtAdvEvents);
            int advertiseInstanceCount = mAppAdvertiseStats.size();
            Log.d(TAG, "advertiseInstanceCount is " + advertiseInstanceCount);
            AppAdvertiseStats.recordAdvertiseInstanceCount(advertiseInstanceCount);
        }
    }

+74 −0
Original line number Diff line number Diff line
@@ -18,16 +18,27 @@ package com.android.bluetooth.gatt;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.PeriodicAdvertisingParameters;

import com.android.bluetooth.btservice.MetricsLogger;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

/**
 * Test cases for {@link AppAdvertiseStats}.
@@ -42,6 +53,21 @@ public class AppAdvertiseStatsTest {
    @Mock
    private GattService service;

    @Mock
    private MetricsLogger  mMetricsLogger;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        MetricsLogger.setInstanceForTesting(mMetricsLogger);
    }

    @After
    public void tearDown() throws Exception {
        MetricsLogger.setInstanceForTesting(null);
        MetricsLogger.getInstance();
    }

    @Test
    public void constructor() {
        int appUid = 0;
@@ -255,4 +281,52 @@ public class AppAdvertiseStatsTest {

        AppAdvertiseStats.dumpToString(sb, appAdvertiseStats);
    }

    @Test
    public void testAdvertiseCounterMetrics() {
        int appUid = 0;
        int id = 1;
        String name = "name";

        AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name, map, service);

        AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder()
                .setConnectable(true).build();
        AdvertiseData advertiseData = new AdvertiseData.Builder().build();
        AdvertiseData scanResponse = new AdvertiseData.Builder().build();
        PeriodicAdvertisingParameters periodicParameters =
                new PeriodicAdvertisingParameters.Builder().build();
        AdvertiseData periodicData = new AdvertiseData.Builder().build();

        appAdvertiseStats.recordAdvertiseStart(
                parameters,
                advertiseData,
                scanResponse,
                periodicParameters,
                periodicData,
                0,
                0
        );
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_ENABLE), eq((long) 1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_ENABLE), eq((long)1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_ENABLE), eq((long) 1));
        Mockito.clearInvocations(mMetricsLogger);

        appAdvertiseStats.recordAdvertiseStop();
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_DISABLE), eq((long) 1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_CONNECTABLE_DISABLE), eq((long)1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_COUNT_PERIODIC_DISABLE), eq((long) 1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_TOTAL_1M), eq((long) 1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_CONNECTABLE_1M), eq((long) 1));
        verify(mMetricsLogger, times(1)).cacheCount(
                eq(BluetoothProtoEnums.LE_ADV_DURATION_COUNT_PERIODIC_1M), eq((long) 1));
    }
}