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

Commit 6c19bcc8 authored by Vlad Popa's avatar Vlad Popa Committed by Android (Google) Code Review
Browse files

Merge "Use AudioDeviceAttributes for managing volumes" into main

parents 79c980b4 2481379b
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -331,6 +331,20 @@ public final class AudioDeviceAttributes implements Parcelable {
                + " descriptors:" + mAudioDescriptors.toString());
    }

    /**
     * @hide
     * Creates a copy of an AudioDeviceAttributes that only stores the device type, role and
     * address.
     *
     * <p>It's recommended to use this method when comparing instances with equals (e.g.: when
     * using them as keys to maps) to recognize a given device based on type and address,
     * ignoring any other fields such as audio descriptors and profiles.
     * @return a new AudioDeviceAttributes from type and address of the original one
     */
    public AudioDeviceAttributes createFromTypeAndAddress() {
        return new AudioDeviceAttributes(mNativeType, mAddress);
    }

    @Override
    public int describeContents() {
        return 0;
+107 −49
Original line number Diff line number Diff line
@@ -936,7 +936,8 @@ public class AudioService extends IAudioService.Stub
    // For possible volume behaviors, see
    // {@link AudioDeviceVolumeManager.AbsoluteDeviceVolumeBehavior}.
    @GuardedBy("mAbsoluteVolumeDeviceInfoMapLock")
    Map<Integer, AbsoluteVolumeDeviceInfo> mAbsoluteVolumeDeviceInfoMap = new ArrayMap<>();
    Map<AudioDeviceAttributes, AbsoluteVolumeDeviceInfo> mAbsoluteVolumeDeviceInfoMap =
            new ArrayMap<>();
    /**
     * Stores information about a device using absolute volume behavior.
@@ -992,8 +993,7 @@ public class AudioService extends IAudioService.Stub
        @Override
        public void binderDied() {
            if (mParent.removeAudioSystemDeviceOutFromAbsVolumeDevices(mDevice.getInternalType())
                    != null) {
            if (mParent.removeFromAbsoluteVolumeDevices(mDevice) != null) {
                mParent.dispatchDeviceVolumeBehavior(mDevice,
                        AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE);
            }
@@ -4184,9 +4184,15 @@ public class AudioService extends IAudioService.Stub
        int oldIndex = getVssForStreamOrDefault(streamType).getIndex(deviceType);
        // Check if the volume adjustment should be handled by an absolute volume controller instead
        if (isAbsoluteVolumeDevice(deviceType)
                && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
            final AbsoluteVolumeDeviceInfo info = getAbsoluteVolumeDeviceInfo(deviceType);
        boolean isAbsoluteVolumeDevice = unifyAbsoluteVolumeManagement() ? isAbsoluteVolumeDevice(
                deviceAttr) : isAbsoluteVolumeDevice(deviceType);
        if (isAbsoluteVolumeDevice && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
            final AbsoluteVolumeDeviceInfo info;
            if (unifyAbsoluteVolumeManagement()) {
                info = getAbsoluteVolumeDeviceInfo(deviceAttr);
            } else {
                info = getAbsoluteVolumeDeviceInfo(deviceType);
            }
            if (info != null && info.mHandlesVolumeAdjustment) {
                dispatchAbsoluteVolumeAdjusted(streamType, info, oldIndex, direction,
                        keyEventMode);
@@ -4314,14 +4320,20 @@ public class AudioService extends IAudioService.Stub
    }
    private boolean handleAbsoluteVolume(int streamType, int streamTypeAlias,
            AudioDeviceAttributes deviceAttr, int newIndex, int flags) {
            @NonNull AudioDeviceAttributes ada, int newIndex, int flags) {
            // Check if volume update should be handled by an external volume controller
        boolean registeredAsAbsoluteVolume = false;
        boolean volumeHandled = false;
        int deviceType = deviceAttr.getInternalType();
        if (isAbsoluteVolumeDevice(deviceType)
                && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
            final AbsoluteVolumeDeviceInfo info = getAbsoluteVolumeDeviceInfo(deviceType);
        int deviceType = ada.getInternalType();
        boolean isAbsoluteVolume = unifyAbsoluteVolumeManagement() ? isAbsoluteVolumeDevice(ada)
                : isAbsoluteVolumeDevice(deviceType);
        if (isAbsoluteVolume && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
            final AbsoluteVolumeDeviceInfo info;
            if (unifyAbsoluteVolumeManagement()) {
                info = getAbsoluteVolumeDeviceInfo(ada);
            } else {
                info = getAbsoluteVolumeDeviceInfo(deviceType);
            }
            if (info != null) {
                dispatchAbsoluteVolumeChanged(streamType, info, newIndex);
                registeredAsAbsoluteVolume = true;
@@ -4700,7 +4712,8 @@ public class AudioService extends IAudioService.Stub
        final AudioDeviceAttributes currDevAttr = getDeviceAttributesForStream(streamType);
        final boolean skipping =
                (currDevAttr.getInternalType() == ada.getInternalType()) || (vss == null);
                (unifyAbsoluteVolumeManagement() ? currDevAttr.equalTypeAddress(ada)
                        : currDevAttr.getInternalType() == ada.getInternalType()) || (vss == null);
        AudioService.sVolumeLogger.enqueue(new DeviceVolumeEvent(streamType, index, ada,
                currDevAttr.getInternalType(), callingPackage, skipping));
@@ -5243,8 +5256,7 @@ public class AudioService extends IAudioService.Stub
        if (absVolumeDevices.size() > 1) {
            Slog.w(TAG, "onUpdateContextualVolumes too many active devices: "
                    + absVolumeDevices.stream().map(AudioDeviceAttributes::toString)
                    .collect(Collectors.joining(","))
                    + ", for stream: " + streamType);
                    .collect(Collectors.joining(",")) + ", for stream: " + streamType);
            return;
        }
@@ -8324,8 +8336,13 @@ public class AudioService extends IAudioService.Stub
        if (register) {
            AbsoluteVolumeDeviceInfo info = new AbsoluteVolumeDeviceInfo(this,
                    device, volumes, cb, handlesVolumeAdjustment, deviceVolumeBehavior);
            final AbsoluteVolumeDeviceInfo oldInfo = getAbsoluteVolumeDeviceInfo(deviceOut);
            addAudioSystemDeviceOutToAbsVolumeDevices(deviceOut, info);
            AbsoluteVolumeDeviceInfo oldInfo;
            if (unifyAbsoluteVolumeManagement()) {
                oldInfo = getAbsoluteVolumeDeviceInfo(device);
            } else {
                oldInfo = getAbsoluteVolumeDeviceInfo(deviceOut);
            }
            addToAbsoluteVolumeDevices(device, info);
            boolean volumeBehaviorChanged = (oldInfo == null)
                    || (oldInfo.mDeviceVolumeBehavior != deviceVolumeBehavior);
@@ -8357,8 +8374,7 @@ public class AudioService extends IAudioService.Stub
                }
            }
        } else {
            AbsoluteVolumeDeviceInfo deviceInfo = removeAudioSystemDeviceOutFromAbsVolumeDevices(
                    deviceOut);
            AbsoluteVolumeDeviceInfo deviceInfo = removeFromAbsoluteVolumeDevices(device);
            if (deviceInfo != null) {
                deviceInfo.unlinkToDeath();
                dispatchDeviceVolumeBehavior(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE);
@@ -8398,10 +8414,15 @@ public class AudioService extends IAudioService.Stub
            return;
        }
        setDeviceVolumeBehaviorInternal(device, deviceVolumeBehavior, pkgName);
        // sanitize the device to contain only type and address
        final AudioDeviceAttributes sanitizedDevice = new AudioDeviceAttributes(
                device.getInternalType(), device.getAddress());
        setDeviceVolumeBehaviorInternal(sanitizedDevice, deviceVolumeBehavior, pkgName);
        persistDeviceVolumeBehavior(device.getInternalType(), deviceVolumeBehavior);
    }
    @SuppressLint("ShortCircuitBoolean")  // we need to execute all or statements
    private void setDeviceVolumeBehaviorInternal(@NonNull AudioDeviceAttributes device,
            @AudioDeviceVolumeManager.DeviceVolumeBehavior int deviceVolumeBehavior,
            @NonNull String caller) {
@@ -8413,22 +8434,19 @@ public class AudioService extends IAudioService.Stub
                volumeBehaviorChanged |=
                        removeAudioSystemDeviceOutFromFullVolumeDevices(audioSystemDeviceOut)
                        | removeAudioSystemDeviceOutFromFixedVolumeDevices(audioSystemDeviceOut)
                        | (removeAudioSystemDeviceOutFromAbsVolumeDevices(audioSystemDeviceOut)
                                != null);
                        | (removeFromAbsoluteVolumeDevices(device) != null);
                break;
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_FIXED:
                volumeBehaviorChanged |=
                        removeAudioSystemDeviceOutFromFullVolumeDevices(audioSystemDeviceOut)
                        | addAudioSystemDeviceOutToFixedVolumeDevices(audioSystemDeviceOut)
                        | (removeAudioSystemDeviceOutFromAbsVolumeDevices(audioSystemDeviceOut)
                                != null);
                        | (removeFromAbsoluteVolumeDevices(device) != null);
                break;
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_FULL:
                volumeBehaviorChanged |=
                        addAudioSystemDeviceOutToFullVolumeDevices(audioSystemDeviceOut)
                        | removeAudioSystemDeviceOutFromFixedVolumeDevices(audioSystemDeviceOut)
                        | (removeAudioSystemDeviceOutFromAbsVolumeDevices(audioSystemDeviceOut)
                                != null);
                        | (removeFromAbsoluteVolumeDevices(device) != null);
                break;
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE:
            case AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY:
@@ -8489,17 +8507,15 @@ public class AudioService extends IAudioService.Stub
        if (mAbsVolumeMultiModeCaseDevices.contains(audioSystemDeviceOut)) {
            return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE;
        }
        // sanitize the device to contain only type and address
        final AudioDeviceAttributes sanitizedDevice = device.createFromTypeAndAddress();
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            if (mAbsoluteVolumeDeviceInfoMap.containsKey(audioSystemDeviceOut)) {
            final AbsoluteVolumeDeviceInfo deviceInfo = mAbsoluteVolumeDeviceInfoMap.get(
                        audioSystemDeviceOut);
                    sanitizedDevice);
            if (deviceInfo != null) {
                return deviceInfo.mDeviceVolumeBehavior;
            }
                Log.e(TAG,
                        "Null absolute volume device info stored for key " + audioSystemDeviceOut);
            }
        }
        if (isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)
@@ -12920,7 +12936,7 @@ public class AudioService extends IAudioService.Stub
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            return mAbsoluteVolumeDeviceInfoMap.entrySet().stream()
                    .filter(entry -> entry.getValue().mDeviceVolumeBehavior == behavior)
                    .map(Map.Entry::getKey)
                    .map(entry -> entry.getKey().getInternalType())
                    .collect(Collectors.toSet());
        }
    }
@@ -15521,7 +15537,25 @@ public class AudioService extends IAudioService.Stub
    @Nullable
    private AbsoluteVolumeDeviceInfo getAbsoluteVolumeDeviceInfo(int deviceType) {
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            return mAbsoluteVolumeDeviceInfoMap.get(deviceType);
            Optional<AbsoluteVolumeDeviceInfo> info =
                    mAbsoluteVolumeDeviceInfoMap.entrySet().stream().filter(
                            entry -> entry.getKey().getInternalType() == deviceType).map(
                            Map.Entry::getValue).findFirst();
            return info.orElse(null);
        }
    }
    /**
     * Returns the input device which uses absolute volume behavior, including its variants,
     * or {@code null} if there is no mapping for the AudioDeviceAttributes.
     *
     * @param device the simplified attributes continaing onlye address and type
     */
    @Nullable
    private AbsoluteVolumeDeviceInfo getAbsoluteVolumeDeviceInfo(AudioDeviceAttributes device) {
        final AudioDeviceAttributes ada = device.createFromTypeAndAddress();
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            return mAbsoluteVolumeDeviceInfoMap.get(ada);
        }
    }
