Merge "Spatializer: Fix usb headset" into tm-qpr-dev am: 77e1313118
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19374318 Change-Id: Ib7e183745e9b999e960ad55a23717a45bd0e4211 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -46,6 +46,8 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -103,10 +105,6 @@ public class SpatializerHelper {
|
|||||||
AudioDeviceInfo.TYPE_BLE_BROADCAST
|
AudioDeviceInfo.TYPE_BLE_BROADCAST
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int[] WIRELESS_SPEAKER_TYPES = {
|
|
||||||
AudioDeviceInfo.TYPE_BLE_SPEAKER,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spatializer state machine
|
// Spatializer state machine
|
||||||
private static final int STATE_UNINITIALIZED = 0;
|
private static final int STATE_UNINITIALIZED = 0;
|
||||||
private static final int STATE_NOT_SUPPORTED = 1;
|
private static final int STATE_NOT_SUPPORTED = 1;
|
||||||
@@ -166,6 +164,7 @@ public class SpatializerHelper {
|
|||||||
* List of devices where Spatial Audio is possible. Each device can be enabled or disabled
|
* List of devices where Spatial Audio is possible. Each device can be enabled or disabled
|
||||||
* (== user choice to use or not)
|
* (== user choice to use or not)
|
||||||
*/
|
*/
|
||||||
|
@GuardedBy("this")
|
||||||
private final ArrayList<SADeviceState> mSADevices = new ArrayList<>(0);
|
private final ArrayList<SADeviceState> mSADevices = new ArrayList<>(0);
|
||||||
|
|
||||||
//------------------------------------------------------
|
//------------------------------------------------------
|
||||||
@@ -520,30 +519,30 @@ public class SpatializerHelper {
|
|||||||
* set to true if the device is added to the list, otherwise, if already
|
* set to true if the device is added to the list, otherwise, if already
|
||||||
* present, the setting is left untouched.
|
* present, the setting is left untouched.
|
||||||
*/
|
*/
|
||||||
|
@GuardedBy("this")
|
||||||
private void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada,
|
private void addCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada,
|
||||||
boolean forceEnable) {
|
boolean forceEnable) {
|
||||||
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
|
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loglogi("addCompatibleAudioDevice: dev=" + ada);
|
loglogi("addCompatibleAudioDevice: dev=" + ada);
|
||||||
boolean isInList = false;
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
SADeviceState deviceUpdated = null; // non-null on update.
|
SADeviceState deviceUpdated = null; // non-null on update.
|
||||||
|
if (deviceState != null) {
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
if (forceEnable && !deviceState.mEnabled) {
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
|
||||||
isInList = true;
|
|
||||||
if (forceEnable) {
|
|
||||||
deviceState.mEnabled = true;
|
|
||||||
deviceUpdated = deviceState;
|
deviceUpdated = deviceState;
|
||||||
|
deviceUpdated.mEnabled = true;
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
// When adding, force the device type to be a canonical one.
|
||||||
|
final int canonicalDeviceType = getCanonicalDeviceType(ada.getType());
|
||||||
|
if (canonicalDeviceType == AudioDeviceInfo.TYPE_UNKNOWN) {
|
||||||
|
Log.e(TAG, "addCompatibleAudioDevice with incompatible AudioDeviceAttributes "
|
||||||
|
+ ada);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
deviceUpdated = new SADeviceState(canonicalDeviceType, ada.getAddress());
|
||||||
if (!isInList) {
|
mSADevices.add(deviceUpdated);
|
||||||
final SADeviceState deviceState = new SADeviceState(ada.getType(), ada.getAddress());
|
|
||||||
deviceState.mEnabled = true;
|
|
||||||
mSADevices.add(deviceState);
|
|
||||||
deviceUpdated = deviceState;
|
|
||||||
}
|
}
|
||||||
if (deviceUpdated != null) {
|
if (deviceUpdated != null) {
|
||||||
onRoutingUpdated();
|
onRoutingUpdated();
|
||||||
@@ -574,34 +573,59 @@ public class SpatializerHelper {
|
|||||||
|
|
||||||
synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
|
synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
|
||||||
loglogi("removeCompatibleAudioDevice: dev=" + ada);
|
loglogi("removeCompatibleAudioDevice: dev=" + ada);
|
||||||
SADeviceState deviceUpdated = null; // non-null on update.
|
|
||||||
|
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
if (deviceState != null && deviceState.mEnabled) {
|
||||||
deviceState.mEnabled = false;
|
deviceState.mEnabled = false;
|
||||||
deviceUpdated = deviceState;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deviceUpdated != null) {
|
|
||||||
onRoutingUpdated();
|
onRoutingUpdated();
|
||||||
mAudioService.persistSpatialAudioDeviceSettings();
|
mAudioService.persistSpatialAudioDeviceSettings();
|
||||||
logDeviceState(deviceUpdated, "removeCompatibleAudioDevice");
|
logDeviceState(deviceState, "removeCompatibleAudioDevice");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a possibly aliased device type which is used
|
||||||
|
* for spatial audio settings (or TYPE_UNKNOWN if it doesn't exist).
|
||||||
|
*/
|
||||||
|
private static @AudioDeviceInfo.AudioDeviceType int getCanonicalDeviceType(int deviceType) {
|
||||||
|
if (isWireless(deviceType)) return deviceType;
|
||||||
|
|
||||||
|
final int spatMode = SPAT_MODE_FOR_DEVICE_TYPE.get(deviceType, Integer.MIN_VALUE);
|
||||||
|
if (spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL) {
|
||||||
|
return AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
|
||||||
|
} else if (spatMode == SpatializationMode.SPATIALIZER_BINAURAL) {
|
||||||
|
return AudioDeviceInfo.TYPE_WIRED_HEADPHONES;
|
||||||
|
}
|
||||||
|
return AudioDeviceInfo.TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Spatial Audio device state for an audio device attributes
|
||||||
|
* or null if it does not exist.
|
||||||
|
*/
|
||||||
|
@GuardedBy("this")
|
||||||
|
@Nullable
|
||||||
|
private SADeviceState findDeviceStateForAudioDeviceAttributes(AudioDeviceAttributes ada) {
|
||||||
|
final int deviceType = ada.getType();
|
||||||
|
final boolean isWireless = isWireless(deviceType);
|
||||||
|
final int canonicalDeviceType = getCanonicalDeviceType(deviceType);
|
||||||
|
|
||||||
|
for (SADeviceState deviceState : mSADevices) {
|
||||||
|
if (deviceState.mDeviceType == canonicalDeviceType
|
||||||
|
&& (!isWireless || ada.getAddress().equals(deviceState.mDeviceAddress))) {
|
||||||
|
return deviceState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if Spatial Audio is enabled and available for the given device
|
* Return if Spatial Audio is enabled and available for the given device
|
||||||
* @param ada
|
* @param ada
|
||||||
* @return a pair of boolean, 1/ enabled? 2/ available?
|
* @return a pair of boolean, 1/ enabled? 2/ available?
|
||||||
*/
|
*/
|
||||||
private synchronized Pair<Boolean, Boolean> evaluateState(AudioDeviceAttributes ada) {
|
private synchronized Pair<Boolean, Boolean> evaluateState(AudioDeviceAttributes ada) {
|
||||||
// if not a wireless device, this value will be overwritten to map the type
|
final @AudioDeviceInfo.AudioDeviceType int deviceType = ada.getType();
|
||||||
// to TYPE_BUILTIN_SPEAKER or TYPE_WIRED_HEADPHONES
|
|
||||||
@AudioDeviceInfo.AudioDeviceType int deviceType = ada.getType();
|
|
||||||
|
|
||||||
// if not a wireless device: find if media device is in the speaker, wired headphones
|
|
||||||
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);
|
||||||
@@ -614,50 +638,30 @@ public class SpatializerHelper {
|
|||||||
Log.e(TAG, "no spatialization mode found for device type:" + deviceType);
|
Log.e(TAG, "no spatialization mode found for device type:" + deviceType);
|
||||||
return new Pair<>(false, false);
|
return new Pair<>(false, false);
|
||||||
}
|
}
|
||||||
// map the spatialization mode to the SPEAKER or HEADPHONES device
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (spatMode == SpatializationMode.SPATIALIZER_TRANSAURAL) {
|
if (deviceState == null) {
|
||||||
deviceType = AudioDeviceInfo.TYPE_BUILTIN_SPEAKER;
|
// no matching device state?
|
||||||
} else {
|
Log.i(TAG, "no spatialization device state found for Spatial Audio device:" + ada);
|
||||||
deviceType = AudioDeviceInfo.TYPE_WIRED_HEADPHONES;
|
|
||||||
}
|
|
||||||
} else { // wireless device
|
|
||||||
if (isWirelessSpeaker(deviceType) && !mTransauralSupported) {
|
|
||||||
Log.i(TAG, "Device incompatible with Spatial Audio (no transaural) dev:"
|
|
||||||
+ ada);
|
|
||||||
return new Pair<>(false, false);
|
return new Pair<>(false, false);
|
||||||
}
|
}
|
||||||
if (!mBinauralSupported) {
|
// found the matching device state.
|
||||||
Log.i(TAG, "Device incompatible with Spatial Audio (no binaural) dev:"
|
return new Pair<>(deviceState.mEnabled, true /* available */);
|
||||||
+ ada);
|
|
||||||
return new Pair<>(false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean enabled = false;
|
|
||||||
boolean available = false;
|
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
|
||||||
available = true;
|
|
||||||
enabled = deviceState.mEnabled;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Pair<>(enabled, available);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) {
|
private synchronized void addWirelessDeviceIfNew(@NonNull AudioDeviceAttributes ada) {
|
||||||
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
|
if (!isDeviceCompatibleWithSpatializationModes(ada)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean knownDevice = false;
|
if (findDeviceStateForAudioDeviceAttributes(ada) == null) {
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
// wireless device types should be canonical, but we translate to be sure.
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
final int canonicalDeviceType = getCanonicalDeviceType((ada.getType()));
|
||||||
knownDevice = true;
|
if (canonicalDeviceType == AudioDeviceInfo.TYPE_UNKNOWN) {
|
||||||
break;
|
Log.e(TAG, "addWirelessDeviceIfNew with incompatible AudioDeviceAttributes "
|
||||||
|
+ ada);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
final SADeviceState deviceState =
|
||||||
if (!knownDevice) {
|
new SADeviceState(canonicalDeviceType, ada.getAddress());
|
||||||
final SADeviceState deviceState = new SADeviceState(ada.getType(), ada.getAddress());
|
|
||||||
mSADevices.add(deviceState);
|
mSADevices.add(deviceState);
|
||||||
mAudioService.persistSpatialAudioDeviceSettings();
|
mAudioService.persistSpatialAudioDeviceSettings();
|
||||||
logDeviceState(deviceState, "addWirelessDeviceIfNew"); // may be updated later.
|
logDeviceState(deviceState, "addWirelessDeviceIfNew"); // may be updated later.
|
||||||
@@ -699,12 +703,7 @@ public class SpatializerHelper {
|
|||||||
if (ada.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
|
if (ada.getRole() != AudioDeviceAttributes.ROLE_OUTPUT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
return findDeviceStateForAudioDeviceAttributes(ada) != null;
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
|
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
|
||||||
@@ -1086,8 +1085,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);
|
||||||
}
|
}
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
if (deviceState == null) return;
|
||||||
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");
|
||||||
@@ -1097,9 +1096,7 @@ public class SpatializerHelper {
|
|||||||
deviceState.mHeadTrackerEnabled = enabled;
|
deviceState.mHeadTrackerEnabled = enabled;
|
||||||
mAudioService.persistSpatialAudioDeviceSettings();
|
mAudioService.persistSpatialAudioDeviceSettings();
|
||||||
logDeviceState(deviceState, "setHeadTrackerEnabled");
|
logDeviceState(deviceState, "setHeadTrackerEnabled");
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 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() == ada.getType()
|
if (ROUTING_DEVICES[0].getType() == ada.getType()
|
||||||
&& ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
|
&& ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
|
||||||
@@ -1113,12 +1110,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;
|
||||||
}
|
}
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
return deviceState != null && deviceState.mHasHeadTracker;
|
||||||
return deviceState.mHasHeadTracker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1131,8 +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;
|
||||||
}
|
}
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
if (deviceState != null) {
|
||||||
if (!deviceState.mHasHeadTracker) {
|
if (!deviceState.mHasHeadTracker) {
|
||||||
deviceState.mHasHeadTracker = true;
|
deviceState.mHasHeadTracker = true;
|
||||||
mAudioService.persistSpatialAudioDeviceSettings();
|
mAudioService.persistSpatialAudioDeviceSettings();
|
||||||
@@ -1140,7 +1133,6 @@ public class SpatializerHelper {
|
|||||||
}
|
}
|
||||||
return deviceState.mHeadTrackerEnabled;
|
return deviceState.mHeadTrackerEnabled;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Log.e(TAG, "setHasHeadTracker: device not found for:" + ada);
|
Log.e(TAG, "setHasHeadTracker: device not found for:" + ada);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1150,15 +1142,9 @@ 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;
|
||||||
}
|
}
|
||||||
for (SADeviceState deviceState : mSADevices) {
|
final SADeviceState deviceState = findDeviceStateForAudioDeviceAttributes(ada);
|
||||||
if (deviceState.matchesAudioDeviceAttributes(ada)) {
|
return deviceState != null
|
||||||
if (!deviceState.mHasHeadTracker) {
|
&& deviceState.mHasHeadTracker && deviceState.mHeadTrackerEnabled;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return deviceState.mHeadTrackerEnabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized boolean isHeadTrackerAvailable() {
|
synchronized boolean isHeadTrackerAvailable() {
|
||||||
@@ -1582,12 +1568,6 @@ public class SpatializerHelper {
|
|||||||
mDeviceType, mDeviceAddress == null ? "" : mDeviceAddress);
|
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() {
|
||||||
@@ -1608,7 +1588,10 @@ 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);
|
||||||
|
// Note if the device is not compatible with spatialization mode
|
||||||
|
// or the device type is not canonical, it is ignored.
|
||||||
if (devState != null
|
if (devState != null
|
||||||
|
&& devState.mDeviceType == getCanonicalDeviceType(devState.mDeviceType)
|
||||||
&& isDeviceCompatibleWithSpatializationModes(
|
&& isDeviceCompatibleWithSpatializationModes(
|
||||||
devState.getAudioDeviceAttributes())) {
|
devState.getAudioDeviceAttributes())) {
|
||||||
mSADevices.add(devState);
|
mSADevices.add(devState);
|
||||||
@@ -1645,15 +1628,6 @@ public class SpatializerHelper {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isWirelessSpeaker(@AudioDeviceInfo.AudioDeviceType int deviceType) {
|
|
||||||
for (int type : WIRELESS_SPEAKER_TYPES) {
|
|
||||||
if (type == deviceType) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getHeadSensorHandleUpdateTracker() {
|
private int getHeadSensorHandleUpdateTracker() {
|
||||||
int headHandle = -1;
|
int headHandle = -1;
|
||||||
UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(ROUTING_DEVICES[0]);
|
UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(ROUTING_DEVICES[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user