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

Commit 09c9ec41 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Automerger Merge Worker
Browse files

audio HAL: Minimal example implementation am: df5adfde am: 88a81f47

parents e2ec1b9f 88a81f47
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "hardware_interfaces_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["hardware_interfaces_license"],
}

cc_library_static {
    name: "libaudioserviceexampleimpl",
    vendor: true,
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "android.hardware.audio.core-V1-ndk",
    ],
    export_include_dirs: ["include"],
    srcs: [
        "Config.cpp",
        "Configuration.cpp",
        "Module.cpp",
        "Stream.cpp",
    ],
    visibility: [
        ":__subpackages__",
    ],
}

cc_binary {
    name: "android.hardware.audio.service-aidl.example",
    relative_install_path: "hw",
    init_rc: ["android.hardware.audio.service-aidl.example.rc"],
    vintf_fragments: ["android.hardware.audio.service-aidl.xml"],
    vendor: true,
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "android.hardware.audio.core-V1-ndk",
    ],
    static_libs: [
        "libaudioserviceexampleimpl",
    ],
    srcs: ["main.cpp"],
}
+19 −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.
 */

#include "core-impl/Config.h"

namespace aidl::android::hardware::audio::core {}  // namespace aidl::android::hardware::audio::core
+196 −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.
 */

#include <aidl/android/media/audio/common/AudioChannelLayout.h>
#include <aidl/android/media/audio/common/AudioDeviceType.h>
#include <aidl/android/media/audio/common/AudioFormatType.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>

#include "aidl/android/media/audio/common/AudioFormatDescription.h"
#include "core-impl/Configuration.h"

using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioGainConfig;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::PcmType;

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

static AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
                                  const std::vector<int32_t>& sampleRates) {
    AudioProfile profile;
    profile.format.type = AudioFormatType::PCM;
    profile.format.pcm = pcmType;
    for (auto layout : channelLayouts) {
        profile.channelMasks.push_back(
                AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
    }
    profile.sampleRates.insert(profile.sampleRates.end(), sampleRates.begin(), sampleRates.end());
    return profile;
}

static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags) {
    AudioPortDeviceExt deviceExt;
    deviceExt.device.type.type = devType;
    deviceExt.flags = flags;
    return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
}

static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
    AudioPortMixExt mixExt;
    mixExt.maxOpenStreamCount = maxOpenStreamCount;
    mixExt.maxActiveStreamCount = maxActiveStreamCount;
    return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
}

static AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
                            const AudioPortExt& ext) {
    AudioPort port;
    port.id = id;
    port.name = name;
    port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
                         : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
    port.ext = ext;
    return port;
}

static AudioPortConfig createPortConfig(int32_t id, int32_t portId, PcmType pcmType, int32_t layout,
                                        int32_t sampleRate, int32_t flags, bool isInput,
                                        const AudioPortExt& ext) {
    AudioPortConfig config;
    config.id = id;
    config.portId = portId;
    config.sampleRate = Int{.value = sampleRate};
    config.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout);
    config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType};
    config.gain = AudioGainConfig();
    config.flags = isInput ? AudioIoFlags::make<AudioIoFlags::Tag::input>(flags)
                           : AudioIoFlags::make<AudioIoFlags::Tag::output>(flags);
    config.ext = ext;
    return config;
}

static AudioRoute createRoute(const std::vector<int32_t>& sources, int32_t sink) {
    AudioRoute route;
    route.sinkPortId = sink;
    route.sourcePortIds.insert(route.sourcePortIds.end(), sources.begin(), sources.end());
    return route;
}

