SpatializerHelper: fix Settings UI when transaural is not supported

Fix two problems:
1) It was possible to add a device to the list of compatible devices
even if the type was not compatible with the supported spatialization
modes.
2) Fix the logic conditions on wireless category when checking if a
SADeviceState matches a given AudioDeviceAttributes.

Bug: 237080475
Test: check Spatial Audio settings UI
Merged-In: I1747875efb7400b1be503431d2697daff8894306
Change-Id: I1747875efb7400b1be503431d2697daff8894306
This commit is contained in:
Eric Laurent 2022-06-24 17:34:57 +02:00 committed by Andy Hung
parent 2e933599ed
commit c5b2da71dd

View File

@ -280,18 +280,13 @@ public class SpatializerHelper {
} }
// for both transaural / binaural, we are not forcing enablement as the init() method // for both transaural / binaural, we are not forcing enablement as the init() method
// could have been called another time after boot in case of audioserver restart // could have been called another time after boot in case of audioserver restart
if (mTransauralSupported) { addCompatibleAudioDevice(
// not force-enabling as this device might already be in the device list new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""),
addCompatibleAudioDevice( false /*forceEnable*/);
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, ""), // not force-enabling as this device might already be in the device list
false /*forceEnable*/); addCompatibleAudioDevice(
} new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, ""),
if (mBinauralSupported) { false /*forceEnable*/);
// not force-enabling as this device might already be in the device list
addCompatibleAudioDevice(
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, ""),
false /*forceEnable*/);
}
} catch (RemoteException e) { } catch (RemoteException e) {
resetCapabilities(); resetCapabilities();
} finally { } finally {
@ -497,10 +492,9 @@ public class SpatializerHelper {
synchronized @NonNull List<AudioDeviceAttributes> getCompatibleAudioDevices() { synchronized @NonNull List<AudioDeviceAttributes> getCompatibleAudioDevices() {
// build unionOf(mCompatibleAudioDevices, mEnabledDevice) - mDisabledAudioDevices // build unionOf(mCompatibleAudioDevices, mEnabledDevice) - mDisabledAudioDevices
ArrayList<AudioDeviceAttributes> compatList = new ArrayList<>(); ArrayList<AudioDeviceAttributes> compatList = new ArrayList<>();
for (SADeviceState dev : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (dev.mEnabled) { if (deviceState.mEnabled) {
compatList.add(new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT, compatList.add(deviceState.getAudioDeviceAttributes());
dev.mDeviceType, dev.mDeviceAddress == null ? "" : dev.mDeviceAddress));
} }
} }
return compatList; return compatList;
@ -521,15 +515,15 @@ public class SpatializerHelper {
*/ */
private void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada, private void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada,
boolean forceEnable) { boolean forceEnable) {
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
return;
}
loglogi("addCompatibleAudioDevice: dev=" + ada); loglogi("addCompatibleAudioDevice: dev=" + ada);
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
boolean isInList = false; boolean isInList = false;
SADeviceState deviceUpdated = null; // non-null on update. SADeviceState deviceUpdated = null; // non-null on update.
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (!wireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
isInList = true; isInList = true;
if (forceEnable) { if (forceEnable) {
deviceState.mEnabled = true; deviceState.mEnabled = true;
@ -539,11 +533,10 @@ public class SpatializerHelper {
} }
} }
if (!isInList) { if (!isInList) {
final SADeviceState dev = new SADeviceState(deviceType, final SADeviceState deviceState = new SADeviceState(ada.getType(), ada.getAddress());
wireless ? ada.getAddress() : ""); deviceState.mEnabled = true;
dev.mEnabled = true; mSADevices.add(deviceState);
mSADevices.add(dev); deviceUpdated = deviceState;
deviceUpdated = dev;
} }
if (deviceUpdated != null) { if (deviceUpdated != null) {
onRoutingUpdated(); onRoutingUpdated();
@ -574,13 +567,10 @@ public class SpatializerHelper {
synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) { synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
loglogi("removeCompatibleAudioDevice: dev=" + ada); loglogi("removeCompatibleAudioDevice: dev=" + ada);
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
SADeviceState deviceUpdated = null; // non-null on update. SADeviceState deviceUpdated = null; // non-null on update.
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (!wireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
deviceState.mEnabled = false; deviceState.mEnabled = false;
deviceUpdated = deviceState; deviceUpdated = deviceState;
break; break;
@ -602,10 +592,9 @@ public class SpatializerHelper {
// if not a wireless device, this value will be overwritten to map the type // if not a wireless device, this value will be overwritten to map the type
// to TYPE_BUILTIN_SPEAKER or TYPE_WIRED_HEADPHONES // to TYPE_BUILTIN_SPEAKER or TYPE_WIRED_HEADPHONES
@AudioDeviceInfo.AudioDeviceType int deviceType = ada.getType(); @AudioDeviceInfo.AudioDeviceType int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
// if not a wireless device: find if media device is in the speaker, wired headphones // if not a wireless device: find if media device is in the speaker, wired headphones
if (!wireless) { if (!isWireless(deviceType)) {
// is the device type capable of doing SA? // is the device type capable of doing SA?
if (!mSACapableDeviceTypes.contains(deviceType)) { if (!mSACapableDeviceTypes.contains(deviceType)) {
Log.i(TAG, "Device incompatible with Spatial Audio dev:" + ada); Log.i(TAG, "Device incompatible with Spatial Audio dev:" + ada);
@ -640,9 +629,7 @@ public class SpatializerHelper {
boolean enabled = false; boolean enabled = false;
boolean available = false; boolean available = false;
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
available = true; available = true;
enabled = deviceState.mEnabled; enabled = deviceState.mEnabled;
break; break;
@ -652,11 +639,12 @@ public class SpatializerHelper {
} }
private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) { private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) {
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
return;
}
boolean knownDevice = false; boolean knownDevice = false;
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
// wireless device so always check address if (deviceState.matchesAudioDeviceAttributes(ada)) {
if (ada.getType() == deviceState.mDeviceType
&& ada.getAddress().equals(deviceState.mDeviceAddress)) {
knownDevice = true; knownDevice = true;
break; break;
} }
@ -704,13 +692,8 @@ public class SpatializerHelper {
if (ada.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) { if (ada.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
return false; return false;
} }
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
return true; return true;
} }
} }
@ -719,12 +702,19 @@ public class SpatializerHelper {
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes, private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
@NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) { @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) {
final byte modeForDevice = (byte) SPAT_MODE_FOR_DEVICE_TYPE.get(devices[0].getType(), if (isDeviceCompatibleWithSpatializationModes(devices[0])) {
return AudioSystem.canBeSpatialized(attributes, format, devices);
}
return false;
}
private boolean isDeviceCompatibleWithSpatializationModes(@NonNull AudioDeviceAttributes ada) {
final byte modeForDevice = (byte) SPAT_MODE_FOR_DEVICE_TYPE.get(ada.getType(),
/*default when type not found*/ SpatializationMode.SPATIALIZER_BINAURAL); /*default when type not found*/ SpatializationMode.SPATIALIZER_BINAURAL);
if ((modeForDevice == SpatializationMode.SPATIALIZER_BINAURAL && mBinauralSupported) if ((modeForDevice == SpatializationMode.SPATIALIZER_BINAURAL && mBinauralSupported)
|| (modeForDevice == SpatializationMode.SPATIALIZER_TRANSAURAL || (modeForDevice == SpatializationMode.SPATIALIZER_TRANSAURAL
&& mTransauralSupported)) { && mTransauralSupported)) {
return AudioSystem.canBeSpatialized(attributes, format, devices); return true;
} }
return false; return false;
} }
@ -1089,13 +1079,8 @@ public class SpatializerHelper {
Log.v(TAG, "no headtracking support, ignoring setHeadTrackerEnabled to " + enabled Log.v(TAG, "no headtracking support, ignoring setHeadTrackerEnabled to " + enabled
+ " for " + ada); + " for " + ada);
} }
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
if (!deviceState.mHasHeadTracker) { if (!deviceState.mHasHeadTracker) {
Log.e(TAG, "Called setHeadTrackerEnabled enabled:" + enabled Log.e(TAG, "Called setHeadTrackerEnabled enabled:" + enabled
+ " device:" + ada + " on a device without headtracker"); + " device:" + ada + " on a device without headtracker");
@ -1109,7 +1094,7 @@ public class SpatializerHelper {
} }
} }
// check current routing to see if it affects the headtracking mode // check current routing to see if it affects the headtracking mode
if (ROUTING_DEVICES[0].getType() == deviceType if (ROUTING_DEVICES[0].getType() == ada.getType()
&& ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) { && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled
: Spatializer.HEAD_TRACKING_MODE_DISABLED); : Spatializer.HEAD_TRACKING_MODE_DISABLED);
@ -1121,13 +1106,8 @@ public class SpatializerHelper {
Log.v(TAG, "no headtracking support, hasHeadTracker always false for " + ada); Log.v(TAG, "no headtracking support, hasHeadTracker always false for " + ada);
return false; return false;
} }
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
return deviceState.mHasHeadTracker; return deviceState.mHasHeadTracker;
} }
} }
@ -1144,13 +1124,8 @@ public class SpatializerHelper {
Log.v(TAG, "no headtracking support, setHasHeadTracker always false for " + ada); Log.v(TAG, "no headtracking support, setHasHeadTracker always false for " + ada);
return false; return false;
} }
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
if (!deviceState.mHasHeadTracker) { if (!deviceState.mHasHeadTracker) {
deviceState.mHasHeadTracker = true; deviceState.mHasHeadTracker = true;
mAudioService.persistSpatialAudioDeviceSettings(); mAudioService.persistSpatialAudioDeviceSettings();
@ -1168,13 +1143,8 @@ public class SpatializerHelper {
Log.v(TAG, "no headtracking support, isHeadTrackerEnabled always false for " + ada); Log.v(TAG, "no headtracking support, isHeadTrackerEnabled always false for " + ada);
return false; return false;
} }
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
for (SADeviceState deviceState : mSADevices) { for (SADeviceState deviceState : mSADevices) {
if (deviceType == deviceState.mDeviceType if (deviceState.matchesAudioDeviceAttributes(ada)) {
&& (wireless && ada.getAddress().equals(deviceState.mDeviceAddress))
|| !wireless) {
if (!deviceState.mHasHeadTracker) { if (!deviceState.mHasHeadTracker) {
return false; return false;
} }
@ -1531,7 +1501,7 @@ public class SpatializerHelper {
SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @NonNull String address) { SADeviceState(@AudioDeviceInfo.AudioDeviceType int deviceType, @NonNull String address) {
mDeviceType = deviceType; mDeviceType = deviceType;
mDeviceAddress = Objects.requireNonNull(address); mDeviceAddress = isWireless(deviceType) ? Objects.requireNonNull(address) : "";
} }
@Override @Override
@ -1599,6 +1569,18 @@ public class SpatializerHelper {
return null; return null;
} }
} }
public AudioDeviceAttributes getAudioDeviceAttributes() {
return new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
mDeviceType, mDeviceAddress == null ? "" : mDeviceAddress);
}
public boolean matchesAudioDeviceAttributes(AudioDeviceAttributes ada) {
final int deviceType = ada.getType();
final boolean wireless = isWireless(deviceType);
return (deviceType == mDeviceType)
&& (!wireless || ada.getAddress().equals(mDeviceAddress));
}
} }
/*package*/ synchronized String getSADeviceSettings() { /*package*/ synchronized String getSADeviceSettings() {
@ -1619,7 +1601,9 @@ public class SpatializerHelper {
// small list, not worth overhead of Arrays.stream(devSettings) // small list, not worth overhead of Arrays.stream(devSettings)
for (String setting : devSettings) { for (String setting : devSettings) {
SADeviceState devState = SADeviceState.fromPersistedString(setting); SADeviceState devState = SADeviceState.fromPersistedString(setting);
if (devState != null) { if (devState != null
&& isDeviceCompatibleWithSpatializationModes(
devState.getAudioDeviceAttributes())) {
mSADevices.add(devState); mSADevices.add(devState);
logDeviceState(devState, "setSADeviceSettings"); logDeviceState(devState, "setSADeviceSettings");
} }