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

Commit b1cdc87b authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioService: more LE audio/Hearing Aid volume fixes

Remove redundant LE Audio and Hearing Aid volume handling methods.
Align LE Audio and Hearing Aid volume updates when audio mode changes
and communication device is selected.
Do not perform volume initialization steps when a LE audio input device
is connected as those are needed only for an output device.

Bug: 349007365
Bug: 349244832
Test: make
Flag: EXEMPT bug fix
Change-Id: Ib9580515b8a9831cf4132525520c845204787eed
parent 0db977b6
Loading
Loading
Loading
Loading
+4 −13
Original line number Diff line number Diff line
@@ -474,19 +474,10 @@ public class AudioDeviceBroker {
                mBtHelper.stopBluetoothSco(eventSource);
            }
        }
        // In BT classic for communication, the device changes from a2dp to sco device, but for
        // LE Audio it stays the same and we must trigger the proper stream volume alignment, if
        // LE Audio communication device is activated after the audio system has already switched to
        // MODE_IN_CALL mode.
        if (isBluetoothLeAudioRequested() && device != null) {
            final int streamType = mAudioService.getBluetoothContextualVolumeStream();
            final int leAudioVolIndex = getVssVolumeForDevice(streamType, device.getInternalType());
            final int leAudioMaxVolIndex = getMaxVssVolumeForStream(streamType);
            if (AudioService.DEBUG_COMM_RTE) {
                Log.v(TAG, "setCommunicationRouteForClient restoring LE Audio device volume lvl.");
            }
            postSetLeAudioVolumeIndex(leAudioVolIndex, leAudioMaxVolIndex, streamType);
        }
        // In BT classic for communication, the device changes from a2dp to sco device,
        // but for LE Audio or Hearing Aid it stays the same and we must trigger the proper
        // stream volume alignment.
        mAudioService.postUpdateContextualVolumes();

        updateCommunicationRoute(eventSource);
    }
+16 −12
Original line number Diff line number Diff line
@@ -2548,12 +2548,15 @@ public class AudioDeviceInventory {
                    new DeviceInfo(device, name, address,
                            btInfo.mDevice.getIdentityAddress(), codec,
                            groupId, peerAddress, peerIdentityAddress));
            if (btInfo.mIsLeOutput) {
                mDeviceBroker.postAccessoryPlugMediaUnmute(device);
                setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
            }
            addAudioDeviceInInventoryIfNeeded(device, address, peerAddress,
                    BtHelper.getBtDeviceCategory(address), /*userDefined=*/false);
        }

        if (btInfo.mIsLeOutput) {
            if (streamType == AudioSystem.STREAM_DEFAULT) {
                // No need to update volume for input devices
                return;
@@ -2565,6 +2568,7 @@ public class AudioDeviceInventory {
            final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
            mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
            mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
        }

        updateBluetoothPreferredModes_l(btInfo.mDevice /*connectedDevice*/);
    }
+38 −89
Original line number Diff line number Diff line
@@ -841,7 +841,9 @@ public class AudioService extends IAudioService.Stub
    // full scale, and volume control separately) and can be used for multiple use cases reflected
    // by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
    Set<Integer> mAbsVolumeMultiModeCaseDevices = new HashSet<>(
            Arrays.asList(AudioSystem.DEVICE_OUT_HEARING_AID));
            Arrays.asList(AudioSystem.DEVICE_OUT_HEARING_AID,
                          AudioSystem.DEVICE_OUT_BLE_HEADSET,
                          AudioSystem.DEVICE_OUT_BLE_SPEAKER));
    private final boolean mMonitorRotation;
@@ -3815,11 +3817,11 @@ public class AudioService extends IAudioService.Stub
                    mStreamStates[streamType].getMaxIndex(), streamType);
            }
            // Check if volume update should be send to Hearing Aid
            if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                // only modify the hearing aid attenuation when the stream to modify matches
                // the one expected by the hearing aid
                if (streamType == getBluetoothContextualVolumeStream()) {
            // Check if volume update should be send to Hearing Aid.
            // Only modify the hearing aid attenuation when the stream to modify matches
            // the one expected by the hearing aid.
            if (device == AudioSystem.DEVICE_OUT_HEARING_AID
                    && streamType == getBluetoothContextualVolumeStream()) {
                if (DEBUG_VOL) {
                    Log.d(TAG, "adjustStreamVolume postSetHearingAidVolumeIndex index="
                            + newIndex + " stream=" + streamType);
@@ -3827,7 +3829,6 @@ public class AudioService extends IAudioService.Stub
                mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
            }
        }
        }
        final int newIndex = mStreamStates[streamType].getIndex(device);
