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

Commit 1988e657 authored by Palash Ahuja's avatar Palash Ahuja Committed by Automerger Merge Worker
Browse files

Merge "[BluetoothMetrics] Refactor Hashed Name Retrieval from logging" into...

Merge "[BluetoothMetrics] Refactor Hashed Name Retrieval from logging" into main am: b49bda56 am: eb7afbc0

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2983018



Change-Id: Icc5a5eef36fb42dcf621ada6b9479f2c2929c62b
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 023a5100 eb7afbc0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -763,7 +763,8 @@ class AdapterProperties {
        if (state == BluetoothProfile.STATE_CONNECTING) {
            BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_DEVICE_NAME_REPORTED,
                    metricId, device.getName());
            MetricsLogger.getInstance().logSanitizedBluetoothDeviceName(metricId, device.getName());
            MetricsLogger.getInstance()
                    .logAllowlistedDeviceNameHash(metricId, device.getName(), true);
        }
        BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, state,
                0 /* deprecated */, profile, mService.obfuscateAddress(device),
+0 −1
Original line number Diff line number Diff line
@@ -941,7 +941,6 @@ public class AdapterService extends Service {
            long socketCreationTimeNanos,
            boolean isSerialPort,
            int appUid) {

        int metricId = getMetricId(device);
        long currentTime = System.nanoTime();
        long endToEndLatencyNanos = currentTime - socketCreationTimeNanos;
+72 −35
Original line number Diff line number Diff line
@@ -19,21 +19,23 @@ import static com.android.bluetooth.BtRestrictedStatsLog.RESTRICTED_BLUETOOTH_DE

import android.app.AlarmManager;
import android.content.Context;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;

import androidx.annotation.RequiresApi;

import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog;
import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats;
import com.android.bluetooth.BluetoothMetricsProto.ProfileId;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.BtRestrictedStatsLog;
import com.android.bluetooth.Utils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.build.SdkLevel;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import com.google.common.hash.Hashing;

import java.io.ByteArrayInputStream;
import java.io.File;
@@ -42,7 +44,9 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Class of Bluetooth Metrics
@@ -269,11 +273,10 @@ public class MetricsLogger {
        mAlarmManager.cancel(mOnAlarmListener);
    }

    protected boolean logSanitizedBluetoothDeviceName(int metricId, String deviceName) {
        if (!mBloomFilterInitialized || deviceName == null) {
            return false;
    private List<String> getWordBreakdownList(String deviceName) {
        if (deviceName == null) {
            return new ArrayList<String>();
        }

        // remove more than one spaces in a row
        deviceName = deviceName.trim().replaceAll(" +", " ");
        // remove non alphanumeric characters and spaces, and transform to lower cases.
@@ -282,52 +285,86 @@ public class MetricsLogger {

        if (words.length > MAX_WORDS_ALLOWED_IN_DEVICE_NAME) {
            // Validity checking here to avoid excessively long sequences
            return false;
            return new ArrayList<String>();
        }
        // find the longest matched substring
        String matchedString = "";
        byte[] matchedSha256 = null;
        // collect the word breakdown in an arraylist
        ArrayList<String> wordBreakdownList = new ArrayList<String>();
        for (int start = 0; start < words.length; start++) {

            String toBeMatched = "";
            StringBuilder deviceNameCombination = new StringBuilder();
            for (int end = start; end < words.length; end++) {
                toBeMatched += words[end];
                // TODO(b/280868296): Refactor to log even if bloom filter isn't initialized.
                if (SdkLevel.isAtLeastU()) {
                    BtRestrictedStatsLog.write(RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED,
                            toBeMatched);
                deviceNameCombination.append(words[end]);
                wordBreakdownList.add(deviceNameCombination.toString());
            }
                byte[] sha256 = getSha256(toBeMatched);
                if (sha256 == null) {
                    continue;
        }

                if (mBloomFilter.mightContain(sha256)
                        && toBeMatched.length() > matchedString.length()) {
                    matchedString = toBeMatched;
                    matchedSha256 = sha256;
        return wordBreakdownList;
    }

    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    private void uploadRestrictedBluetothDeviceName(List<String> wordBreakdownList) {
        for (String word : wordBreakdownList) {
            BtRestrictedStatsLog.write(RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED, word);
        }
    }

        // upload the sha256 of the longest matched string.
        if (matchedSha256 == null) {
            return false;
    private String getMatchedString(List<String> wordBreakdownList) {
        if (!mBloomFilterInitialized || wordBreakdownList.isEmpty()) {
            return "";
        }
        statslogBluetoothDeviceNames(
                metricId,
                matchedString,
                Hashing.sha256().hashString(matchedString, StandardCharsets.UTF_8).toString());
        return true;

        String matchedString = "";
        for (String word : wordBreakdownList) {
            byte[] sha256 = getSha256(word);
            if (mBloomFilter.mightContain(sha256) && word.length() > matchedString.length()) {
                matchedString = word;
            }
        }
        return matchedString;
    }

    protected void statslogBluetoothDeviceNames(int metricId, String matchedString, String sha256) {
    protected String getAllowlistedDeviceNameHash(String deviceName) {
        List<String> wordBreakdownList = getWordBreakdownList(deviceName);
        String matchedString = getMatchedString(wordBreakdownList);
        return getSha256String(matchedString);
    }

    protected String logAllowlistedDeviceNameHash(
            int metricId, String deviceName, boolean logRestrictedNames) {
        List<String> wordBreakdownList = getWordBreakdownList(deviceName);
        String matchedString = getMatchedString(wordBreakdownList);
        if (logRestrictedNames) {
            // Log the restricted bluetooth device name
            if (SdkLevel.isAtLeastU()) {
                uploadRestrictedBluetothDeviceName(wordBreakdownList);
            }
        }
        if (!matchedString.isEmpty()) {
            statslogBluetoothDeviceNames(metricId, matchedString);
        }
        return getSha256String(matchedString);
    }

    protected void statslogBluetoothDeviceNames(int metricId, String matchedString) {
        String sha256 = getSha256String(matchedString);
        Log.d(TAG,
                "Uploading sha256 hash of matched bluetooth device name: " + sha256);
        BluetoothStatsLog.write(
                BluetoothStatsLog.BLUETOOTH_HASHED_DEVICE_NAME_REPORTED, metricId, sha256);
    }

    protected static String getSha256String(String name) {
        if (name.isEmpty()) {
            return "";
        }
        StringBuilder hexString = new StringBuilder();
        byte[] hashBytes = getSha256(name);
        for (byte b : hashBytes) {
            hexString.append(String.format("%02x", b));
        }
        return hexString.toString();
    }

    protected static byte[] getSha256(String name) {
        MessageDigest digest = null;
        try {
+69 −196
Original line number Diff line number Diff line
@@ -42,15 +42,48 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Unit tests for {@link MetricsLogger}
 */
/** Unit tests for {@link MetricsLogger} */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class MetricsLoggerTest {
    private static final String TEST_BLOOMFILTER_NAME = "TestBloomfilter";

    private static final HashMap<String, String> SANITIZED_DEVICE_NAME_MAP = new HashMap<>();

    static {
        SANITIZED_DEVICE_NAME_MAP.put("AirpoDspro", "airpodspro");
        SANITIZED_DEVICE_NAME_MAP.put("AirpoDs-pro", "airpodspro");
        SANITIZED_DEVICE_NAME_MAP.put("Someone's AirpoDs", "airpods");
        SANITIZED_DEVICE_NAME_MAP.put("Galaxy Buds pro", "galaxybudspro");
        SANITIZED_DEVICE_NAME_MAP.put("Someone's AirpoDs", "airpods");
        SANITIZED_DEVICE_NAME_MAP.put("Who's Pixel 7", "pixel7");
        SANITIZED_DEVICE_NAME_MAP.put("陈的pixel 7手机", "pixel7");
        SANITIZED_DEVICE_NAME_MAP.put("pixel 7 pro", "pixel7pro");
        SANITIZED_DEVICE_NAME_MAP.put("My Pixel 7 Pro", "pixel7pro");
        SANITIZED_DEVICE_NAME_MAP.put("My Pixel   7   PRO", "pixel7pro");
        SANITIZED_DEVICE_NAME_MAP.put("My Pixel   7   - PRO", "pixel7pro");
        SANITIZED_DEVICE_NAME_MAP.put("My BMW X5", "bmwx5");
        SANITIZED_DEVICE_NAME_MAP.put("Jane Doe's Tesla Model--X", "teslamodelx");
        SANITIZED_DEVICE_NAME_MAP.put("TESLA of Jane DOE", "tesla");
        SANITIZED_DEVICE_NAME_MAP.put("SONY WH-1000XM noise cancelling headsets", "sonywh1000xm");
        SANITIZED_DEVICE_NAME_MAP.put("Amazon Echo Dot in Kitchen", "amazonechodot");
        SANITIZED_DEVICE_NAME_MAP.put("斯巴鲁 Starlink", "starlink");
        SANITIZED_DEVICE_NAME_MAP.put("大黄蜂MyLink", "mylink");
        SANITIZED_DEVICE_NAME_MAP.put("Dad's Fitbit Charge 3", "fitbitcharge3");
        SANITIZED_DEVICE_NAME_MAP.put("Mike's new Galaxy Buds 2", "galaxybuds2");
        SANITIZED_DEVICE_NAME_MAP.put("My third Ford F-150", "fordf150");
        SANITIZED_DEVICE_NAME_MAP.put("BOSE QC_35 Noise Cancelling Headsets", "boseqc35");
        SANITIZED_DEVICE_NAME_MAP.put("Fitbit versa 3 band", "fitbitversa3");
        SANITIZED_DEVICE_NAME_MAP.put("vw atlas", "vwatlas");
        SANITIZED_DEVICE_NAME_MAP.put("My volkswagen tiguan", "volkswagentiguan");
        SANITIZED_DEVICE_NAME_MAP.put("SomeDevice1", "");
        SANITIZED_DEVICE_NAME_MAP.put("Some Device-2", "");
        SANITIZED_DEVICE_NAME_MAP.put("abcgfDG gdfg", "");
        SANITIZED_DEVICE_NAME_MAP.put("Bluetooth headset", "");
    }

    private TestableMetricsLogger mTestableMetricsLogger;
    @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

@@ -68,16 +101,13 @@ public class MetricsLoggerTest {
        }

        @Override
        protected void scheduleDrains() {
        }
        protected void scheduleDrains() {}

        @Override
        protected void cancelPendingDrain() {
        }
        protected void cancelPendingDrain() {}

        @Override
        protected void statslogBluetoothDeviceNames(
                int metricId, String matchedString, String sha256) {
        protected void statslogBluetoothDeviceNames(int metricId, String matchedString) {
            mTestableDeviceNames.merge(matchedString, 1, Integer::sum);
        }
    }
@@ -88,8 +118,7 @@ public class MetricsLoggerTest {
        MetricsLogger.dumpProto(BluetoothLog.newBuilder());
        mTestableMetricsLogger = new TestableMetricsLogger();
        mTestableMetricsLogger.mBloomFilterInitialized = true;
        doReturn(null)
                .when(mMockAdapterService).registerReceiver(any(), any());
        doReturn(null).when(mMockAdapterService).registerReceiver(any(), any());
    }

    @After
@@ -99,9 +128,7 @@ public class MetricsLoggerTest {
        mTestableMetricsLogger.close();
    }

    /**
     * Simple test to verify that profile connection event can be logged, dumped, and cleaned
     */
    /** Simple test to verify that profile connection event can be logged, dumped, and cleaned */
    @Test
    public void testLogProfileConnectionEvent() {
        MetricsLogger.logProfileConnectionEvent(ProfileId.AVRCP);
@@ -119,9 +146,7 @@ public class MetricsLoggerTest {
        Assert.assertEquals(0, metricsProtoAfterDump.getProfileConnectionStatsCount());
    }

    /**
     * Test whether multiple profile's connection events can be logged interleaving
     */
    /** Test whether multiple profile's connection events can be logged interleaving */
    @Test
    public void testLogProfileConnectionEventMultipleProfile() {
        MetricsLogger.logProfileConnectionEvent(ProfileId.AVRCP);
@@ -134,11 +159,11 @@ public class MetricsLoggerTest {
        HashMap<ProfileId, ProfileConnectionStats> profileConnectionCountMap =
                getProfileUsageStatsMap(metricsProto.getProfileConnectionStatsList());
        Assert.assertTrue(profileConnectionCountMap.containsKey(ProfileId.AVRCP));
        Assert.assertEquals(2,
                profileConnectionCountMap.get(ProfileId.AVRCP).getNumTimesConnected());
        Assert.assertEquals(
                2, profileConnectionCountMap.get(ProfileId.AVRCP).getNumTimesConnected());
        Assert.assertTrue(profileConnectionCountMap.containsKey(ProfileId.HEADSET));
        Assert.assertEquals(1,
                profileConnectionCountMap.get(ProfileId.HEADSET).getNumTimesConnected());
        Assert.assertEquals(
                1, profileConnectionCountMap.get(ProfileId.HEADSET).getNumTimesConnected());
        // Verify that MetricsLogger's internal state is cleared after a dump
        BluetoothLog.Builder metricsBuilderAfterDump = BluetoothLog.newBuilder();
        MetricsLogger.dumpProto(metricsBuilderAfterDump);
@@ -153,9 +178,7 @@ public class MetricsLoggerTest {
        return profileUsageStatsMap;
    }

    /**
     * Test add counters and send them to statsd
     */
    /** Test add counters and send them to statsd */
    @Test
    public void testAddAndSendCountersNormalCases() {
        mTestableMetricsLogger.init(mMockAdapterService);
@@ -172,12 +195,9 @@ public class MetricsLoggerTest {
        mTestableMetricsLogger.cacheCount(2, 5);
        mTestableMetricsLogger.cacheCount(3, 1);
        mTestableMetricsLogger.drainBufferedCounters();
        Assert.assertEquals(
                3L, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
        Assert.assertEquals(
                10L, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
        Assert.assertEquals(
                1L, mTestableMetricsLogger.mTestableCounters.get(3).longValue());
        Assert.assertEquals(3L, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
        Assert.assertEquals(10L, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
        Assert.assertEquals(1L, mTestableMetricsLogger.mTestableCounters.get(3).longValue());
    }

    @Test
@@ -204,8 +224,7 @@ public class MetricsLoggerTest {
        mTestableMetricsLogger.cacheCount(2, Long.MAX_VALUE);
        mTestableMetricsLogger.close();

        Assert.assertEquals(
                1, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
        Assert.assertEquals(1, mTestableMetricsLogger.mTestableCounters.get(1).longValue());
        Assert.assertEquals(
                Long.MAX_VALUE, mTestableMetricsLogger.mTestableCounters.get(2).longValue());
    }
@@ -226,172 +245,26 @@ public class MetricsLoggerTest {
    }

    @Test
    public void testDeviceNameUploadingDeviceSet1() {
        initTestingBloomfitler();

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "a b c d e f g h pixel 7");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "AirpoDspro");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("airpodspro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "AirpoDs-pro");
        Assert.assertEquals(2,
                mTestableMetricsLogger.mTestableDeviceNames.get("airpodspro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "Someone's AirpoDs");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("airpods").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "Who's Pixel 7");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "陈的pixel 7手机");
        Assert.assertEquals(2,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(2, "pixel 7 pro");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7pro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "My Pixel 7 PRO");
        Assert.assertEquals(2,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7pro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "My Pixel   7   PRO");
        Assert.assertEquals(3,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7pro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "My Pixel   7   - PRO");
        Assert.assertEquals(4,
                mTestableMetricsLogger.mTestableDeviceNames.get("pixel7pro").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "My BMW X5");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("bmwx5").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "Jane Doe's Tesla Model--X");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("teslamodelx").intValue());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "TESLA of Jane DOE");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("tesla").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "SONY WH-1000XM noise cancelling headsets");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("sonywh1000xm").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "SONY WH-1000XM4 noise cancelling headsets");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("sonywh1000xm4").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "Amazon Echo Dot in Kitchen");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("amazonechodot").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "斯巴鲁 Starlink");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("starlink").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "大黄蜂MyLink");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("mylink").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "Dad's Fitbit Charge 3");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("fitbitcharge3").intValue());

        mTestableMetricsLogger.mTestableDeviceNames.clear();
        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, " ");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "SomeDevice1");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "Bluetooth headset");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(3, "Some Device-2");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(5, "abcgfDG gdfg");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());
    public void testDeviceNameToSha() {
        initTestingBloomfilter();
        for (Map.Entry<String, String> entry : SANITIZED_DEVICE_NAME_MAP.entrySet()) {
            String deviceName = entry.getKey();
            String sha256 = MetricsLogger.getSha256String(entry.getValue());
            Assert.assertEquals(
                    sha256,
                    mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, deviceName, true));
        }
    }

    @Test
    public void testDeviceNameUploadingDeviceSet2() {
        initTestingBloomfitler();

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "Galaxy Buds pro");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("galaxybudspro").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "Mike's new Galaxy Buds 2");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("galaxybuds2").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(877, "My third Ford F-150");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("fordf150").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "BOSE QC_35 Noise Cancelling Headsets");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("boseqc35").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "BOSE Quiet Comfort 35 Headsets");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("bosequietcomfort35").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "Fitbit versa 3 band");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("fitbitversa3").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "vw atlas");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("vwatlas").intValue());

        mTestableMetricsLogger
                .logSanitizedBluetoothDeviceName(1, "My volkswagen tiguan");
        Assert.assertEquals(1,
                mTestableMetricsLogger.mTestableDeviceNames.get("volkswagentiguan").intValue());

        mTestableMetricsLogger.mTestableDeviceNames.clear();
        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, " ");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, "weirddevice");
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

        mTestableMetricsLogger.logSanitizedBluetoothDeviceName(1, ""
                + "My BOSE Quiet Comfort 35 Noise Cancelling Headsets");
        // Too long, won't process
        Assert.assertTrue(mTestableMetricsLogger.mTestableDeviceNames.isEmpty());

    public void uploadEmptyDeviceName() {
        initTestingBloomfilter();
        Assert.assertEquals("", mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, "", true));
    }
    private void initTestingBloomfitler() {
        byte[] bloomfilterData = DeviceBloomfilterGenerator.hexStringToByteArray(

    private void initTestingBloomfilter() {
        byte[] bloomfilterData =
                DeviceBloomfilterGenerator.hexStringToByteArray(
                        DeviceBloomfilterGenerator.BLOOM_FILTER_DEFAULT);
        try {
            mTestableMetricsLogger.setBloomfilter(