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

Commit 29e51689 authored by Weilin Xu's avatar Weilin Xu Committed by Android Build Cherrypicker Worker
Browse files

Support multiple output devices in refrence audio HAL

Parsed card id and device id from output bus device address,
and used them to write output data into corresponding PCM
devices in stream alsa.

Bug: 336370745
Test: atest VtsHalAudioCoreTargetTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4d71bd736be6f52a9e954dd518be0b6ece3ddc1b)
Merged-In: I18efa2d1aea233375906efc0aa9c93c8f3b464e8
Change-Id: I18efa2d1aea233375906efc0aa9c93c8f3b464e8
parent ad6288c8
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -75,6 +75,10 @@ StreamAlsa::~StreamAlsa() {
    }
    decltype(mAlsaDeviceProxies) alsaDeviceProxies;
    for (const auto& device : getDeviceProfiles()) {
        if ((device.direction == PCM_OUT && mIsInput) ||
            (device.direction == PCM_IN && !mIsInput)) {
            continue;
        }
        alsa::DeviceProxy proxy;
        if (device.isExternal) {
            // Always ask alsa configure as required since the configuration should be supported
@@ -92,6 +96,9 @@ StreamAlsa::~StreamAlsa() {
        }
        alsaDeviceProxies.push_back(std::move(proxy));
    }
    if (alsaDeviceProxies.empty()) {
        return ::android::NO_INIT;
    }
    mAlsaDeviceProxies = std::move(alsaDeviceProxies);
    return ::android::OK;
}
+7 −1
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ namespace aidl::android::hardware::audio::core {

class StreamPrimary : public StreamAlsa {
  public:
    StreamPrimary(StreamContext* context, const Metadata& metadata);
    StreamPrimary(StreamContext* context, const Metadata& metadata,
                  const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);

    ::android::status_t start() override;
    ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
@@ -39,6 +40,11 @@ class StreamPrimary : public StreamAlsa {
    int64_t mStartTimeNs = 0;
    long mFramesSinceStart = 0;
    bool mSkipNextTransfer = false;

  private:
    static std::pair<int, int> getCardAndDeviceId(
            const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);
    const std::pair<int, int> mCardAndDeviceId;
};

class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
+35 −14
Original line number Diff line number Diff line
@@ -15,7 +15,11 @@
 */

#define LOG_TAG "AHAL_StreamPrimary"

#include <cstdio>

#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <audio_utils/clock.h>
#include <error/Result.h>
@@ -28,6 +32,7 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDevice;
using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioOffloadInfo;
@@ -36,9 +41,15 @@ using android::base::GetBoolProperty;

namespace aidl::android::hardware::audio::core {

StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
const static constexpr std::pair<int, int> kDefaultCardAndDeviceId = {
        primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice};

StreamPrimary::StreamPrimary(
        StreamContext* context, const Metadata& metadata,
        const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
    : StreamAlsa(context, metadata, 3 /*readWriteRetries*/),
      mIsAsynchronous(!!getContext().getAsyncCallback()) {
      mIsAsynchronous(!!getContext().getAsyncCallback()),
      mCardAndDeviceId(getCardAndDeviceId(devices)) {
    context->startStreamDataProcessor();
}

@@ -92,17 +103,27 @@ StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
}

std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
    static const std::vector<alsa::DeviceProfile> kBuiltInSource{
            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
                                .device = primary::PrimaryMixer::kAlsaDevice,
                                .direction = PCM_IN,
    return {alsa::DeviceProfile{.card = mCardAndDeviceId.first,
                                .device = mCardAndDeviceId.second,
                                .direction = mIsInput ? PCM_IN : PCM_OUT,
                                .isExternal = false}};
    static const std::vector<alsa::DeviceProfile> kBuiltInSink{
            alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
                                .device = primary::PrimaryMixer::kAlsaDevice,
                                .direction = PCM_OUT,
                                .isExternal = false}};
    return mIsInput ? kBuiltInSource : kBuiltInSink;
}

std::pair<int, int> StreamPrimary::getCardAndDeviceId(const std::vector<AudioDevice>& devices) {
    if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) {
        return kDefaultCardAndDeviceId;
    }
    std::string deviceAddress = devices[0].address.get<AudioDeviceAddress::id>();
    std::pair<int, int> cardAndDeviceId;
    if (const size_t suffixPos = deviceAddress.rfind("CARD_");
        suffixPos == std::string::npos ||
        sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first,
               &cardAndDeviceId.second) != 2) {
        return kDefaultCardAndDeviceId;
    }
    LOG(DEBUG) << __func__ << ": parsed with card id " << cardAndDeviceId.first << ", device id "
               << cardAndDeviceId.second;
    return cardAndDeviceId;
}

StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
@@ -145,7 +166,7 @@ std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
                new InnerStreamWrapper<StreamStub>(context, metadata));
    }
    return std::unique_ptr<StreamCommonInterfaceEx>(
            new InnerStreamWrapper<StreamPrimary>(context, metadata));
            new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}

ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
@@ -217,7 +238,7 @@ std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
                new InnerStreamWrapper<StreamStub>(context, metadata));
    }
    return std::unique_ptr<StreamCommonInterfaceEx>(
            new InnerStreamWrapper<StreamPrimary>(context, metadata));
            new InnerStreamWrapper<StreamPrimary>(context, metadata, devices));
}

ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {