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

Commit 6d60701e authored by Eric Laurent's avatar Eric Laurent
Browse files

audio policy: add Spatializer effect control

Add APIs to discover support for audio spatialization function and control a
spatializer output mixer and effect creation to Audio Policy Service.

When supported, a system service can retrieve a ISpatializer
interface to query supported features and set a spatialization mode.

When spatialization is enabled, the corresponding specialized output mixer is
created and the effect applied.

The audio policy manager will attach clients which audio attributes and
format qualifying for spatialization to the specialized output mixer.

Bug: 188502620
Test: make

Change-Id: Ie2734fb9bb3ef9b945431c6c9bd110b1434a79cd
Merged-In: Ie2734fb9bb3ef9b945431c6c9bd110b1434a79cd
parent 3e295742
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -388,7 +388,9 @@ aidl_interface {
        "aidl/android/media/AudioProductStrategy.aidl",
        "aidl/android/media/AudioVolumeGroup.aidl",
        "aidl/android/media/DeviceRole.aidl",
        "aidl/android/media/HeadTrackingMode.aidl",
        "aidl/android/media/SoundTriggerSession.aidl",
        "aidl/android/media/SpatializationLevel.aidl",
    ],
    imports: [
        "audio_common-aidl",
@@ -459,10 +461,13 @@ aidl_interface {
    srcs: [
        "aidl/android/media/GetInputForAttrResponse.aidl",
        "aidl/android/media/GetOutputForAttrResponse.aidl",
        "aidl/android/media/GetSpatializerResponse.aidl",
        "aidl/android/media/Int.aidl",
        "aidl/android/media/RecordClientInfo.aidl",
        "aidl/android/media/IAudioPolicyService.aidl",
        "aidl/android/media/IAudioPolicyServiceClient.aidl",
        "aidl/android/media/INativeSpatializerCallback.aidl",
        "aidl/android/media/ISpatializer.aidl",
    ],
    imports: [
        "audio_common-aidl",
+41 −0
Original line number Diff line number Diff line
@@ -2240,6 +2240,47 @@ status_t AudioSystem::getDevicesForRoleAndCapturePreset(audio_source_t audioSour
    return OK;
}

status_t AudioSystem::getSpatializer(const sp<media::INativeSpatializerCallback>& callback,
                                          sp<media::ISpatializer>* spatializer) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (spatializer == nullptr) {
        return BAD_VALUE;
    }
    if (aps == 0) {
        return PERMISSION_DENIED;
    }
    media::GetSpatializerResponse response;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            aps->getSpatializer(callback, &response)));

    *spatializer = response.spatializer;
    return OK;
}

status_t AudioSystem::canBeSpatialized(const audio_attributes_t *attr,
                                    const audio_config_t *config,
                                    const AudioDeviceTypeAddrVector &devices,
                                    bool *canBeSpatialized) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) {
        return PERMISSION_DENIED;
    }
    audio_attributes_t attributes = attr != nullptr ? *attr : AUDIO_ATTRIBUTES_INITIALIZER;
    audio_config_t configuration = config != nullptr ? *config : AUDIO_CONFIG_INITIALIZER;

    std::optional<media::AudioAttributesInternal> attrAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
    std::optional<media::AudioConfig> configAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_config_t_AudioConfig(configuration));
    std::vector<media::AudioDevice> devicesAidl = VALUE_OR_RETURN_STATUS(
            convertContainer<std::vector<media::AudioDevice>>(devices,
                                                   legacy2aidl_AudioDeviceTypeAddress));
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
            aps->canBeSpatialized(attrAidl, configAidl, devicesAidl, canBeSpatialized)));
    return OK;
}


class CaptureStateListenerImpl : public media::BnCaptureStateListener,
                                 public IBinder::DeathRecipient {
public:
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.ISpatializer;

/**
 * Used as a return value for IAudioPolicyService.getSpatializer() method
 * {@hide}
 */
 parcelable GetSpatializerResponse {
    /* The ISpatializer interface if successful, null if not */
    @nullable ISpatializer spatializer;
}
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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;


/**
 * The head tracking mode supported by the spatializer stage effect implementation.
 * Used by methods of the ISpatializer interface.
 * {@hide}
 */
@Backing(type="byte")
enum HeadTrackingMode {
    /** Head tracking is active in a mode not listed below (forward compatibility) */
    OTHER = 0,
    /** Head tracking is disabled */
    DISABLED = 1,
    /** Head tracking is performed relative to the real work environment */
    RELATIVE_WORLD = 2,
    /** Head tracking is performed relative to the device's screen */
    RELATIVE_SCREEN = 3,
}
+27 −0
Original line number Diff line number Diff line
@@ -47,8 +47,10 @@ import android.media.DeviceRole;
import android.media.EffectDescriptor;
import android.media.GetInputForAttrResponse;
import android.media.GetOutputForAttrResponse;
import android.media.GetSpatializerResponse;
import android.media.IAudioPolicyServiceClient;
import android.media.ICaptureStateListener;
import android.media.INativeSpatializerCallback;
import android.media.Int;
import android.media.SoundTriggerSession;

@@ -348,4 +350,29 @@ interface IAudioPolicyService {
                                                    DeviceRole role);

    boolean registerSoundTriggerCaptureStateListener(ICaptureStateListener listener);

    /** If a spatializer stage effect is present on the platform, this will return an
     * ISpatializer interface (see GetSpatializerResponse,aidl) to control this
     * feature.
     * If no spatializer stage is present, a null interface is returned.
     * The INativeSpatializerCallback passed must not be null.
     * Only one ISpatializer interface can exist at a given time. The native audio policy
     * service will reject the request if an interface was already acquired and previous owner
     * did not die or call ISpatializer.release().
     */
    GetSpatializerResponse getSpatializer(INativeSpatializerCallback callback);

    /** Queries if some kind of spatialization will be performed if the audio playback context
     * described by the provided arguments is present.
     * The context is made of:
     * - The audio attributes describing the playback use case.
     * - The audio configuration describing the audio format, channels, sampling rate...
     * - The devices describing the sink audio device selected for playback.
     * All arguments are optional and only the specified arguments are used to match against
     * supported criteria. For instance, supplying no argument will tell if spatialization is
     * supported or not in general.
     */
    boolean canBeSpatialized(in @nullable AudioAttributesInternal attr,
                             in @nullable AudioConfig config,
                             in AudioDevice[] devices);
}
Loading