@@ -4631,93 +4632,43 @@ public class AudioService extends IAudioService.Stub
    private void onUpdateContextualVolumes() {
        final int streamType = getBluetoothContextualVolumeStream();
        final int device = getDeviceForStream(streamType);
        final int index = getStreamVolume(streamType, device);
        if (AudioSystem.isLeAudioDeviceType(device)) {
            mDeviceBroker.postSetLeAudioVolumeIndex(index * 10,
                    mStreamStates[streamType].getMaxIndex(), streamType);
        } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
            mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
        }
        sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_CONTEXTUAL_VOLUME,
                mVoicePlaybackActive.get(), streamType, index, device));
    }
    /**
     * Manage an audio mode change for audio devices that use an "absolute volume" model,
     * i.e. the framework sends the full scale signal, and the actual volume for the use case
     * is communicated separately.
     */
    void updateAbsVolumeMultiModeDevices(int oldMode, int newMode) {
        if (oldMode == newMode) {
            return;
        }
        switch (newMode) {
            case AudioSystem.MODE_IN_COMMUNICATION:
            case AudioSystem.MODE_IN_CALL:
            case AudioSystem.MODE_NORMAL:
            case AudioSystem.MODE_CALL_SCREENING:
            case AudioSystem.MODE_CALL_REDIRECT:
            case AudioSystem.MODE_COMMUNICATION_REDIRECT:
                break;
            default:
                // no-op is enough for all other values
                return;
        }
        int streamType = getBluetoothContextualVolumeStream(newMode);
        final Set<Integer> deviceTypes = getDeviceSetForStreamDirect(streamType);
        final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes(
        final Set<Integer> absVolumeMultiModeCaseDevices =
                AudioSystem.intersectionAudioDeviceTypes(
                        mAbsVolumeMultiModeCaseDevices, deviceTypes);
        if (absVolumeMultiModeCaseDevices.isEmpty()) {
            return;
        }
        // handling of specific interfaces goes here:
        if (AudioSystem.isSingleAudioDeviceType(
                absVolumeMultiModeCaseDevices, AudioSystem.DEVICE_OUT_HEARING_AID)) {
            final int index = getStreamVolume(streamType);
            sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_MODE_CHANGE_HEARING_AID,
                    newMode, streamType, index));
            mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
        }
        if (absVolumeMultiModeCaseDevices.size() > 1) {
            Log.w(TAG, "onUpdateContextualVolumes too many active devices: "
                    + absVolumeMultiModeCaseDevices.stream().map(AudioSystem::getOutputDeviceName)
                        .collect(Collectors.joining(","))
                    + ", for stream: " + streamType);
            return;
        }
    private void setLeAudioVolumeOnModeUpdate(int mode, int device, int streamType, int index,
            int maxIndex) {
        switch (mode) {
            case AudioSystem.MODE_IN_COMMUNICATION:
            case AudioSystem.MODE_IN_CALL:
            case AudioSystem.MODE_NORMAL:
            case AudioSystem.MODE_CALL_SCREENING:
            case AudioSystem.MODE_CALL_REDIRECT:
            case AudioSystem.MODE_COMMUNICATION_REDIRECT:
            case AudioSystem.MODE_RINGTONE:
                break;
            default:
                // no-op is enough for all other values
                return;
        final int device = absVolumeMultiModeCaseDevices.toArray(new Integer[0])[0].intValue();
        final int index = getStreamVolume(streamType, device);
        if (DEBUG_VOL) {
            Log.i(TAG, "onUpdateContextualVolumes streamType: " + streamType
                    + ", device: " + AudioSystem.getOutputDeviceName(device)
                    + ", index: " + index);
        }
        // In some cases (like the outgoing or rejected call) the value of 'device' is not
        // DEVICE_OUT_BLE_* even when BLE is connected. Changing the volume level in such case
        // may cuase the other devices volume level leaking into the LeAudio device settings.
        if (!AudioSystem.isLeAudioDeviceType(device)) {
            Log.w(TAG, "setLeAudioVolumeOnModeUpdate ignoring invalid device="
                    + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
                    + " streamType=" + streamType);
        if (AudioSystem.isLeAudioDeviceType(device)) {
            mDeviceBroker.postSetLeAudioVolumeIndex(index * 10,
                    mStreamStates[streamType].getMaxIndex(), streamType);
        } else if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
            mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
        } else {
            return;
        }
        if (DEBUG_VOL) {
            Log.d(TAG, "setLeAudioVolumeOnModeUpdate postSetLeAudioVolumeIndex device="
                    + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
                    + " streamType=" + streamType);
        }
        mDeviceBroker.postSetLeAudioVolumeIndex(index, maxIndex, streamType);
        mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "setLeAudioVolumeOnModeUpdate");
        sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_VOICE_ACTIVITY_CONTEXTUAL_VOLUME,
                mVoicePlaybackActive.get(), streamType, index, device));
    }
    private void setStreamVolume(int streamType, int index, int flags,
@@ -6254,9 +6205,7 @@ public class AudioService extends IAudioService.Stub
                updateStreamVolumeAlias(true /*updateVolumes*/, requesterPackage);
                // change of mode may require volume to be re-applied on some devices
                updateAbsVolumeMultiModeDevices(previousMode, mode);
                setLeAudioVolumeOnModeUpdate(mode, device, streamAlias, index, maxIndex);
                onUpdateContextualVolumes();
                synchronized (mCachedAbsVolDrivingStreamsLock) {
                    mCachedAbsVolDrivingStreams.replaceAll((absDev, stream) -> {