Configuration& getNullPrimaryConfiguration() {
    static Configuration configuration = []() {
        Configuration c;

        AudioPort nullOutDevice =
                createPort(c.nextPortId++, "Null", 0, false,
                           createDeviceExt(AudioDeviceType::OUT_SPEAKER,
                                           1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
        c.ports.push_back(nullOutDevice);

        AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
                                             1 << static_cast<int32_t>(AudioOutputFlags::PRIMARY),
                                             false, createPortMixExt(1, 1));
        primaryOutMix.profiles.push_back(
                createProfile(PcmType::INT_16_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {44100, 48000}));
        primaryOutMix.profiles.push_back(
                createProfile(PcmType::INT_24_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {44100, 48000}));
        c.ports.push_back(primaryOutMix);

        c.routes.push_back(createRoute({primaryOutMix.id}, nullOutDevice.id));

        c.initialConfigs.push_back(
                createPortConfig(nullOutDevice.id, nullOutDevice.id, PcmType::INT_24_BIT,
                                 AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
                                 createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0)));

        AudioPort loopOutDevice = createPort(c.nextPortId++, "Loopback Out", 0, false,
                                             createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0));
        loopOutDevice.profiles.push_back(
                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        c.ports.push_back(loopOutDevice);

        AudioPort loopOutMix =
                createPort(c.nextPortId++, "loopback output", 0, false, createPortMixExt(0, 0));
        loopOutMix.profiles.push_back(
                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        c.ports.push_back(loopOutMix);

        c.routes.push_back(createRoute({loopOutMix.id}, loopOutDevice.id));

        AudioPort zeroInDevice =
                createPort(c.nextPortId++, "Zero", 0, true,
                           createDeviceExt(AudioDeviceType::IN_MICROPHONE,
                                           1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
        c.ports.push_back(zeroInDevice);

        AudioPort primaryInMix =
                createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(2, 2));
        primaryInMix.profiles.push_back(
                createProfile(PcmType::INT_16_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                               AudioChannelLayout::LAYOUT_FRONT_BACK},
                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
        primaryInMix.profiles.push_back(
                createProfile(PcmType::INT_24_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO,
                               AudioChannelLayout::LAYOUT_FRONT_BACK},
                              {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}));
        c.ports.push_back(primaryInMix);

        c.routes.push_back(createRoute({zeroInDevice.id}, primaryInMix.id));

        c.initialConfigs.push_back(
                createPortConfig(zeroInDevice.id, zeroInDevice.id, PcmType::INT_24_BIT,
                                 AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
                                 createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0)));

        AudioPort loopInDevice = createPort(c.nextPortId++, "Loopback In", 0, true,
                                            createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
        loopInDevice.profiles.push_back(
                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        c.ports.push_back(loopInDevice);

        AudioPort loopInMix =
                createPort(c.nextPortId++, "loopback input", 0, true, createPortMixExt(0, 0));
        loopInMix.profiles.push_back(
                createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        c.ports.push_back(loopInMix);

        c.routes.push_back(createRoute({loopInDevice.id}, loopInMix.id));

        c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
        return c;
    }();
    return configuration;
}

}  // namespace aidl::android::hardware::audio::core::internal
+522 −0

File added.

Preview size limit exceeded, changes collapsed.

+76 −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.
 */

#define LOG_TAG "AHAL_Stream"
#define LOG_NDEBUG 0
#include <android-base/logging.h>

#include "core-impl/Stream.h"

using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioOffloadInfo;

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

StreamIn::StreamIn(const SinkMetadata& sinkMetadata) : mMetadata(sinkMetadata) {}

ndk::ScopedAStatus StreamIn::close() {
    LOG(DEBUG) << __func__;
    if (!mIsClosed) {
        mIsClosed = true;
        return ndk::ScopedAStatus::ok();
    } else {
        LOG(ERROR) << __func__ << ": stream was already closed";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
}

ndk::ScopedAStatus StreamIn::updateMetadata(const SinkMetadata& in_sinkMetadata) {
    LOG(DEBUG) << __func__;
    if (!mIsClosed) {
        mMetadata = in_sinkMetadata;
        return ndk::ScopedAStatus::ok();
    }
    LOG(ERROR) << __func__ << ": stream was closed";
    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}

StreamOut::StreamOut(const SourceMetadata& sourceMetadata,
                     const std::optional<AudioOffloadInfo>& offloadInfo)
    : mMetadata(sourceMetadata), mOffloadInfo(offloadInfo) {}

ndk::ScopedAStatus StreamOut::close() {
    LOG(DEBUG) << __func__;
    if (!mIsClosed) {
        mIsClosed = true;
        return ndk::ScopedAStatus::ok();
    }
    LOG(ERROR) << __func__ << ": stream was already closed";
    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}

ndk::ScopedAStatus StreamOut::updateMetadata(const SourceMetadata& in_sourceMetadata) {
    LOG(DEBUG) << __func__;
    if (!mIsClosed) {
        mMetadata = in_sourceMetadata;
        return ndk::ScopedAStatus::ok();
    }
    LOG(ERROR) << __func__ << ": stream was closed";
    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}

}  // namespace aidl::android::hardware::audio::core
Loading