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

Commit 043b3a24 authored by David Li's avatar David Li Committed by Shunkai Yao
Browse files

audio: Fix remote submix module device ports handling

 - remove the default address "0" for IN_SUBMIX and OUT_SUBMIX;
 - remove the profiles in the device port and assign profiles when
   connecting;
 - make remote submix input to use "virtual" connection type,
   same as the output;
 - fix ModuleConfig in VTS to avoid returning devices with virtual
   connections as "external devices" because they can actually
   be connected even when connection simulation is disabled;
 - fix TryConnectMissingDevice VTS test to disconnect the device
   if the operation has unexpectedly succeeded.

Bug: 286914845
Bug: 294976817
Test: atest VtsHalAudioCoreTargetTest
Change-Id: Ife11c9c356d1b5dc587d08cef47294e3b29f65c5
Merged-In: Ife11c9c356d1b5dc587d08cef47294e3b29f65c5
parent 3e31e557
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -88,7 +88,6 @@ cc_library {
        "primary/PrimaryMixer.cpp",
        "primary/StreamPrimary.cpp",
        "r_submix/ModuleRemoteSubmix.cpp",
        "r_submix/RemoteSubmixUtils.cpp",
        "r_submix/SubmixRoute.cpp",
        "r_submix/StreamRemoteSubmix.cpp",
        "stub/ModuleStub.cpp",
+35 −20
Original line number Diff line number Diff line
@@ -81,8 +81,6 @@ static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags,
        deviceExt.device.address = "bottom";
    } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
        deviceExt.device.address = "back";
    } else if (devType == AudioDeviceType::IN_SUBMIX || devType == AudioDeviceType::OUT_SUBMIX) {
        deviceExt.device.address = "0";
    }
    deviceExt.device.type.connection = std::move(connection);
    deviceExt.flags = flags;
