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

Commit afad75ae authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "AudioService: more LE audio/Hearing Aid volume fixes" into main

parents f00dda2e b1cdc87b
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) -> {