Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19f5db7f authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioDeviceInventory: fix Spatial Audio for LE broadcast.

LE broadcast devices are virtual devices that should not have their own
SA state. Also head tracking does not make sense in a broadcast situation.

The SA state for a broadcast device is now derived from the SA state of
the corresponding unicast device except for HT which is always disabled.
The state is not persisted and cannot be changed by Spatializer APIs.

Bug: 380151062
Test: make
Flag: EXEMPT bug fix.
Change-Id: I6aeee91993d1755b100d01919383e33aa009cd9d
parent c933c6ad
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1155,6 +1155,8 @@ public class AudioSystem
    public static final Set<Integer> DEVICE_OUT_ALL_BLE_SET;
    /** @hide */
    public static final Set<Integer> DEVICE_OUT_PICK_FOR_VOLUME_SET;
    /** @hide */
    public static final Set<Integer> DEVICE_OUT_ALL_BLE_UNICAST_SET;

    static {
        DEVICE_OUT_ALL_SET = new HashSet<>();
@@ -1224,6 +1226,10 @@ public class AudioSystem
        DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER);
        DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_BROADCAST);

        DEVICE_OUT_ALL_BLE_UNICAST_SET = new HashSet<>();
        DEVICE_OUT_ALL_BLE_UNICAST_SET.add(DEVICE_OUT_BLE_HEADSET);
        DEVICE_OUT_ALL_BLE_UNICAST_SET.add(DEVICE_OUT_BLE_SPEAKER);

        DEVICE_OUT_PICK_FOR_VOLUME_SET = new HashSet<>();
        DEVICE_OUT_PICK_FOR_VOLUME_SET.add(DEVICE_OUT_WIRED_HEADSET);
        DEVICE_OUT_PICK_FOR_VOLUME_SET.add(DEVICE_OUT_WIRED_HEADPHONE);