@@ -291,15 +289,21 @@ std::unique_ptr<Configuration> getPrimaryConfiguration() {
//
// Device ports:
//  * "Remote Submix Out", OUT_SUBMIX
//    - profile PCM 16-bit; STEREO; 48000
//    - no profiles specified
//  * "Remote Submix In", IN_SUBMIX
//    - profile PCM 16-bit; STEREO; 48000
//    - no profiles specified
//
// Mix ports:
//  * "r_submix output", 1 max open, 1 max active stream
//    - profile PCM 16-bit; STEREO; 48000
//  * "r_submix input", 1 max open, 1 max active stream
//    - profile PCM 16-bit; STEREO; 48000
//  * "r_submix output", unlimited max open, unlimited max active stream
//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//  * "r_submix input", unlimited max open, unlimited max active stream
//    - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 32-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//    - profile PCM 32-bit float; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000
//
// Routes:
//  "r_submix output" -> "Remote Submix Out"
@@ -308,6 +312,19 @@ std::unique_ptr<Configuration> getPrimaryConfiguration() {
std::unique_ptr<Configuration> getRSubmixConfiguration() {
    static const Configuration configuration = []() {
        Configuration c;
        const std::vector<AudioProfile> standardPcmAudioProfiles{
                createProfile(PcmType::FLOAT_32_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {8000, 11025, 16000, 32000, 44100, 48000}),
                createProfile(PcmType::INT_32_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {8000, 11025, 16000, 32000, 44100, 48000}),
                createProfile(PcmType::INT_24_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {8000, 11025, 16000, 32000, 44100, 48000}),
                createProfile(PcmType::INT_16_BIT,
                              {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
                              {8000, 11025, 16000, 32000, 44100, 48000})};

        // Device ports

@@ -315,28 +332,26 @@ std::unique_ptr<Configuration> getRSubmixConfiguration() {
                createPort(c.nextPortId++, "Remote Submix Out", 0, false,
                           createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0,
                                           AudioDeviceDescription::CONNECTION_VIRTUAL));
        rsubmixOutDevice.profiles.push_back(
                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        c.ports.push_back(rsubmixOutDevice);
        c.connectedProfiles[rsubmixOutDevice.id] = standardPcmAudioProfiles;

        AudioPort rsubmixInDevice = createPort(c.nextPortId++, "Remote Submix In", 0, true,
                                               createDeviceExt(AudioDeviceType::IN_SUBMIX, 0));
        rsubmixInDevice.profiles.push_back(
                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
        AudioPort rsubmixInDevice =
                createPort(c.nextPortId++, "Remote Submix In", 0, true,
                           createDeviceExt(AudioDeviceType::IN_SUBMIX, 0,
                                           AudioDeviceDescription::CONNECTION_VIRTUAL));
        c.ports.push_back(rsubmixInDevice);
        c.connectedProfiles[rsubmixInDevice.id] = standardPcmAudioProfiles;

        // Mix ports

        AudioPort rsubmixOutMix =
                createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(1, 1));
        rsubmixOutMix.profiles.push_back(
                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
                createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(0, 0));
        rsubmixOutMix.profiles = standardPcmAudioProfiles;
        c.ports.push_back(rsubmixOutMix);

        AudioPort rsubmixInMix =
                createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(1, 1));
        rsubmixInMix.profiles.push_back(
                createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
                createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(0, 0));
        rsubmixInMix.profiles = standardPcmAudioProfiles;
        c.ports.push_back(rsubmixInMix);

        c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
+0 −5
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ class ModuleRemoteSubmix : public Module {

  private:
    // IModule interfaces
    ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
    ndk::ScopedAStatus getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
    ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
    ndk::ScopedAStatus setMicMute(bool in_mute) override;

@@ -49,9 +47,6 @@ class ModuleRemoteSubmix : public Module {
            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sources,
            const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks)
            override;
    void onExternalDeviceConnectionChanged(
            const ::aidl::android::media::audio::common::AudioPort& audioPort,
            bool connected) override;
    ndk::ScopedAStatus onMasterMuteChanged(bool mute) override;
    ndk::ScopedAStatus onMasterVolumeChanged(float volume) override;
};
+19 −34
Original line number Diff line number Diff line
@@ -19,8 +19,8 @@
#include <vector>

#include <android-base/logging.h>
#include <error/expected_utils.h>

#include "RemoteSubmixUtils.h"
#include "core-impl/ModuleRemoteSubmix.h"
#include "core-impl/StreamRemoteSubmix.h"

@@ -33,18 +33,6 @@ using aidl::android::media::audio::common::MicrophoneInfo;

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

ndk::ScopedAStatus ModuleRemoteSubmix::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
    *_aidl_return = nullptr;
    LOG(DEBUG) << __func__ << ": returning null";
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus ModuleRemoteSubmix::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
    *_aidl_return = nullptr;
    LOG(DEBUG) << __func__ << ": returning null";
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
    LOG(DEBUG) << __func__ << ": is not supported";
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -70,23 +58,26 @@ ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
}

ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort) {
    LOG(VERBOSE) << __func__ << ": Profiles already populated by Configuration";
    for (auto profile : audioPort->profiles) {
        for (auto channelMask : profile.channelMasks) {
            if (!r_submix::isChannelMaskSupported(channelMask)) {
                LOG(ERROR) << __func__ << ": the profile " << profile.name
                           << " has unsupported channel mask : " << channelMask.toString();
                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
            }
        }
        for (auto sampleRate : profile.sampleRates) {
            if (!r_submix::isSampleRateSupported(sampleRate)) {
                LOG(ERROR) << __func__ << ": the profile " << profile.name
                           << " has unsupported sample rate : " << sampleRate;
                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
            }
        }
    }
    // Find the corresponding mix port and copy its profiles.
    std::vector<AudioRoute> routes;
    // At this moment, the port has the same ID as the template port, see connectExternalDevice.
    RETURN_STATUS_IF_ERROR(getAudioRoutesForAudioPort(audioPort->id, &routes));
    if (routes.empty()) {
        LOG(ERROR) << __func__ << ": no routes found for the port " << audioPort->toString();
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    const auto& route = *routes.begin();
    AudioPort mixPort;
    if (route.sinkPortId == audioPort->id) {
        if (route.sourcePortIds.empty()) {
            LOG(ERROR) << __func__ << ": invalid route " << route.toString();
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
        }
        RETURN_STATUS_IF_ERROR(getAudioPort(*route.sourcePortIds.begin(), &mixPort));
    } else {
        RETURN_STATUS_IF_ERROR(getAudioPort(route.sinkPortId, &mixPort));
    }
    audioPort->profiles = mixPort.profiles;
    return ndk::ScopedAStatus::ok();
}

@@ -106,12 +97,6 @@ ndk::ScopedAStatus ModuleRemoteSubmix::checkAudioPatchEndpointsMatch(
    return ndk::ScopedAStatus::ok();
}

void ModuleRemoteSubmix::onExternalDeviceConnectionChanged(
        const ::aidl::android::media::audio::common::AudioPort& audioPort __unused,
        bool connected __unused) {
    LOG(DEBUG) << __func__ << ": do nothing and return";
}

ndk::ScopedAStatus ModuleRemoteSubmix::onMasterMuteChanged(bool __unused) {
    LOG(DEBUG) << __func__ << ": is not supported";
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+0 −47
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <vector>

#include "RemoteSubmixUtils.h"

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

bool isChannelMaskSupported(const AudioChannelLayout& channelMask) {
    const static std::vector<AudioChannelLayout> kSupportedChannelMask = {
            AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
                    AudioChannelLayout::LAYOUT_MONO),
            AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
                    AudioChannelLayout::LAYOUT_STEREO)};

    if (std::find(kSupportedChannelMask.begin(), kSupportedChannelMask.end(), channelMask) !=
        kSupportedChannelMask.end()) {
        return true;
    }
    return false;
}

bool isSampleRateSupported(int sampleRate) {
    const static std::vector<int> kSupportedSampleRates = {8000,  11025, 12000, 16000, 22050,
                                                           24000, 32000, 44100, 48000};

    if (std::find(kSupportedSampleRates.begin(), kSupportedSampleRates.end(), sampleRate) !=
        kSupportedSampleRates.end()) {
        return true;
    }
    return false;
}

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