diff options
| author | 2023-09-11 10:54:37 +0800 | |
|---|---|---|
| committer | 2023-09-11 17:53:22 +0800 | |
| commit | 61c0185b297b69f50f12c37f744237cd225d0eb5 (patch) | |
| tree | 362e0128976e1af66fc1a6ac44f3e0dd4d272e74 | |
| parent | 8d2b222965dc1d860fa6dc2f578646acb6b7cce7 (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
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); + } } |