diff options
4 files changed, 151 insertions, 0 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index a5f3df9f628d..7927c5d460a4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -81,8 +81,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private int mDeviceMode; private long mHiSyncId; private int mGroupId; + // Need this since there is no method for getting RSSI short mRssi; + // mProfiles and mRemovedProfiles does not do swap() between main and sub device. It is // because current sub device is only for HearingAid and its profile is the same. private final Collection<LocalBluetoothProfile> mProfiles = new CopyOnWriteArrayList<>(); diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java new file mode 100644 index 000000000000..feb5e0bf6e69 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtils.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 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.settingslib.bluetooth; + +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FrameworkStatsLog; + +import java.util.HashMap; + +/** Utils class to report hearing aid metrics to statsd */ +public final class HearingAidStatsLogUtils { + + private static final String TAG = "HearingAidStatsLogUtils"; + private static final HashMap<String, Integer> sDeviceAddressToBondEntryMap = new HashMap<>(); + + /** + * Sets the mapping from hearing aid device to the bond entry where this device starts it's + * bonding(connecting) process. + * + * @param bondEntry The entry page id where the bonding process starts + * @param device The bonding(connecting) hearing aid device + */ + public static void setBondEntryForDevice(int bondEntry, CachedBluetoothDevice device) { + sDeviceAddressToBondEntryMap.put(device.getAddress(), bondEntry); + } + + /** + * Logs hearing aid device information to westworld, including device mode, device side, and + * entry page id where the binding(connecting) process starts. + * + * Only logs the info once after hearing aid is bonded(connected). Clears the map entry of this + * device when logging is completed. + * + * @param device The bonded(connected) hearing aid device + */ + public static void logHearingAidInfo(CachedBluetoothDevice device) { + final String deviceAddress = device.getAddress(); + if (sDeviceAddressToBondEntryMap.containsKey(deviceAddress)) { + final int bondEntry = sDeviceAddressToBondEntryMap.getOrDefault(deviceAddress, -1); + final int deviceMode = device.getDeviceMode(); + final int deviceSide = device.getDeviceSide(); + FrameworkStatsLog.write(FrameworkStatsLog.HEARING_AID_INFO_REPORTED, deviceMode, + deviceSide, bondEntry); + + sDeviceAddressToBondEntryMap.remove(deviceAddress); + } else { + Log.w(TAG, "The device address was not found. Hearing aid device info is not logged."); + } + } + + @VisibleForTesting + static HashMap<String, Integer> getDeviceAddressToBondEntryMap() { + return sDeviceAddressToBondEntryMap; + } + + private HearingAidStatsLogUtils() {} +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 4714ff93625b..8a9f9dd9c3fb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -352,6 +352,8 @@ public class LocalBluetoothProfileManager { cachedDevice.setHiSyncId(newHiSyncId); } } + + HearingAidStatsLogUtils.logHearingAidInfo(cachedDevice); } if (getCsipSetCoordinatorProfile() != null diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java new file mode 100644 index 000000000000..0cf5b8900245 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidStatsLogUtilsTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 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.settingslib.bluetooth; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import com.android.internal.util.FrameworkStatsLog; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +import java.util.HashMap; + +@RunWith(RobolectricTestRunner.class) +public class HearingAidStatsLogUtilsTest { + + private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"; + + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private CachedBluetoothDevice mCachedBluetoothDevice; + + @Test + public void setBondEntryForDevice_addsEntryToDeviceAddressToBondEntryMap() { + when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); + + HearingAidStatsLogUtils.setBondEntryForDevice( + FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH, + mCachedBluetoothDevice); + + final HashMap<String, Integer> map = + HearingAidStatsLogUtils.getDeviceAddressToBondEntryMap(); + assertThat(map.containsKey(TEST_DEVICE_ADDRESS)).isTrue(); + assertThat(map.get(TEST_DEVICE_ADDRESS)).isEqualTo( + FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH); + } + + @Test + public void logHearingAidInfo_removesEntryFromDeviceAddressToBondEntryMap() { + when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS); + + HearingAidStatsLogUtils.setBondEntryForDevice( + FrameworkStatsLog.HEARING_AID_INFO_REPORTED__BOND_ENTRY__BLUETOOTH, + mCachedBluetoothDevice); + HearingAidStatsLogUtils.logHearingAidInfo(mCachedBluetoothDevice); + + final HashMap<String, Integer> map = + HearingAidStatsLogUtils.getDeviceAddressToBondEntryMap(); + assertThat(map.containsKey(TEST_DEVICE_ADDRESS)).isFalse(); + } +} |