/* * 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 #include #include #include #include #include #include #include #include "core-impl/Configuration.h" using aidl::android::hardware::audio::common::makeBitPositionFlagMask; using aidl::android::media::audio::common::AudioChannelLayout; using aidl::android::media::audio::common::AudioDeviceDescription; 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; using Configuration = aidl::android::hardware::audio::core::Module::Configuration; namespace aidl::android::hardware::audio::core::internal { static void fillProfile(AudioProfile* profile, const std::vector& channelLayouts, const std::vector& sampleRates) { for (auto layout : channelLayouts) { profile->channelMasks.push_back( AudioChannelLayout::make(layout)); } profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end()); } static AudioProfile createProfile(PcmType pcmType, const std::vector& channelLayouts, const std::vector& sampleRates) { AudioProfile profile; profile.format.type = AudioFormatType::PCM; profile.format.pcm = pcmType; fillProfile(&profile, channelLayouts, sampleRates); return profile; } static AudioProfile createProfile(const std::string& encodingType, const std::vector& channelLayouts, const std::vector& sampleRates) { AudioProfile profile; profile.format.encoding = encodingType; fillProfile(&profile, channelLayouts, sampleRates); return profile; } static AudioPortExt createDeviceExt(AudioDeviceType devType, int32_t flags, std::string connection = "") { AudioPortDeviceExt deviceExt; deviceExt.device.type.type = devType; if (devType == AudioDeviceType::IN_MICROPHONE && connection.empty()) { deviceExt.device.address = "bottom"; } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) { deviceExt.device.address = "back"; } deviceExt.device.type.connection = std::move(connection); deviceExt.flags = flags; return AudioPortExt::make(deviceExt); } static AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) { AudioPortMixExt mixExt; mixExt.maxOpenStreamCount = maxOpenStreamCount; mixExt.maxActiveStreamCount = maxActiveStreamCount; return AudioPortExt::make(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(flags) : AudioIoFlags::make(flags); port.ext = ext; return port; } static AudioPortConfig createDynamicPortConfig(int32_t id, int32_t portId, int32_t flags, bool isInput, const AudioPortExt& ext) { AudioPortConfig config; config.id = id; config.portId = portId; config.format = AudioFormatDescription{}; config.channelMask = AudioChannelLayout{}; config.sampleRate = Int{.value = 0}; config.gain = AudioGainConfig(); config.flags = isInput ? AudioIoFlags::make(flags) : AudioIoFlags::make(flags); config.ext = ext; return config; } 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 = createDynamicPortConfig(id, portId, flags, isInput, ext); config.sampleRate = Int{.value = sampleRate}; config.channelMask = AudioChannelLayout::make(layout); config.format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType}; return config; } static AudioRoute createRoute(const std::vector& sources, const AudioPort& sink) { AudioRoute route; route.sinkPortId = sink.id; std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds), [](const auto& port) { return port.id; }); return route; } std::vector getStandard16And24BitPcmAudioProfiles() { auto createStdPcmAudioProfile = [](const PcmType& pcmType) { return AudioProfile{ .format = AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = pcmType}, .channelMasks = {AudioChannelLayout::make( AudioChannelLayout::LAYOUT_MONO), AudioChannelLayout::make( AudioChannelLayout::LAYOUT_STEREO)}, .sampleRates = {8000, 11025, 16000, 32000, 44100, 48000}}; }; return { createStdPcmAudioProfile(PcmType::INT_16_BIT), createStdPcmAudioProfile(PcmType::INT_24_BIT), }; } // Primary (default) configuration: // // Device ports: // * "Speaker", OUT_SPEAKER, default // - no profiles specified // * "Built-In Mic", IN_MICROPHONE, default // - no profiles specified // * "Telephony Tx", OUT_TELEPHONY_TX // - no profiles specified // * "Telephony Rx", IN_TELEPHONY_RX // - no profiles specified // * "FM Tuner", IN_FM_TUNER // - no profiles specified // // Mix ports: // * "primary output", PRIMARY, 1 max open, 1 max active stream // - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "primary input", 1 max open, 1 max active stream // - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "telephony_tx", 1 max open, 1 max active stream // - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "telephony_rx", 1 max open, 1 max active stream // - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "fm_tuner", 1 max open, 1 max active stream // - profile PCM 16-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // // Routes: // "primary out" -> "Speaker" // "Built-In Mic" -> "primary input" // "Telephony Rx" -> "telephony_rx" // "telephony_tx" -> "Telephony Tx" // "FM Tuner" -> "fm_tuner" // // Initial port configs: // * "Speaker" device port: dynamic configuration // * "Built-In Mic" device port: dynamic configuration // * "Telephony Tx" device port: dynamic configuration // * "Telephony Rx" device port: dynamic configuration // * "FM Tuner" device port: dynamic configuration // std::unique_ptr getPrimaryConfiguration() { static const Configuration configuration = []() { const std::vector standardPcmAudioProfiles = { createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO}, {8000, 11025, 16000, 32000, 44100, 48000})}; Configuration c; // Device ports AudioPort speakerOutDevice = createPort(c.nextPortId++, "Speaker", 0, false, createDeviceExt(AudioDeviceType::OUT_SPEAKER, 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE)); c.ports.push_back(speakerOutDevice); c.initialConfigs.push_back( createDynamicPortConfig(speakerOutDevice.id, speakerOutDevice.id, 0, false, createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0))); AudioPort micInDevice = createPort(c.nextPortId++, "Built-In Mic", 0, true, createDeviceExt(AudioDeviceType::IN_MICROPHONE, 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE)); c.ports.push_back(micInDevice); c.initialConfigs.push_back( createDynamicPortConfig(micInDevice.id, micInDevice.id, 0, true, createDeviceExt(AudioDeviceType::IN_MICROPHONE, 0))); AudioPort telephonyTxOutDevice = createPort(c.nextPortId++, "Telephony Tx", 0, false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0)); c.ports.push_back(telephonyTxOutDevice); c.initialConfigs.push_back( createDynamicPortConfig(telephonyTxOutDevice.id, telephonyTxOutDevice.id, 0, false, createDeviceExt(AudioDeviceType::OUT_TELEPHONY_TX, 0))); AudioPort telephonyRxInDevice = createPort(c.nextPortId++, "Telephony Rx", 0, true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0)); c.ports.push_back(telephonyRxInDevice); c.initialConfigs.push_back( createDynamicPortConfig(telephonyRxInDevice.id, telephonyRxInDevice.id, 0, true, createDeviceExt(AudioDeviceType::IN_TELEPHONY_RX, 0))); AudioPort fmTunerInDevice = createPort(c.nextPortId++, "FM Tuner", 0, true, createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0)); c.ports.push_back(fmTunerInDevice); c.initialConfigs.push_back( createDynamicPortConfig(fmTunerInDevice.id, fmTunerInDevice.id, 0, true, createDeviceExt(AudioDeviceType::IN_FM_TUNER, 0))); // Mix ports AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output", makeBitPositionFlagMask(AudioOutputFlags::PRIMARY), false, createPortMixExt(0, 0)); primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(primaryOutMix); AudioPort primaryInMix = createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 1)); primaryInMix.profiles.push_back( createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO}, {8000, 11025, 16000, 32000, 44100, 48000})); c.ports.push_back(primaryInMix); AudioPort telephonyTxOutMix = createPort(c.nextPortId++, "telephony_tx", 0, false, createPortMixExt(1, 1)); telephonyTxOutMix.profiles.insert(telephonyTxOutMix.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(telephonyTxOutMix); AudioPort telephonyRxInMix = createPort(c.nextPortId++, "telephony_rx", 0, true, createPortMixExt(0, 1)); telephonyRxInMix.profiles.insert(telephonyRxInMix.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(telephonyRxInMix); AudioPort fmTunerInMix = createPort(c.nextPortId++, "fm_tuner", 0, true, createPortMixExt(0, 1)); fmTunerInMix.profiles.insert(fmTunerInMix.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(fmTunerInMix); c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice)); c.routes.push_back(createRoute({micInDevice}, primaryInMix)); c.routes.push_back(createRoute({telephonyRxInDevice}, telephonyRxInMix)); c.routes.push_back(createRoute({telephonyTxOutMix}, telephonyTxOutDevice)); c.routes.push_back(createRoute({fmTunerInDevice}, fmTunerInMix)); c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end()); return c; }(); return std::make_unique(configuration); } // Note: When transitioning to loading of XML configs, either keep the configuration // of the remote submix sources from this static configuration, or update the XML // config to match it. There are several reasons for that: // 1. The "Remote Submix In" device is listed in the XML config as "attached", // however in the AIDL scheme its device type has a "virtual" connection. // 2. The canonical r_submix configuration only lists 'STEREO' and '48000', // however the framework attempts to open streams for other sample rates // as well. The legacy r_submix implementation allowed that, but libaudiohal@aidl // will not find a mix port to use. Because of that, list all sample rates that // the legacy implementation allowed (note that mono was not allowed, the framework // is expected to upmix mono tracks into stereo if needed). // 3. The legacy implementation had a hard limit on the number of routes (10), // and this is checked indirectly by AudioPlaybackCaptureTest#testPlaybackCaptureDoS // CTS test. Instead of hardcoding the number of routes, we can use // "maxOpen/ActiveStreamCount" to enforce a similar limit. However, the canonical // XML file lacks this specification. // // Remote Submix configuration: // // Device ports: // * "Remote Submix Out", OUT_SUBMIX // - no profiles specified // * "Remote Submix In", IN_SUBMIX // - no profiles specified // // Mix ports: // * "r_submix output", maximum 10 opened streams, maximum 10 active streams // - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "r_submix input", maximum 10 opened streams, maximum 10 active streams // - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // // Routes: // "r_submix output" -> "Remote Submix Out" // "Remote Submix In" -> "r_submix input" // std::unique_ptr getRSubmixConfiguration() { static const Configuration configuration = []() { Configuration c; const std::vector remoteSubmixPcmAudioProfiles{ createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {8000, 11025, 16000, 32000, 44100, 48000})}; // Device ports AudioPort rsubmixOutDevice = createPort(c.nextPortId++, "Remote Submix Out", 0, false, createDeviceExt(AudioDeviceType::OUT_SUBMIX, 0, AudioDeviceDescription::CONNECTION_VIRTUAL)); c.ports.push_back(rsubmixOutDevice); c.connectedProfiles[rsubmixOutDevice.id] = remoteSubmixPcmAudioProfiles; 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] = remoteSubmixPcmAudioProfiles; // Mix ports AudioPort rsubmixOutMix = createPort(c.nextPortId++, "r_submix output", 0, false, createPortMixExt(10, 10)); rsubmixOutMix.profiles = remoteSubmixPcmAudioProfiles; c.ports.push_back(rsubmixOutMix); AudioPort rsubmixInMix = createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(10, 10)); rsubmixInMix.profiles = remoteSubmixPcmAudioProfiles; c.ports.push_back(rsubmixInMix); c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice)); c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInMix)); return c; }(); return std::make_unique(configuration); } // Usb configuration: // // Device ports: // * "USB Device Out", OUT_DEVICE, CONNECTION_USB // - no profiles specified // * "USB Headset Out", OUT_HEADSET, CONNECTION_USB // - no profiles specified // * "USB Device In", IN_DEVICE, CONNECTION_USB // - no profiles specified // * "USB Headset In", IN_HEADSET, CONNECTION_USB // - no profiles specified // // Mix ports: // * "usb_device output", 1 max open, 1 max active stream // - no profiles specified // * "usb_device input", 1 max open, 1 max active stream // - no profiles specified // // Routes: // * "usb_device output" -> "USB Device Out" // * "usb_device output" -> "USB Headset Out" // * "USB Device In", "USB Headset In" -> "usb_device input" // // Profiles for device port connected state (when simulating connections): // * "USB Device Out", "USB Headset Out": // - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000 // - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000 // * "USB Device In", "USB Headset In": // - profile PCM 16-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000 // - profile PCM 24-bit; MONO, STEREO, INDEX_MASK_1, INDEX_MASK_2; 44100, 48000 // std::unique_ptr getUsbConfiguration() { static const Configuration configuration = []() { const std::vector standardPcmAudioProfiles = { createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO, AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2}, {44100, 48000}), createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO, AudioChannelLayout::INDEX_MASK_1, AudioChannelLayout::INDEX_MASK_2}, {44100, 48000})}; Configuration c; // Device ports AudioPort usbOutDevice = createPort(c.nextPortId++, "USB Device Out", 0, false, createDeviceExt(AudioDeviceType::OUT_DEVICE, 0, AudioDeviceDescription::CONNECTION_USB)); c.ports.push_back(usbOutDevice); c.connectedProfiles[usbOutDevice.id] = standardPcmAudioProfiles; AudioPort usbOutHeadset = createPort(c.nextPortId++, "USB Headset Out", 0, false, createDeviceExt(AudioDeviceType::OUT_HEADSET, 0, AudioDeviceDescription::CONNECTION_USB)); c.ports.push_back(usbOutHeadset); c.connectedProfiles[usbOutHeadset.id] = standardPcmAudioProfiles; AudioPort usbInDevice = createPort(c.nextPortId++, "USB Device In", 0, true, createDeviceExt(AudioDeviceType::IN_DEVICE, 0, AudioDeviceDescription::CONNECTION_USB)); c.ports.push_back(usbInDevice); c.connectedProfiles[usbInDevice.id] = standardPcmAudioProfiles; AudioPort usbInHeadset = createPort(c.nextPortId++, "USB Headset In", 0, true, createDeviceExt(AudioDeviceType::IN_HEADSET, 0, AudioDeviceDescription::CONNECTION_USB)); c.ports.push_back(usbInHeadset); c.connectedProfiles[usbInHeadset.id] = standardPcmAudioProfiles; // Mix ports AudioPort usbDeviceOutMix = createPort(c.nextPortId++, "usb_device output", 0, false, createPortMixExt(1, 1)); c.ports.push_back(usbDeviceOutMix); AudioPort usbDeviceInMix = createPort(c.nextPortId++, "usb_device input", 0, true, createPortMixExt(0, 1)); c.ports.push_back(usbDeviceInMix); c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutDevice)); c.routes.push_back(createRoute({usbDeviceOutMix}, usbOutHeadset)); c.routes.push_back(createRoute({usbInDevice, usbInHeadset}, usbDeviceInMix)); return c; }(); return std::make_unique(configuration); } // Stub configuration: // // Device ports: // * "Test Out", OUT_AFE_PROXY // - no profiles specified // * "Test In", IN_AFE_PROXY // - no profiles specified // * "Wired Headset", OUT_HEADSET // - no profiles specified // * "Wired Headset Mic", IN_HEADSET // - no profiles specified // // Mix ports: // * "test output", 1 max open, 1 max active stream // - profile PCM 24-bit; MONO, STEREO; 8000, 11025, 16000, 32000, 44100, 48000 // * "test fast output", 1 max open, 1 max active stream // - profile PCM 24-bit; STEREO; 44100, 48000 // * "test compressed offload", DIRECT|COMPRESS_OFFLOAD|NON_BLOCKING, 1 max open, 1 max active // stream // - profile MP3; MONO, STEREO; 44100, 48000 // * "test input", 2 max open, 2 max active streams // - profile PCM 24-bit; MONO, STEREO, FRONT_BACK; // 8000, 11025, 16000, 22050, 32000, 44100, 48000 // // Routes: // "test output", "test fast output", "test compressed offload" -> "Test Out" // "test output" -> "Wired Headset" // "Test In", "Wired Headset Mic" -> "test input" // // Initial port configs: // * "Test Out" device port: PCM 24-bit; STEREO; 48000 // * "Test In" device port: PCM 24-bit; MONO; 48000 // // Profiles for device port connected state (when simulating connections): // * "Wired Headset": dynamic profiles // * "Wired Headset Mic": dynamic profiles // std::unique_ptr getStubConfiguration() { static const Configuration configuration = []() { Configuration c; // Device ports AudioPort testOutDevice = createPort(c.nextPortId++, "Test Out", 0, false, createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)); c.ports.push_back(testOutDevice); c.initialConfigs.push_back( createPortConfig(testOutDevice.id, testOutDevice.id, PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false, createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0))); AudioPort headsetOutDevice = createPort(c.nextPortId++, "Wired Headset", 0, false, createDeviceExt(AudioDeviceType::OUT_HEADSET, 0, AudioDeviceDescription::CONNECTION_ANALOG)); c.ports.push_back(headsetOutDevice); AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true, createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)); c.ports.push_back(testInDevice); c.initialConfigs.push_back( createPortConfig(testInDevice.id, testInDevice.id, PcmType::INT_24_BIT, AudioChannelLayout::LAYOUT_MONO, 48000, 0, true, createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0))); AudioPort headsetInDevice = createPort(c.nextPortId++, "Wired Headset Mic", 0, true, createDeviceExt(AudioDeviceType::IN_HEADSET, 0, AudioDeviceDescription::CONNECTION_ANALOG)); c.ports.push_back(headsetInDevice); // Mix ports AudioPort testOutMix = createPort(c.nextPortId++, "test output", 0, false, createPortMixExt(1, 1)); testOutMix.profiles.push_back( createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO}, {8000, 11025, 16000, 32000, 44100, 48000})); c.ports.push_back(testOutMix); AudioPort testFastOutMix = createPort(c.nextPortId++, "test fast output", makeBitPositionFlagMask({AudioOutputFlags::FAST}), false, createPortMixExt(1, 1)); testFastOutMix.profiles.push_back(createProfile( PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000})); c.ports.push_back(testFastOutMix); AudioPort compressedOffloadOutMix = createPort(c.nextPortId++, "test compressed offload", makeBitPositionFlagMask({AudioOutputFlags::DIRECT, AudioOutputFlags::COMPRESS_OFFLOAD, AudioOutputFlags::NON_BLOCKING}), false, createPortMixExt(1, 1)); compressedOffloadOutMix.profiles.push_back( createProfile(::android::MEDIA_MIMETYPE_AUDIO_MPEG, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000})); c.ports.push_back(compressedOffloadOutMix); AudioPort testInMix = createPort(c.nextPortId++, "test input", 0, true, createPortMixExt(2, 2)); testInMix.profiles.push_back( createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO, AudioChannelLayout::LAYOUT_FRONT_BACK}, {8000, 11025, 16000, 22050, 32000, 44100, 48000})); testInMix.profiles.push_back( createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO, AudioChannelLayout::LAYOUT_FRONT_BACK}, {8000, 11025, 16000, 22050, 32000, 44100, 48000})); c.ports.push_back(testInMix); c.routes.push_back( createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice)); c.routes.push_back(createRoute({testOutMix}, headsetOutDevice)); c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMix)); c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end()); return c; }(); return std::make_unique(configuration); } // Bluetooth configuration: // // Device ports: // * "BT A2DP Out", OUT_DEVICE, CONNECTION_BT_A2DP // - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000 // * "BT A2DP Headphones", OUT_HEADPHONE, CONNECTION_BT_A2DP // - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000 // * "BT A2DP Speaker", OUT_SPEAKER, CONNECTION_BT_A2DP // - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000 // * "BT Hearing Aid Out", OUT_HEARING_AID, CONNECTION_WIRELESS // - no profiles specified // // Mix ports: // * "a2dp output", 1 max open, 1 max active stream // - no profiles specified // * "hearing aid output", 1 max open, 1 max active stream // - profile PCM 16-bit; STEREO; 16000, 24000 // // Routes: // "a2dp output" -> "BT A2DP Out" // "a2dp output" -> "BT A2DP Headphones" // "a2dp output" -> "BT A2DP Speaker" // "hearing aid output" -> "BT Hearing Aid Out" // // Profiles for device port connected state (when simulating connections): // * "BT A2DP Out", "BT A2DP Headphones", "BT A2DP Speaker": // - profile PCM 16-bit; STEREO; 44100, 48000, 88200, 96000 // * "BT Hearing Aid Out": // - profile PCM 16-bit; STEREO; 16000, 24000 // std::unique_ptr getBluetoothConfiguration() { static const Configuration configuration = []() { const std::vector standardPcmAudioProfiles = { createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {44100, 48000, 88200, 96000})}; const std::vector hearingAidAudioProfiles = {createProfile( PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {16000, 24000})}; Configuration c; // Device ports AudioPort btOutDevice = createPort(c.nextPortId++, "BT A2DP Out", 0, false, createDeviceExt(AudioDeviceType::OUT_DEVICE, 0, AudioDeviceDescription::CONNECTION_BT_A2DP)); btOutDevice.profiles.insert(btOutDevice.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(btOutDevice); c.connectedProfiles[btOutDevice.id] = standardPcmAudioProfiles; AudioPort btOutHeadphone = createPort(c.nextPortId++, "BT A2DP Headphones", 0, false, createDeviceExt(AudioDeviceType::OUT_HEADPHONE, 0, AudioDeviceDescription::CONNECTION_BT_A2DP)); btOutHeadphone.profiles.insert(btOutHeadphone.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(btOutHeadphone); c.connectedProfiles[btOutHeadphone.id] = standardPcmAudioProfiles; AudioPort btOutSpeaker = createPort(c.nextPortId++, "BT A2DP Speaker", 0, false, createDeviceExt(AudioDeviceType::OUT_SPEAKER, 0, AudioDeviceDescription::CONNECTION_BT_A2DP)); btOutSpeaker.profiles.insert(btOutSpeaker.profiles.begin(), standardPcmAudioProfiles.begin(), standardPcmAudioProfiles.end()); c.ports.push_back(btOutSpeaker); c.connectedProfiles[btOutSpeaker.id] = standardPcmAudioProfiles; AudioPort btOutHearingAid = createPort(c.nextPortId++, "BT Hearing Aid Out", 0, false, createDeviceExt(AudioDeviceType::OUT_HEARING_AID, 0, AudioDeviceDescription::CONNECTION_WIRELESS)); c.ports.push_back(btOutHearingAid); c.connectedProfiles[btOutHearingAid.id] = hearingAidAudioProfiles; // Mix ports AudioPort btOutMix = createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1)); c.ports.push_back(btOutMix); AudioPort btHearingOutMix = createPort(c.nextPortId++, "hearing aid output", 0, false, createPortMixExt(1, 1)); btHearingOutMix.profiles = hearingAidAudioProfiles; c.ports.push_back(btHearingOutMix); c.routes.push_back(createRoute({btOutMix}, btOutDevice)); c.routes.push_back(createRoute({btOutMix}, btOutHeadphone)); c.routes.push_back(createRoute({btOutMix}, btOutSpeaker)); c.routes.push_back(createRoute({btHearingOutMix}, btOutHearingAid)); return c; }(); return std::make_unique(configuration); } std::unique_ptr getConfiguration(Module::Type moduleType) { switch (moduleType) { case Module::Type::DEFAULT: return getPrimaryConfiguration(); case Module::Type::R_SUBMIX: return getRSubmixConfiguration(); case Module::Type::STUB: return getStubConfiguration(); case Module::Type::USB: return getUsbConfiguration(); case Module::Type::BLUETOOTH: return getBluetoothConfiguration(); } } } // namespace aidl::android::hardware::audio::core::internal