From 92fb7bddbfcc38dd2aa6854a0b027edc821aa902 Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Tue, 15 Aug 2023 18:28:50 -0700 Subject: [PATCH] Disable the spatializer options for device categories If the BT device cannot be of category headphones do not show the spatializer options. Test: manual & atest BluetoothDetailsSpatialAudioControllerTest Bug: 297265575 Change-Id: I7f044d40afadec6ccf659ae4969c0d6e2dc8c79e --- ...toothDetailsAudioDeviceTypeController.java | 1 + ...luetoothDetailsSpatialAudioController.java | 82 +++++++++----- ...oothDetailsSpatialAudioControllerTest.java | 104 +++++------------- 3 files changed, 81 insertions(+), 106 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java b/src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java index fe0d14182cc..9571767253c 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java @@ -109,6 +109,7 @@ public class BluetoothDetailsAudioDeviceTypeController extends BluetoothDetailsC mAudioManager.setBluetoothAudioDeviceCategory(mCachedDevice.getAddress(), mCachedDevice.getDevice().getType() == DEVICE_TYPE_LE, Integer.parseInt(value)); + mCachedDevice.onAudioDeviceCategoryChanged(); } } return true; diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java index bec6b03771f..c431ceeb0ae 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java @@ -53,9 +53,7 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont @VisibleForTesting PreferenceCategory mProfilesContainer; @VisibleForTesting - AudioDeviceAttributes mAudioDevice; - - private boolean mIsAvailable; + AudioDeviceAttributes mAudioDevice = null; public BluetoothDetailsSpatialAudioController( Context context, @@ -65,13 +63,11 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont super(context, fragment, device, lifecycle); AudioManager audioManager = context.getSystemService(AudioManager.class); mSpatializer = audioManager.getSpatializer(); - getAvailableDevice(); - } @Override public boolean isAvailable() { - return mIsAvailable; + return mSpatializer.getImmersiveAudioLevel() != SPATIALIZER_IMMERSIVE_LEVEL_NONE; } @Override @@ -79,15 +75,11 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont SwitchPreference switchPreference = (SwitchPreference) preference; String key = switchPreference.getKey(); if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) { - if (switchPreference.isChecked()) { - mSpatializer.addCompatibleAudioDevice(mAudioDevice); - } else { - mSpatializer.removeCompatibleAudioDevice(mAudioDevice); - } - refresh(); + updateSpatializerEnabled(switchPreference.isChecked()); + refreshSpatialAudioEnabled(switchPreference); return true; } else if (TextUtils.equals(key, KEY_HEAD_TRACKING)) { - mSpatializer.setHeadTrackerEnabled(switchPreference.isChecked(), mAudioDevice); + updateSpatializerHeadTracking(switchPreference.isChecked()); return true; } else { Log.w(TAG, "invalid key name."); @@ -95,6 +87,26 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont } } + private void updateSpatializerEnabled(boolean enabled) { + if (mAudioDevice == null) { + Log.w(TAG, "cannot update spatializer enabled for null audio device."); + return; + } + if (enabled) { + mSpatializer.addCompatibleAudioDevice(mAudioDevice); + } else { + mSpatializer.removeCompatibleAudioDevice(mAudioDevice); + } + } + + private void updateSpatializerHeadTracking(boolean enabled) { + if (mAudioDevice == null) { + Log.w(TAG, "cannot update spatializer head tracking for null audio device."); + return; + } + mSpatializer.setHeadTrackerEnabled(enabled, mAudioDevice); + } + @Override public String getPreferenceKey() { return KEY_SPATIAL_AUDIO_GROUP; @@ -109,15 +121,30 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont @Override protected void refresh() { if (mAudioDevice == null) { - return; + getAvailableDevice(); } SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO); - if (spatialAudioPref == null) { + if (spatialAudioPref == null && mAudioDevice != null) { spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext()); mProfilesContainer.addPreference(spatialAudioPref); + } else if (mAudioDevice == null || !mSpatializer.isAvailableForDevice(mAudioDevice)) { + if (spatialAudioPref != null) { + mProfilesContainer.removePreference(spatialAudioPref); + } + final SwitchPreference headTrackingPref = + mProfilesContainer.findPreference(KEY_HEAD_TRACKING); + if (headTrackingPref != null) { + mProfilesContainer.removePreference(headTrackingPref); + } + mAudioDevice = null; + return; } + refreshSpatialAudioEnabled(spatialAudioPref); + } + + private void refreshSpatialAudioEnabled(SwitchPreference spatialAudioPref) { boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice); Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn); spatialAudioPref.setChecked(isSpatialAudioOn); @@ -127,9 +154,13 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext()); mProfilesContainer.addPreference(headTrackingPref); } + refreshHeadTracking(spatialAudioPref, headTrackingPref); + } + private void refreshHeadTracking(SwitchPreference spatialAudioPref, + SwitchPreference headTrackingPref) { boolean isHeadTrackingAvailable = - isSpatialAudioOn && mSpatializer.hasHeadTracker(mAudioDevice); + spatialAudioPref.isChecked() && mSpatializer.hasHeadTracker(mAudioDevice); Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice)); headTrackingPref.setVisible(isHeadTrackingAvailable); if (isHeadTrackingAvailable) { @@ -158,14 +189,6 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont } private void getAvailableDevice() { - if (mSpatializer.getImmersiveAudioLevel() == SPATIALIZER_IMMERSIVE_LEVEL_NONE) { - mIsAvailable = false; - mAudioDevice = null; - Log.d(TAG, "getAvailableDevice() ignored: spatializer not supported"); - - return; - } - AudioDeviceAttributes a2dpDevice = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, @@ -187,7 +210,6 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont AudioDeviceInfo.TYPE_HEARING_AID, mCachedDevice.getAddress()); - mIsAvailable = true; if (mSpatializer.isAvailableForDevice(bleHeadsetDevice)) { mAudioDevice = bleHeadsetDevice; } else if (mSpatializer.isAvailableForDevice(bleSpeakerDevice)) { @@ -196,20 +218,20 @@ public class BluetoothDetailsSpatialAudioController extends BluetoothDetailsCont mAudioDevice = bleBroadcastDevice; } else if (mSpatializer.isAvailableForDevice(a2dpDevice)) { mAudioDevice = a2dpDevice; - } else { - mIsAvailable = mSpatializer.isAvailableForDevice(hearingAidDevice); + } else if (mSpatializer.isAvailableForDevice(hearingAidDevice)) { mAudioDevice = hearingAidDevice; + } else { + mAudioDevice = null; } Log.d(TAG, "getAvailableDevice() device : " + mCachedDevice.getDevice().getAnonymizedAddress() - + ", type : " + mAudioDevice.getType() - + ", is available : " + mIsAvailable); + + ", is available : " + (mAudioDevice != null) + + ", type : " + (mAudioDevice == null ? "no type" : mAudioDevice.getType())); } @VisibleForTesting void setAvailableDevice(AudioDeviceAttributes audioDevice) { mAudioDevice = audioDevice; - mIsAvailable = mSpatializer.isAvailableForDevice(audioDevice); } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java index 1f0adcfca80..ce5631fd028 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java @@ -16,6 +16,9 @@ package com.android.settings.bluetooth; +import static android.media.Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL; +import static android.media.Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; @@ -62,6 +65,8 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Mock private BluetoothDevice mBluetoothDevice; + private AudioDeviceAttributes mAvailableDevice; + private BluetoothDetailsSpatialAudioController mController; private SwitchPreference mSpatialAudioPref; private SwitchPreference mHeadTrackingPref; @@ -86,94 +91,32 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails when(mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO)).thenReturn(mSpatialAudioPref); when(mProfilesContainer.findPreference(KEY_HEAD_TRACKING)).thenReturn(mHeadTrackingPref); - } - @Test - public void isAvailable_spatialAudioSupportA2dpDevice_returnsTrue() { - AudioDeviceAttributes a2dpDevice = new AudioDeviceAttributes( + mAvailableDevice = new AudioDeviceAttributes( AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, MAC_ADDRESS); - when(mSpatializer.isAvailableForDevice(a2dpDevice)).thenReturn(true); - - mController.setAvailableDevice(a2dpDevice); - - assertThat(mController.isAvailable()).isTrue(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP); } @Test - public void isAvailable_spatialAudioSupportBleHeadsetDevice_returnsTrue() { - AudioDeviceAttributes bleHeadsetDevice = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_HEADSET, - MAC_ADDRESS); - when(mSpatializer.isAvailableForDevice(bleHeadsetDevice)).thenReturn(true); - - mController.setAvailableDevice(bleHeadsetDevice); - - assertThat(mController.isAvailable()).isTrue(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_BLE_HEADSET); - } - - @Test - public void isAvailable_spatialAudioSupportBleSpeakerDevice_returnsTrue() { - AudioDeviceAttributes bleSpeakerDevice = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_SPEAKER, - MAC_ADDRESS); - when(mSpatializer.isAvailableForDevice(bleSpeakerDevice)).thenReturn(true); - - mController.setAvailableDevice(bleSpeakerDevice); - - assertThat(mController.isAvailable()).isTrue(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_BLE_SPEAKER); - } - - @Test - public void isAvailable_spatialAudioSupportBleBroadcastDevice_returnsTrue() { - AudioDeviceAttributes bleBroadcastDevice = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_BLE_BROADCAST, - MAC_ADDRESS); - when(mSpatializer.isAvailableForDevice(bleBroadcastDevice)).thenReturn(true); - - mController.setAvailableDevice(bleBroadcastDevice); - - assertThat(mController.isAvailable()).isTrue(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_BLE_BROADCAST); - } - - @Test - public void isAvailable_spatialAudioSupportHearingAidDevice_returnsTrue() { - AudioDeviceAttributes hearingAidDevice = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, - AudioDeviceInfo.TYPE_HEARING_AID, - MAC_ADDRESS); - when(mSpatializer.isAvailableForDevice(hearingAidDevice)).thenReturn(true); - - mController.setAvailableDevice(hearingAidDevice); - - assertThat(mController.isAvailable()).isTrue(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID); - } - - @Test - public void isAvailable_spatialAudioNotSupported_returnsFalse() { + public void isAvailable_forSpatializerWithLevelNone_returnsFalse() { + when(mSpatializer.getImmersiveAudioLevel()).thenReturn(SPATIALIZER_IMMERSIVE_LEVEL_NONE); assertThat(mController.isAvailable()).isFalse(); - assertThat(mController.mAudioDevice.getType()) - .isEqualTo(AudioDeviceInfo.TYPE_HEARING_AID); + } + + @Test + public void isAvailable_forSpatializerWithLevelNotNone_returnsTrue() { + when(mSpatializer.getImmersiveAudioLevel()).thenReturn( + SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL); + assertThat(mController.isAvailable()).isTrue(); } @Test public void refresh_spatialAudioIsTurnedOn_checksSpatialAudioPreference() { List compatibleAudioDevices = new ArrayList<>(); + mController.setAvailableDevice(mAvailableDevice); compatibleAudioDevices.add(mController.mAudioDevice); + when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true); when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); mController.refresh(); @@ -207,13 +150,14 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails public void refresh_spatialAudioOnAndHeadTrackingIsNotAvailable_hidesHeadTrackingPreference() { List compatibleAudioDevices = new ArrayList<>(); + mController.setAvailableDevice(mAvailableDevice); compatibleAudioDevices.add(mController.mAudioDevice); when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false); mController.refresh(); - assertThat(mHeadTrackingPref.isVisible()).isFalse(); + verify(mProfilesContainer).removePreference(mHeadTrackingPref); } @Test @@ -223,14 +167,16 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails mController.refresh(); - assertThat(mHeadTrackingPref.isVisible()).isFalse(); + verify(mProfilesContainer).removePreference(mHeadTrackingPref); } @Test public void refresh_headTrackingIsTurnedOn_checksHeadTrackingPreference() { List compatibleAudioDevices = new ArrayList<>(); + mController.setAvailableDevice(mAvailableDevice); compatibleAudioDevices.add(mController.mAudioDevice); when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true); when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true); when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true); @@ -242,8 +188,10 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Test public void refresh_headTrackingIsTurnedOff_unchecksHeadTrackingPreference() { List compatibleAudioDevices = new ArrayList<>(); + mController.setAvailableDevice(mAvailableDevice); compatibleAudioDevices.add(mController.mAudioDevice); when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices); + when(mSpatializer.isAvailableForDevice(mController.mAudioDevice)).thenReturn(true); when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true); when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false); @@ -254,6 +202,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Test public void turnedOnSpatialAudio_invokesAddCompatibleAudioDevice() { + mController.setAvailableDevice(mAvailableDevice); mSpatialAudioPref.setChecked(true); mController.onPreferenceClick(mSpatialAudioPref); verify(mSpatializer).addCompatibleAudioDevice(mController.mAudioDevice); @@ -261,6 +210,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Test public void turnedOffSpatialAudio_invokesRemoveCompatibleAudioDevice() { + mController.setAvailableDevice(mAvailableDevice); mSpatialAudioPref.setChecked(false); mController.onPreferenceClick(mSpatialAudioPref); verify(mSpatializer).removeCompatibleAudioDevice(mController.mAudioDevice); @@ -268,6 +218,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Test public void turnedOnHeadTracking_invokesSetHeadTrackerEnabled_setsTrue() { + mController.setAvailableDevice(mAvailableDevice); mHeadTrackingPref.setChecked(true); mController.onPreferenceClick(mHeadTrackingPref); verify(mSpatializer).setHeadTrackerEnabled(true, mController.mAudioDevice); @@ -275,6 +226,7 @@ public class BluetoothDetailsSpatialAudioControllerTest extends BluetoothDetails @Test public void turnedOffHeadTracking_invokesSetHeadTrackerEnabled_setsFalse() { + mController.setAvailableDevice(mAvailableDevice); mHeadTrackingPref.setChecked(false); mController.onPreferenceClick(mHeadTrackingPref); verify(mSpatializer).setHeadTrackerEnabled(false, mController.mAudioDevice);