summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author chelseahao <chelseahao@google.com> 2023-09-11 10:54:37 +0800
committer chelseahao <chelseahao@google.com> 2023-09-11 17:53:22 +0800
commit61c0185b297b69f50f12c37f744237cd225d0eb5 (patch)
tree362e0128976e1af66fc1a6ac44f3e0dd4d272e74
parent8d2b222965dc1d860fa6dc2f578646acb6b7cce7 (diff)
Add shared bluetooth device functions by settings and systemui to settingslib.
These two functions are copied from `AvailableMediaBluetoothDeviceUpdater#isFilterMatched`, `ConnectedBluetoothDeviceUpdater#isFilterMatched`. They check if a bluetooth device is a currently connected media device or currently connected other devices. They will be used both in settings (i.e., `AvailableMediaBluetoothDeviceUpdater#isFilterMatched`, `ConnectedBluetoothDeviceUpdater#isFilterMatched`) and systemui (i.e., the new bluetooth tile dialog). Test: make RunSettingsLibRoboTests -j40 Bug: 298124674 Change-Id: Idcfb284ad6c7e43283aac23c61e5b65b472cdfa5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java134
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java110
2 files changed, 242 insertions, 2 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 755d971e28a6..fa8c1fba6780 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -4,9 +4,9 @@ import static com.android.settingslib.widget.AdaptiveOutlineDrawable.ICON_TYPE_A
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothCsipSetCoordinator;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -14,6 +14,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
import android.net.Uri;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
@@ -23,6 +24,7 @@ import android.util.Pair;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
import androidx.core.graphics.drawable.IconCompat;
import com.android.settingslib.R;
@@ -470,6 +472,136 @@ public class BluetoothUtils {
return extraTagValue(KEY_HEARABLE_CONTROL_SLICE, data);
}
+ /**
+ * Check if the Bluetooth device is an AvailableMediaBluetoothDevice, which means:
+ * 1) currently connected
+ * 2) is Hearing Aid or LE Audio
+ * OR
+ * 3) connected profile matches currentAudioProfile
+ *
+ * @param cachedDevice the CachedBluetoothDevice
+ * @param audioManager audio manager to get the current audio profile
+ * @return if the device is AvailableMediaBluetoothDevice
+ */
+ @WorkerThread
+ public static boolean isAvailableMediaBluetoothDevice(
+ CachedBluetoothDevice cachedDevice, AudioManager audioManager) {
+ int audioMode = audioManager.getMode();
+ int currentAudioProfile;
+
+ if (audioMode == AudioManager.MODE_RINGTONE
+ || audioMode == AudioManager.MODE_IN_CALL
+ || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
+ // in phone call
+ currentAudioProfile = BluetoothProfile.HEADSET;
+ } else {
+ // without phone call
+ currentAudioProfile = BluetoothProfile.A2DP;
+ }
+
+ boolean isFilterMatched = false;
+ if (isDeviceConnected(cachedDevice)) {
+ // If device is Hearing Aid or LE Audio, it is compatible with HFP and A2DP.
+ // It would show in Available Devices group.
+ if (cachedDevice.isConnectedAshaHearingAidDevice()
+ || cachedDevice.isConnectedLeAudioDevice()) {
+ Log.d(TAG, "isFilterMatched() device : "
+ + cachedDevice.getName() + ", the profile is connected.");
+ return true;
+ }
+ // According to the current audio profile type,
+ // this page will show the bluetooth device that have corresponding profile.
+ // For example:
+ // If current audio profile is a2dp, show the bluetooth device that have a2dp profile.
+ // If current audio profile is headset,
+ // show the bluetooth device that have headset profile.
+ switch (currentAudioProfile) {
+ case BluetoothProfile.A2DP:
+ isFilterMatched = cachedDevice.isConnectedA2dpDevice();
+ break;
+ case BluetoothProfile.HEADSET:
+ isFilterMatched = cachedDevice.isConnectedHfpDevice();
+ break;
+ }
+ }
+ return isFilterMatched;
+ }
+
+ /**
+ * Check if the Bluetooth device is a ConnectedBluetoothDevice, which means:
+ * 1) currently connected
+ * 2) is not Hearing Aid or LE Audio
+ * AND
+ * 3) connected profile does not match currentAudioProfile
+ *
+ * @param cachedDevice the CachedBluetoothDevice
+ * @param audioManager audio manager to get the current audio profile
+ * @return if the device is AvailableMediaBluetoothDevice
+ */
+ @WorkerThread
+ public static boolean isConnectedBluetoothDevice(
+ CachedBluetoothDevice cachedDevice, AudioManager audioManager) {
+ int audioMode = audioManager.getMode();
+ int currentAudioProfile;
+
+ if (audioMode == AudioManager.MODE_RINGTONE
+ || audioMode == AudioManager.MODE_IN_CALL
+ || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
+ // in phone call
+ currentAudioProfile = BluetoothProfile.HEADSET;
+ } else {
+ // without phone call
+ currentAudioProfile = BluetoothProfile.A2DP;
+ }
+
+ boolean isFilterMatched = false;
+ if (isDeviceConnected(cachedDevice)) {
+ // If device is Hearing Aid or LE Audio, it is compatible with HFP and A2DP.
+ // It would not show in Connected Devices group.
+ if (cachedDevice.isConnectedAshaHearingAidDevice()
+ || cachedDevice.isConnectedLeAudioDevice()) {
+ return false;
+ }
+ // According to the current audio profile type,
+ // this page will show the bluetooth device that doesn't have corresponding profile.
+ // For example:
+ // If current audio profile is a2dp,
+ // show the bluetooth device that doesn't have a2dp profile.
+ // If current audio profile is headset,
+ // show the bluetooth device that doesn't have headset profile.
+ switch (currentAudioProfile) {
+ case BluetoothProfile.A2DP:
+ isFilterMatched = !cachedDevice.isConnectedA2dpDevice();
+ break;
+ case BluetoothProfile.HEADSET:
+ isFilterMatched = !cachedDevice.isConnectedHfpDevice();
+ break;
+ }
+ }
+ return isFilterMatched;
+ }
+
+ /**
+ * Check if the Bluetooth device is an active media device
+ *
+ * @param cachedDevice the CachedBluetoothDevice
+ * @return if the Bluetooth device is an active media device
+ */
+ public static boolean isActiveMediaDevice(CachedBluetoothDevice cachedDevice) {
+ return cachedDevice.isActiveDevice(BluetoothProfile.A2DP)
+ || cachedDevice.isActiveDevice(BluetoothProfile.HEADSET)
+ || cachedDevice.isActiveDevice(BluetoothProfile.HEARING_AID)
+ || cachedDevice.isActiveDevice(BluetoothProfile.LE_AUDIO);
+ }
+
+ private static boolean isDeviceConnected(CachedBluetoothDevice cachedDevice) {
+ if (cachedDevice == null) {
+ return false;
+ }
+ final BluetoothDevice device = cachedDevice.getDevice();
+ return device.getBondState() == BluetoothDevice.BOND_BONDED && device.isConnected();
+ }
+
@SuppressLint("NewApi") // Hidden API made public
private static boolean doesClassMatch(BluetoothClass btClass, int classId) {
return btClass.doesClassMatch(classId);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 83972e8ef6e3..7409eea2cd51 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -16,7 +16,6 @@
package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -25,6 +24,7 @@ import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
import android.net.Uri;
import android.util.Pair;
@@ -46,6 +46,8 @@ public class BluetoothUtilsTest {
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
+ @Mock
+ private AudioManager mAudioManager;
private Context mContext;
private static final String STRING_METADATA = "string_metadata";
@@ -255,4 +257,110 @@ public class BluetoothUtilsTest {
public void isAdvancedUntetheredDevice_noMetadata_returnFalse() {
assertThat(BluetoothUtils.isAdvancedUntetheredDevice(mBluetoothDevice)).isEqualTo(false);
}
+
+ @Test
+ public void isAvailableMediaBluetoothDevice_isConnectedLeAudioDevice_returnTrue() {
+ when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isAvailableMediaBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(true);
+ }
+
+ @Test
+ public void isAvailableMediaBluetoothDevice_isHeadset_isConnectedA2dpDevice_returnFalse() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
+ when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isAvailableMediaBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(false);
+ }
+
+ @Test
+ public void isAvailableMediaBluetoothDevice_isA2dp_isConnectedA2dpDevice_returnTrue() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
+ when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isAvailableMediaBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(true);
+ }
+
+ @Test
+ public void isAvailableMediaBluetoothDevice_isHeadset_isConnectedHfpDevice_returnTrue() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isAvailableMediaBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(true);
+ }
+
+ @Test
+ public void isConnectedBluetoothDevice_isConnectedLeAudioDevice_returnFalse() {
+ when(mCachedBluetoothDevice.isConnectedLeAudioDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(false);
+ }
+
+ @Test
+ public void isConnectedBluetoothDevice_isHeadset_isConnectedA2dpDevice_returnTrue() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
+ when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(true);
+ }
+
+ @Test
+ public void isConnectedBluetoothDevice_isA2dp_isConnectedA2dpDevice_returnFalse() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
+ when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(false);
+ }
+
+ @Test
+ public void isConnectedBluetoothDevice_isHeadset_isConnectedHfpDevice_returnFalse() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
+ when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(true);
+
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(false);
+ }
+
+ @Test
+ public void isConnectedBluetoothDevice_isNotConnected_returnFalse() {
+ when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
+ when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mBluetoothDevice.isConnected()).thenReturn(false);
+
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice,
+ mAudioManager)).isEqualTo(false);
+ }
}