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

Commit a84c3d3a authored by jiabin's avatar jiabin
Browse files

Support setting preferred mixer attributes for USB devices.

This is part of USB audio improvement. With setting mixer attributes,
apps will be able to choose the best mixer attributes for their
playback. This can help improve latency and audio experience.

Bug: 239435816
Test: atest AudioManagerTest
Test: atest audiopolicy_tests
Test: Manually
Change-Id: Ifd1e8e35f94dab309eabe879d20ae0358038a4bf
parent 7b33ff46
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -392,6 +392,8 @@ aidl_interface {
    srcs: [
        "aidl/android/media/AudioAttributesEx.aidl",
        "aidl/android/media/AudioMix.aidl",
        "aidl/android/media/AudioMixerAttributesInternal.aidl",
        "aidl/android/media/AudioMixerBehavior.aidl",
        "aidl/android/media/AudioMixCallbackFlag.aidl",
        "aidl/android/media/AudioMixMatchCriterion.aidl",
        "aidl/android/media/AudioMixMatchCriterionValue.aidl",
+79 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@

#include <system/audio.h>
#include <android/media/GetInputForAttrResponse.h>
#include <android/media/AudioMixerAttributesInternal.h>

#define VALUE_OR_RETURN_BINDER_STATUS(x) \
    ({ auto _tmp = (x); \
@@ -2538,6 +2539,84 @@ int32_t AudioSystem::getAAudioHardwareBurstMinUsec() {
    return af->getAAudioHardwareBurstMinUsec();
}

status_t AudioSystem::getSupportedMixerAttributes(
        audio_port_handle_t portId, std::vector<audio_mixer_attributes_t> *mixerAttrs) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == nullptr) {
        return PERMISSION_DENIED;
    }

    int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
    std::vector<media::AudioMixerAttributesInternal> _aidlReturn;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            aps->getSupportedMixerAttributes(portIdAidl, &_aidlReturn)));
    *mixerAttrs = VALUE_OR_RETURN_STATUS(
            convertContainer<std::vector<audio_mixer_attributes_t>>(
                    _aidlReturn,
                    aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t));
    return OK;
}

status_t AudioSystem::setPreferredMixerAttributes(const audio_attributes_t *attr,
                                                  audio_port_handle_t portId,
                                                  uid_t uid,
                                                  const audio_mixer_attributes_t *mixerAttr) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == nullptr) {
        return PERMISSION_DENIED;
    }

    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
    media::AudioMixerAttributesInternal mixerAttrAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(*mixerAttr));
    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
    int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));

    return statusTFromBinderStatus(
            aps->setPreferredMixerAttributes(attrAidl, portIdAidl, uidAidl, mixerAttrAidl));
}

status_t AudioSystem::getPreferredMixerAttributes(
        const audio_attributes_t *attr,
        audio_port_handle_t portId,
        std::optional<audio_mixer_attributes_t> *mixerAttr) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == nullptr) {
        return PERMISSION_DENIED;
    }

    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
    int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
    std::optional<media::AudioMixerAttributesInternal> _aidlReturn;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            aps->getPreferredMixerAttributes(attrAidl, portIdAidl, &_aidlReturn)));

    if (_aidlReturn.has_value()) {
         *mixerAttr = VALUE_OR_RETURN_STATUS(
                 aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(
                         _aidlReturn.value()));
    }
    return NO_ERROR;
}

status_t AudioSystem::clearPreferredMixerAttributes(const audio_attributes_t *attr,
                                                    audio_port_handle_t portId,
                                                    uid_t uid) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == nullptr) {
        return PERMISSION_DENIED;
    }

    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
    int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
    int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
    return statusTFromBinderStatus(
            aps->clearPreferredMixerAttributes(attrAidl, portIdAidl, uidAidl));
}

// ---------------------------------------------------------------------------

int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
+43 −0
Original line number Diff line number Diff line
@@ -472,4 +472,47 @@ legacy2aidl_audio_offload_mode_t_AudioOffloadMode(audio_offload_mode_t legacy) {
    return unexpected(BAD_VALUE);
}

ConversionResult<audio_mixer_behavior_t>
aidl2legacy_AudioMixerBehavior_audio_mixer_behavior_t(media::AudioMixerBehavior aidl) {
    switch (aidl) {
        case media::AudioMixerBehavior::DEFAULT:
            return AUDIO_MIXER_BEHAVIOR_DEFAULT;
        case media::AudioMixerBehavior::INVALID:
            return AUDIO_MIXER_BEHAVIOR_INVALID;
    }
    return unexpected(BAD_VALUE);
}
ConversionResult<media::AudioMixerBehavior>
legacy2aidl_audio_mixer_behavior_t_AudioMixerBehavior(audio_mixer_behavior_t legacy) {
    switch (legacy) {
        case AUDIO_MIXER_BEHAVIOR_DEFAULT:
            return media::AudioMixerBehavior::DEFAULT;
        case AUDIO_MIXER_BEHAVIOR_INVALID:
            return media::AudioMixerBehavior::INVALID;
    }
    return unexpected(BAD_VALUE);
}

ConversionResult<audio_mixer_attributes_t>
aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(
        const media::AudioMixerAttributesInternal& aidl) {
    audio_mixer_attributes_t legacy = AUDIO_MIXER_ATTRIBUTES_INITIALIZER;
    legacy.config = VALUE_OR_RETURN(
            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config, false /*isInput*/));
    legacy.mixer_behavior = VALUE_OR_RETURN(
            aidl2legacy_AudioMixerBehavior_audio_mixer_behavior_t(aidl.mixerBehavior));
    return legacy;
}
ConversionResult<media::AudioMixerAttributesInternal>
legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(
        const audio_mixer_attributes& legacy) {
    media::AudioMixerAttributesInternal aidl;
    aidl.config = VALUE_OR_RETURN(
            legacy2aidl_audio_config_base_t_AudioConfigBase(legacy.config, false /*isInput*/));
    aidl.mixerBehavior = VALUE_OR_RETURN(
            legacy2aidl_audio_mixer_behavior_t_AudioMixerBehavior(legacy.mixer_behavior));
    return aidl;
}


}  // namespace android
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import android.media.AudioMixerBehavior;
import android.media.audio.common.AudioConfigBase;

/**
 * This class is used to contains information about audio mixer.
 * The "Internal" suffix of this type name is to disambiguate it from the
 * android.media.AudioMixerAttributes SDK type.
 *
 * {@hide}
 */
parcelable AudioMixerAttributesInternal {
    AudioConfigBase config;
    AudioMixerBehavior mixerBehavior;
}
+33 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

/**
 * Defines the mixer behavior that can be used when setting mixer attributes.
 */
@Backing(type="int")
enum AudioMixerBehavior {
    /**
     * The mixer behavior is invalid.
     */
    INVALID = -1,
    /**
     * The mixer behavior that follows platform default behavior, which is mixing audio from
     * different sources.
     */
    DEFAULT = 0,
}
Loading