@@ -15535,7 +15569,8 @@ public class AudioService extends IAudioService.Stub
    private boolean isAbsoluteVolumeDevice(int deviceType) {
        boolean hasAbsoluteVolumeDeviceKey;
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            hasAbsoluteVolumeDeviceKey = mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType);
            hasAbsoluteVolumeDeviceKey = mAbsoluteVolumeDeviceInfoMap.entrySet().stream().anyMatch(
                    entry -> entry.getKey().getInternalType() == deviceType);
        }
        if (unifyAbsoluteVolumeManagement() && hasAbsoluteVolumeDeviceKey) {
            return true;
@@ -15548,6 +15583,27 @@ public class AudioService extends IAudioService.Stub
        }
    }
    /**
     * Returns whether the input device uses absolute volume behavior, including its variants.
     * For included volume behaviors, see {@link AudioManager.AbsoluteDeviceVolumeBehavior}.
     */
    private boolean isAbsoluteVolumeDevice(AudioDeviceAttributes ada) {
        boolean hasAbsoluteVolumeDeviceKey;
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            hasAbsoluteVolumeDeviceKey = mAbsoluteVolumeDeviceInfoMap.containsKey(
                    ada.createFromTypeAndAddress());
        }
        if (unifyAbsoluteVolumeManagement() && hasAbsoluteVolumeDeviceKey) {
            return true;
        } else {
            return hasAbsoluteVolumeDeviceKey
                    || isA2dpAbsoluteVolumeDevice(ada.getInternalType())
                    || AudioSystem.isLeAudioDeviceType(ada.getInternalType())
                    || ada.getInternalType() == AudioSystem.DEVICE_OUT_HEARING_AID
                    || ada.getInternalType() == AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
        }
    }
    /**
     * Returns whether the input device is a Bluetooth A2dp device that uses absolute volume
     * behavior. This is distinct from the general implementation of absolute volume behavior
@@ -15559,7 +15615,8 @@ public class AudioService extends IAudioService.Stub
    private boolean isHdmiAbsoluteVolumeDevice(int deviceType) {
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            return mAbsoluteVolumeDeviceInfoMap.containsKey(deviceType)
            return mAbsoluteVolumeDeviceInfoMap.entrySet().stream().anyMatch(
                    entry -> entry.getKey().getInternalType() == deviceType)
                    && (deviceType == AudioSystem.DEVICE_OUT_HDMI
                    || deviceType == AudioSystem.DEVICE_OUT_HDMI_ARC
                    || deviceType == AudioSystem.DEVICE_OUT_HDMI_EARC);
@@ -15658,33 +15715,34 @@ public class AudioService extends IAudioService.Stub
        return mFullVolumeDevices.remove(audioSystemDeviceOut);
    }
    private void addAudioSystemDeviceOutToAbsVolumeDevices(int audioSystemDeviceOut,
    private void addToAbsoluteVolumeDevices(AudioDeviceAttributes ada,
            AbsoluteVolumeDeviceInfo info) {
        if (info == null) {
            Log.e(TAG, "Cannot add null absolute volume info for audioSystemDeviceOut "
                    + audioSystemDeviceOut);
            Log.e(TAG, "Cannot add null absolute volume info for ada " + ada);
            return;
        }
        final AudioDeviceAttributes adaAsKey = ada.createFromTypeAndAddress();
        if (DEBUG_VOL) {
            Log.d(TAG, "Adding DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
            Log.d(TAG, "Adding device: " + adaAsKey
                    + " to mAbsoluteVolumeDeviceInfoMap with behavior "
                    + AudioDeviceVolumeManager.volumeBehaviorName(info.mDeviceVolumeBehavior)
            );
        }
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            mAbsoluteVolumeDeviceInfoMap.put(audioSystemDeviceOut, info);
            mAbsoluteVolumeDeviceInfoMap.put(adaAsKey, info);
        }
    }
    private AbsoluteVolumeDeviceInfo removeAudioSystemDeviceOutFromAbsVolumeDevices(
            int audioSystemDeviceOut) {
    private AbsoluteVolumeDeviceInfo removeFromAbsoluteVolumeDevices(
            AudioDeviceAttributes ada) {
        final AudioDeviceAttributes deviceOut = ada.createFromTypeAndAddress();
        if (DEBUG_VOL) {
            Log.d(TAG, "Removing DeviceType: 0x" + Integer.toHexString(audioSystemDeviceOut)
                    + " from mAbsoluteVolumeDeviceInfoMap");
            Log.d(TAG, "Removing device: " + deviceOut + " from mAbsoluteVolumeDeviceInfoMap");
        }
        synchronized (mAbsoluteVolumeDeviceInfoMapLock) {
            return mAbsoluteVolumeDeviceInfoMap.remove(audioSystemDeviceOut);
            return mAbsoluteVolumeDeviceInfoMap.remove(deviceOut);
        }
    }