@@ -1435,6 +1441,11 @@ public class AudioSystem
                || isBluetoothLeInDevice(deviceType);
    }

    /** @hide */
    public static boolean isBluetoothLeOutUnicastDevice(int deviceType) {
        return DEVICE_OUT_ALL_BLE_UNICAST_SET.contains(deviceType);
    }

    /** @hide */
    public static boolean isRemoteSubmixDevice(int deviceType) {
        return deviceType == DEVICE_IN_REMOTE_SUBMIX || deviceType == DEVICE_OUT_REMOTE_SUBMIX;
+4 −4
Original line number Diff line number Diff line
@@ -1832,12 +1832,12 @@ public class AudioDeviceBroker {
        return mBluetoothA2dpEnabled.get();
    }

    /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device) {
        return mBtHelper.getLeAudioDeviceGroupId(device);
    /*package*/ int getLeAudioDeviceGroupId(BluetoothDevice device, int profile) {
        return mBtHelper.getLeAudioDeviceGroupId(device, profile);
    }

    /*package*/ List<Pair<String, String>> getLeAudioGroupAddresses(int groupId) {
        return mBtHelper.getLeAudioGroupAddresses(groupId);
    /*package*/ List<Pair<String, String>> getLeAudioGroupAddresses(int groupId, int profile) {
        return mBtHelper.getLeAudioGroupAddresses(groupId, profile);
    }

    /*package*/ void broadcastStickyIntentToCurrentProfileGroup(Intent intent) {
+63 −25
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
import static android.media.AudioSystem.isBluetoothA2dpOutDevice;
import static android.media.AudioSystem.isBluetoothDevice;
import static android.media.AudioSystem.isBluetoothLeOutDevice;
import static android.media.AudioSystem.isBluetoothLeOutUnicastDevice;
import static android.media.AudioSystem.isBluetoothOutDevice;
import static android.media.AudioSystem.isBluetoothScoOutDevice;

@@ -169,7 +170,8 @@ public class AudioDeviceInventory {
        }
        synchronized (mDeviceInventoryLock) {
            AdiDeviceState ads = findBtDeviceStateForAddress(address, deviceType);
            if (ads == null && peerAddress != null) {
            if (ads == null && peerAddress != null
                    && deviceType != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
                ads = findBtDeviceStateForAddress(peerAddress, deviceType);
            }
            if (ads != null) {
@@ -177,7 +179,8 @@ public class AudioDeviceInventory {
                // do not reset the category back to unknown since it might have been set
                // before by the user
                if (ads.getAudioDeviceCategory() != category && (userDefined
                        || category != AUDIO_DEVICE_CATEGORY_UNKNOWN)) {
                        || category != AUDIO_DEVICE_CATEGORY_UNKNOWN)
                        && deviceType != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
                    ads.setAudioDeviceCategory(category);
                    mDeviceBroker.postUpdatedAdiDeviceState(ads, false /*initSA*/);
                    mDeviceBroker.postPersistAudioDeviceSettings();
@@ -192,8 +195,12 @@ public class AudioDeviceInventory {
            mDeviceInventory.put(ads.getDeviceId(), ads);
            checkDeviceInventorySize_l();

            if (deviceType != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
                mDeviceBroker.postUpdatedAdiDeviceState(ads, true /*initSA*/);
                mDeviceBroker.postPersistAudioDeviceSettings();
            } else {
                mDeviceBroker.postSynchronizeAdiDevicesInInventory(ads);
            }
        }
    }

@@ -204,6 +211,9 @@ public class AudioDeviceInventory {
     */
    void addOrUpdateAudioDeviceCategoryInInventory(
            AdiDeviceState deviceState, boolean syncInventory) {
        if (deviceState.getInternalDeviceType() == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
            return;
        }
        AtomicBoolean updatedCategory = new AtomicBoolean(false);
        synchronized (mDeviceInventoryLock) {
            if (deviceState.updateAudioDeviceCategory()) {
@@ -330,6 +340,27 @@ public class AudioDeviceInventory {
                continue;
            }
            if (di.mDeviceAddress.equals(updatedDevice.getDeviceAddress())) {
                if (di.mDeviceType == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
                    for (AdiDeviceState ads2 : mDeviceInventory.values()) {
                        if (!(isBluetoothLeOutUnicastDevice(ads2.getInternalDeviceType())
                            && di.mPeerDeviceAddress.equals(ads2.getDeviceAddress()))) {
                            continue;
                        }
                        if (mDeviceBroker.isSADevice(updatedDevice)
                            == mDeviceBroker.isSADevice(ads2)) {
                            updatedDevice.setHasHeadTracker(false);
                            updatedDevice.setHeadTrackerEnabled(false);
                            updatedDevice.setSAEnabled(ads2.isSAEnabled());
                        }
                        updatedDevice.setAudioDeviceCategory(ads2.getAudioDeviceCategory());

                        mDeviceBroker.postUpdatedAdiDeviceState(updatedDevice, false /*initSA*/);
                        AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                                "synchronizeBleDeviceInInventory synced broadcast device ="
                                    + updatedDevice + " with ads =" + ads2).printLog(TAG));
                        return true;
                    }
                } else {
                    for (AdiDeviceState ads2 : mDeviceInventory.values()) {
                        if (!(di.mDeviceType == ads2.getInternalDeviceType()
                                && di.mPeerDeviceAddress.equals(ads2.getDeviceAddress()))) {
@@ -350,7 +381,9 @@ public class AudioDeviceInventory {
                        return true;
                    }
                }
            if (di.mPeerDeviceAddress.equals(updatedDevice.getDeviceAddress())) {
            }
            if (di.mDeviceType != AudioSystem.DEVICE_OUT_BLE_BROADCAST
                    && di.mPeerDeviceAddress.equals(updatedDevice.getDeviceAddress())) {
                for (AdiDeviceState ads2 : mDeviceInventory.values()) {
                    if (!(di.mDeviceType == ads2.getInternalDeviceType()
                            && di.mDeviceAddress.equals(ads2.getDeviceAddress()))) {
@@ -377,6 +410,9 @@ public class AudioDeviceInventory {

    @GuardedBy("mDeviceInventoryLock")
    private boolean synchronizeDeviceProfilesInInventory(AdiDeviceState updatedDevice) {
        if (updatedDevice.getInternalDeviceType() == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
            return false;
        }
        for (AdiDeviceState ads : mDeviceInventory.values()) {
            if (updatedDevice.getInternalDeviceType() == ads.getInternalDeviceType()
                    || !updatedDevice.getDeviceAddress().equals(ads.getDeviceAddress())) {
@@ -1148,7 +1184,8 @@ public class AudioDeviceInventory {
            for (DeviceInfo di : mConnectedDevices.values()) {
                if (di.mGroupId == groupId) {
                    if (addresses.isEmpty()) {
                        addresses = mDeviceBroker.getLeAudioGroupAddresses(groupId);
                        addresses = mDeviceBroker.getLeAudioGroupAddresses(
                                groupId, BluetoothProfile.LE_AUDIO);
                    }
                    if (di.mPeerDeviceAddress.equals("")) {
                        for (Pair<String, String> addr : addresses) {
@@ -2678,13 +2715,14 @@ public class AudioDeviceInventory {
            String name = BtHelper.getName(btInfo.mDevice);

            // Find LE Group ID and peer headset address if available
            final int groupId = mDeviceBroker.getLeAudioDeviceGroupId(btInfo.mDevice);
            final int groupId =
                    mDeviceBroker.getLeAudioDeviceGroupId(btInfo.mDevice, btInfo.mProfile);
            String peerAddress = "";
            String peerIdentityAddress = "";
            if (groupId != BluetoothLeAudio.GROUP_ID_INVALID) {
                List<Pair<String, String>> addresses =
                        mDeviceBroker.getLeAudioGroupAddresses(groupId);
                if (addresses.size() > 1) {
                        mDeviceBroker.getLeAudioGroupAddresses(groupId, btInfo.mProfile);
                if (addresses.size() >= 1) {
                    for (Pair<String, String> addr : addresses) {
                        if (!addr.first.equals(address)) {
                            peerAddress = addr.first;
@@ -2725,7 +2763,6 @@ public class AudioDeviceInventory {
            }
            // Reset LEA suspend state each time a new sink is connected
            mDeviceBroker.clearLeAudioSuspended(true /* internalOnly */);

            if (btInfo.mIsLeOutput) {
                mDeviceBroker.postAccessoryPlugMediaUnmute(device);
                setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
@@ -3164,7 +3201,8 @@ public class AudioDeviceInventory {
            AdiDeviceState devState = AdiDeviceState.fromPersistedString(setting);
            // Note if the device is not compatible with spatialization mode or the device
            // type is not canonical, it will be ignored in {@link SpatializerHelper}.
            if (devState != null) {
            if (devState != null
                    && devState.getInternalDeviceType() != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
                addOrUpdateDeviceSAStateInInventory(devState, false /*syncInventory*/);
                addOrUpdateAudioDeviceCategoryInInventory(devState, false /*syncInventory*/);
            }
+19 −6
Original line number Diff line number Diff line
@@ -1234,11 +1234,15 @@ public class BtHelper {
        return result;
    }

    /*package*/ synchronized int getLeAudioDeviceGroupId(BluetoothDevice device) {
    /*package*/ synchronized int getLeAudioDeviceGroupId(BluetoothDevice device, int profile) {
        if (mLeAudio == null || device == null) {
            return BluetoothLeAudio.GROUP_ID_INVALID;
        }
        if (profile == BluetoothProfile.LE_AUDIO) {
            return mLeAudio.getGroupId(device);
        } else {
            return mLeAudio.getBroadcastToUnicastFallbackGroup();
        }
    }

    /**
@@ -1247,18 +1251,27 @@ public class BtHelper {
     * @return A List of Pair(String main_address, String identity_address). Note that the
     * addresses returned by BluetoothDevice can be null.
     */
    /*package*/ synchronized List<Pair<String, String>> getLeAudioGroupAddresses(int groupId) {
    /*package*/ synchronized List<Pair<String, String>> getLeAudioGroupAddresses(
                int groupId, int profile) {
        List<Pair<String, String>> addresses = new ArrayList<>();
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        if (adapter == null || mLeAudio == null) {
            return addresses;
        }
        List<BluetoothDevice> activeDevices = adapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
        if (profile == BluetoothProfile.LE_AUDIO) {
            List<BluetoothDevice> activeDevices = adapter.getActiveDevices(
                    BluetoothProfile.LE_AUDIO);
            for (BluetoothDevice device : activeDevices) {
                if (device != null && mLeAudio.getGroupId(device) == groupId) {
                    addresses.add(new Pair(device.getAddress(), device.getIdentityAddress()));
                }
            }
        } else {
            BluetoothDevice device = mLeAudio.getConnectedGroupLeadDevice(groupId);
            if (device != null) {
                addresses.add(new Pair(device.getAddress(), device.getIdentityAddress()));
            }
        }
        return addresses;
    }

+9 −0
Original line number Diff line number Diff line
@@ -547,6 +547,9 @@ public class SpatializerHelper {
        if (!isDeviceCompatibleWithSpatializationModes(ada)) {
            return;
        }
        if (ada.getInternalType() == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
            return;
        }
        loglogi("addCompatibleAudioDevice: dev=" + ada);
        final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
        AdiDeviceState updatedDevice = null; // non-null on update.
@@ -619,6 +622,9 @@ public class SpatializerHelper {
    }

    synchronized void removeCompatibleAudioDevice(@NonNull AudioDeviceAttributes ada) {
        if (ada.getInternalType() == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
            return;
        }
        loglogi("removeCompatibleAudioDevice: dev=" + ada);

        final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
@@ -1275,6 +1281,9 @@ public class SpatializerHelper {
            Log.v(TAG, "no headtracking support, setHasHeadTracker always false for " + ada);
            return false;
        }
        if (ada.getInternalType() == AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
            return false;
        }
        final AdiDeviceState deviceState = findSACompatibleDeviceStateForAudioDeviceAttributes(ada);
        if (deviceState != null) {
            if (!deviceState.hasHeadTracker()) {