blob: aefe8ed3b5cb08f24fb7787ff9703044e4c9af07 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "DeviceHalAidl"
Vlad Popa03bd5bc2023-01-17 16:16:51 +010018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganovf56ce782023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovb0c55252023-02-08 16:59:41 -080023#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
24#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000025#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
David Li9cf5e622023-03-21 00:51:10 +080026#include <android/binder_enums.h>
27#include <binder/Enums.h>
Mikhail Naganovfab697c2023-01-11 19:33:13 +000028#include <error/expected_utils.h>
29#include <media/AidlConversionCppNdk.h>
30#include <media/AidlConversionUtil.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000031#include <mediautils/TimeCheck.h>
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080032#include <Utils.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000033#include <utils/Log.h>
Shunkai Yao51202502022-12-12 06:11:46 +000034
Mikhail Naganov31d46652023-01-10 18:29:25 +000035#include "DeviceHalAidl.h"
36#include "StreamHalAidl.h"
37
Mikhail Naganovfab697c2023-01-11 19:33:13 +000038using aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070039using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080040using aidl::android::media::audio::common::AudioConfig;
41using aidl::android::media::audio::common::AudioDevice;
David Li9cf5e622023-03-21 00:51:10 +080042using aidl::android::media::audio::common::AudioDeviceAddress;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080043using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070044using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080045using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080046using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovb0c55252023-02-08 16:59:41 -080047using aidl::android::media::audio::common::AudioLatencyMode;
David Li9cf5e622023-03-21 00:51:10 +080048using aidl::android::media::audio::common::AudioMMapPolicy;
49using aidl::android::media::audio::common::AudioMMapPolicyInfo;
50using aidl::android::media::audio::common::AudioMMapPolicyType;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000051using aidl::android::media::audio::common::AudioMode;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080052using aidl::android::media::audio::common::AudioOutputFlags;
53using aidl::android::media::audio::common::AudioPort;
54using aidl::android::media::audio::common::AudioPortConfig;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -080055using aidl::android::media::audio::common::AudioPortDeviceExt;
David Li9cf5e622023-03-21 00:51:10 +080056using aidl::android::media::audio::common::AudioPortExt;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -080057using aidl::android::media::audio::common::AudioPortMixExt;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -080058using aidl::android::media::audio::common::AudioPortMixExtUseCase;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070059using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080060using aidl::android::media::audio::common::AudioSource;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000061using aidl::android::media::audio::common::Float;
David Li9cf5e622023-03-21 00:51:10 +080062using aidl::android::media::audio::common::Int;
63using aidl::android::media::audio::common::MicrophoneDynamicInfo;
64using aidl::android::media::audio::common::MicrophoneInfo;
Mikhail Naganov6352e822023-03-09 18:22:36 -080065using aidl::android::hardware::audio::common::getFrameSizeInBytes;
66using aidl::android::hardware::audio::common::isBitPositionFlagSet;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070067using aidl::android::hardware::audio::common::isDefaultAudioFormat;
Mikhail Naganov6352e822023-03-09 18:22:36 -080068using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
Mikhail Naganovf56ce782023-01-25 11:29:11 -080069using aidl::android::hardware::audio::common::RecordTrackMetadata;
70using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganovecfafb72023-03-29 10:06:15 -070071using aidl::android::hardware::audio::core::AudioRoute;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000072using aidl::android::hardware::audio::core::IModule;
73using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070074using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000075using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000076
77namespace android {
78
Mikhail Naganovf56ce782023-01-25 11:29:11 -080079namespace {
80
81bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
82 return portConfig.sampleRate.value().value == config.base.sampleRate &&
83 portConfig.channelMask.value() == config.base.channelMask &&
84 portConfig.format.value() == config.base.format;
85}
86
87void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
88 config->base.sampleRate = portConfig.sampleRate.value().value;
89 config->base.channelMask = portConfig.channelMask.value();
90 config->base.format = portConfig.format.value();
91}
92
93void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
94 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
95 portConfig->channelMask = config.base.channelMask;
96 portConfig->format = config.base.format;
97}
98
David Li9cf5e622023-03-21 00:51:10 +080099template<typename OutEnum, typename OutEnumRange, typename InEnum>
100ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
101 using InIntType = std::underlying_type_t<InEnum>;
102 static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
103
104 InIntType inEnumIndex = static_cast<InIntType>(e);
105 OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
106 if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
107 return ::android::base::unexpected(BAD_VALUE);
108 }
109 return outEnum;
110}
111
112template<typename NdkEnum, typename CppEnum>
113ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
114 return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
115}
116
117template<typename CppEnum, typename NdkEnum>
118ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
119 return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
120}
121
122ConversionResult<android::media::audio::common::AudioDeviceAddress>
123ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
124 using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
125 using NdkTag = AudioDeviceAddress::Tag;
126
127 CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
128
129 switch (cppTag) {
130 case CppTag::id:
131 return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
132 ndk.get<NdkTag::id>());
133 case CppTag::mac:
134 return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
135 ndk.get<NdkTag::mac>());
136 case CppTag::ipv4:
137 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
138 ndk.get<NdkTag::ipv4>());
139 case CppTag::ipv6:
140 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
141 ndk.get<NdkTag::ipv6>());
142 case CppTag::alsa:
143 return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
144 ndk.get<NdkTag::alsa>());
145 }
146
147 return ::android::base::unexpected(BAD_VALUE);
148}
149
150ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
151 media::audio::common::AudioDevice cpp;
152 cpp.type.type = VALUE_OR_RETURN(
153 ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
154 cpp.type.connection = ndk.type.connection;
155 cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
156 return cpp;
157}
158
159ConversionResult<media::audio::common::AudioMMapPolicyInfo>
160ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
161 media::audio::common::AudioMMapPolicyInfo cpp;
162 cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
163 cpp.mmapPolicy = VALUE_OR_RETURN(
164 ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
165 return cpp;
166}
167
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800168} // namespace
169
Mikhail Naganov31d46652023-01-10 18:29:25 +0000170status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
171 // Obsolete.
172 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000173}
174
175status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800176 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000177 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800178 std::vector<AudioPort> ports;
179 RETURN_STATUS_IF_ERROR(
180 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
181 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
182 __func__, mInstance.c_str());
183 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
184 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800185 mDefaultInputPortId = mDefaultOutputPortId = -1;
186 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
187 for (const auto& pair : mPorts) {
188 const auto& p = pair.second;
189 if (p.ext.getTag() == AudioPortExt::Tag::device &&
190 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
191 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
192 mDefaultInputPortId = p.id;
193 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
194 mDefaultOutputPortId = p.id;
195 }
196 }
197 }
198 ALOGI("%s: module %s default port ids: input %d, output %d",
199 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700200 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800201 std::vector<AudioPortConfig> portConfigs;
202 RETURN_STATUS_IF_ERROR(
203 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
204 std::transform(portConfigs.begin(), portConfigs.end(),
205 std::inserter(mPortConfigs, mPortConfigs.end()),
206 [](const auto& p) { return std::make_pair(p.id, p); });
jiabin2248fa12023-04-27 22:04:16 +0000207 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
208 std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
209 [](const auto& pcPair) { return pcPair.first; });
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800210 std::vector<AudioPatch> patches;
211 RETURN_STATUS_IF_ERROR(
212 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
213 std::transform(patches.begin(), patches.end(),
214 std::inserter(mPatches, mPatches.end()),
215 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000216 return OK;
217}
218
219status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000220 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000221 if (!mModule) return NO_INIT;
222 std::shared_ptr<ITelephony> telephony;
223 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
224 status.isOk() && telephony != nullptr) {
225 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
226 RETURN_STATUS_IF_ERROR(
227 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
228 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
229 "%s: the resulting voice volume %f is not the same as requested %f",
230 __func__, outConfig.voiceVolume.value().value, volume);
231 }
232 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000233}
234
235status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000236 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000237 if (!mModule) return NO_INIT;
238 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000239}
240
241status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000242 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000243 if (!mModule) return NO_INIT;
244 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000245}
246
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000247status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248 TIME_CHECK();
249 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000250 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
251 std::shared_ptr<ITelephony> telephony;
252 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
253 status.isOk() && telephony != nullptr) {
254 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
255 }
256 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000257}
258
259status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000260 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000261 if (!mModule) return NO_INIT;
262 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000263}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000264
Shunkai Yao51202502022-12-12 06:11:46 +0000265status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000266 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000267 if (!mModule) return NO_INIT;
268 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000269}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000270
Shunkai Yao51202502022-12-12 06:11:46 +0000271status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000272 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000273 if (!mModule) return NO_INIT;
274 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000275}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000276
Shunkai Yao51202502022-12-12 06:11:46 +0000277status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000278 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000279 if (!mModule) return NO_INIT;
280 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000281}
282
Mikhail Naganov31d46652023-01-10 18:29:25 +0000283status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
284 TIME_CHECK();
285 if (!mModule) return NO_INIT;
286 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000287 return OK;
288}
289
Mikhail Naganov31d46652023-01-10 18:29:25 +0000290status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
291 TIME_CHECK();
292 values->clear();
293 if (!mModule) return NO_INIT;
294 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000295 return OK;
296}
297
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800298namespace {
299
300class Cleanup {
301 public:
302 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
303
304 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
305 mDevice(device), mCleaner(cleaner), mId(id) {}
306 ~Cleanup() { clean(); }
307 void clean() {
308 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
309 disarm();
310 }
311 void disarm() { mDevice = nullptr; }
312
313 private:
314 DeviceHalAidl* mDevice;
315 const Cleaner mCleaner;
316 const int32_t mId;
317};
318
319} // namespace
320
321// Since the order of container elements destruction is unspecified,
322// ensure that cleanups are performed from the most recent one and upwards.
323// This is the same as if there were individual Cleanup instances on the stack,
324// however the bonus is that we can disarm all of them with just one statement.
325class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
326 public:
327 ~Cleanups() { for (auto& c : *this) c.clean(); }
328 void disarmAll() { for (auto& c : *this) c.disarm(); }
329};
330
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800331status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
332 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
333 if (size == nullptr) return BAD_VALUE;
334 TIME_CHECK();
335 if (!mModule) return NO_INIT;
336 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
337 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
338 AudioDevice aidlDevice;
339 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800340 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800341 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
342 AudioPortConfig mixPortConfig;
343 Cleanups cleanups;
344 audio_config writableConfig = *config;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700345 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800346 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700347 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800348 *size = aidlConfig.frameCount *
349 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
350 // Do not disarm cleanups to release temporary port configs.
351 return OK;
352}
353
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800354status_t DeviceHalAidl::prepareToOpenStream(
355 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800356 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800357 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700358 AudioPatch* aidlPatch) {
359 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
360 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
361 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
362 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
jiabin2248fa12023-04-27 22:04:16 +0000363 resetUnusedPatchesAndPortConfigs();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800364 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
365 // Find / create AudioPortConfigs for the device port and the mix port,
366 // then find / create a patch between them, and open a stream on the mix port.
367 AudioPortConfig devicePortConfig;
368 bool created = false;
jiabin2248fa12023-04-27 22:04:16 +0000369 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
370 &devicePortConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800371 if (created) {
372 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
373 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800374 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700375 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800376 if (created) {
377 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
378 }
379 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800380 if (isInput) {
381 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700382 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800383 } else {
384 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700385 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800386 }
387 if (created) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700388 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800389 }
390 if (aidlConfig->frameCount <= 0) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700391 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800392 }
393 *config = VALUE_OR_RETURN_STATUS(
394 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
395 return OK;
396}
397
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800398namespace {
399
400class StreamCallbackBase {
401 protected:
402 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
403 public:
404 void* getCookie() const { return mCookie; }
405 void setCookie(void* cookie) { mCookie = cookie; }
406 sp<CallbackBroker> getBroker() const {
407 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
408 return nullptr;
409 }
410 private:
411 const wp<CallbackBroker> mBroker;
412 std::atomic<void*> mCookie;
413};
414
415template<class C>
416class StreamCallbackBaseHelper {
417 protected:
418 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
419 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
420 using CbRef = const sp<C>&;
421 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
422 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
423 return ndk::ScopedAStatus::ok();
424 }
425 private:
426 const StreamCallbackBase& mBase;
427};
428
429template<>
430sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
431 const sp<CallbackBroker>& broker, void* cookie) {
432 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
433 return nullptr;
434}
435
436template<>
437sp<StreamOutHalInterfaceEventCallback>
438StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
439 const sp<CallbackBroker>& broker, void* cookie) {
440 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
441 return nullptr;
442}
443
444template<>
445sp<StreamOutHalInterfaceLatencyModeCallback>
446StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
447 const sp<CallbackBroker>& broker, void* cookie) {
448 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
449 return nullptr;
450}
451
452/*
453Note on the callback ownership.
454
455In the Binder ownership model, the server implementation is kept alive
456as long as there is any client (proxy object) alive. This is done by
457incrementing the refcount of the server-side object by the Binder framework.
458When it detects that the last client is gone, it decrements the refcount back.
459
460Thus, it is not needed to keep any references to StreamCallback on our
461side (after we have sent an instance to the client), because we are
462the server-side. The callback object will be kept alive as long as the HAL server
463holds a strong ref to IStreamCallback proxy.
464*/
465
466class OutputStreamCallbackAidl : public StreamCallbackBase,
467 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
468 public ::aidl::android::hardware::audio::core::BnStreamCallback {
469 public:
470 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
471 : StreamCallbackBase(broker),
472 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
473 *static_cast<StreamCallbackBase*>(this)) {}
474 ndk::ScopedAStatus onTransferReady() override {
475 return runCb([](CbRef cb) { cb->onWriteReady(); });
476 }
477 ndk::ScopedAStatus onError() override {
478 return runCb([](CbRef cb) { cb->onError(); });
479 }
480 ndk::ScopedAStatus onDrainReady() override {
481 return runCb([](CbRef cb) { cb->onDrainReady(); });
482 }
483};
484
485class OutputStreamEventCallbackAidl :
486 public StreamCallbackBase,
487 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
488 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
489 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
490 public:
491 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
492 : StreamCallbackBase(broker),
493 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
494 *static_cast<StreamCallbackBase*>(this)),
495 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
496 *static_cast<StreamCallbackBase*>(this)) {}
497 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
498 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
499 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
500 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
501 }
502 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
503 const std::vector<AudioLatencyMode>& in_modes) override {
504 auto halModes = VALUE_OR_FATAL(
505 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
506 in_modes,
507 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
508 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
509 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
510 }
511};
512
513} // namespace
514
Mikhail Naganov31d46652023-01-10 18:29:25 +0000515status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800516 audio_io_handle_t handle, audio_devices_t devices,
517 audio_output_flags_t flags, struct audio_config* config,
518 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000519 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800520 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000521 if (!outStream || !config) {
522 return BAD_VALUE;
523 }
524 TIME_CHECK();
525 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800526 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
527 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
528 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
529 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
530 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
531 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
532 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
533 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
534 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
535 AudioPortConfig mixPortConfig;
536 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700537 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800538 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
539 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700540 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800541 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
542 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800543 const bool isOffload = isBitPositionFlagSet(
544 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
545 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
546 if (isOffload) {
547 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
548 }
549 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
550 if (isOffload) {
551 args.offloadInfo = aidlConfig.offloadInfo;
552 args.callback = streamCb;
553 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800554 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800555 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800556 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
557 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800558 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800559 if (!context.isValid()) {
560 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
561 __func__, ret.desc.toString().c_str());
562 return NO_INIT;
563 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700564 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800565 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700566 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800567 void* cbCookie = (*outStream).get();
568 {
569 std::lock_guard l(mLock);
570 mCallbacks.emplace(cbCookie, Callbacks{});
571 }
572 if (streamCb) streamCb->setCookie(cbCookie);
573 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800574 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000575 return OK;
576}
577
Mikhail Naganov31d46652023-01-10 18:29:25 +0000578status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800579 audio_io_handle_t handle, audio_devices_t devices,
580 struct audio_config* config, audio_input_flags_t flags,
581 const char* address, audio_source_t source,
582 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000583 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800584 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000585 if (!inStream || !config) {
586 return BAD_VALUE;
587 }
588 TIME_CHECK();
589 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800590 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
591 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
592 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
593 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
594 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
595 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
596 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
597 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
598 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
599 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
600 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
601 AudioPortConfig mixPortConfig;
602 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700603 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800604 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700605 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800606 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
607 args.portConfigId = mixPortConfig.id;
608 RecordTrackMetadata aidlTrackMetadata{
609 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
610 if (outputDevice != AUDIO_DEVICE_NONE) {
611 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
612 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
613 outputDevice, outputDeviceAddress));
614 }
615 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
616 args.bufferSizeFrames = aidlConfig.frameCount;
617 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
618 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800619 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800620 if (!context.isValid()) {
621 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
622 __func__, ret.desc.toString().c_str());
623 return NO_INIT;
624 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700625 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800626 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700627 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800628 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000629 return OK;
630}
631
632status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
633 *supportsPatches = true;
634 return OK;
635}
636
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800637status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
638 const struct audio_port_config* sources,
639 unsigned int num_sinks,
640 const struct audio_port_config* sinks,
641 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800642 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000643 TIME_CHECK();
644 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800645 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
646 sources == nullptr || sinks == nullptr || patch == nullptr) {
647 return BAD_VALUE;
648 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800649 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
650 // the framework wants to create a new patch. The handle has to be generated
651 // by the HAL. Since handles generated this way can only be unique within
652 // a HAL module, the framework generates a globally unique handle, and maps
653 // it on the <HAL module, patch handle> pair.
654 // When the patch handle is set, it meant the framework intends to update
655 // an existing patch.
656 //
657 // This behavior corresponds to HAL module behavior, with the only difference
658 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
659 // that both the framework and the HAL use the same value for "no ID":
660 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
661 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800662
663 // Upon conversion, mix port configs contain audio configuration, while
664 // device port configs contain device address. This data is used to find
665 // or create HAL configs.
666 std::vector<AudioPortConfig> aidlSources, aidlSinks;
667 for (unsigned int i = 0; i < num_sources; ++i) {
668 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
669 sources[i].role, sources[i].type)) ==
670 ::aidl::android::AudioPortDirection::INPUT;
671 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
672 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
673 sources[i], isInput, 0)));
674 }
675 for (unsigned int i = 0; i < num_sinks; ++i) {
676 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
677 sinks[i].role, sinks[i].type)) ==
678 ::aidl::android::AudioPortDirection::INPUT;
679 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
680 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
681 sinks[i], isInput, 0)));
682 }
683 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800684 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800685 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800686 if (existingPatchIt != mPatches.end()) {
687 aidlPatch = existingPatchIt->second;
688 aidlPatch.sourcePortConfigIds.clear();
689 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800690 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800691 ALOGD("%s: sources: %s, sinks: %s",
692 __func__, ::android::internal::ToString(aidlSources).c_str(),
693 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800694 auto fillPortConfigs = [&](
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700695 const std::vector<AudioPortConfig>& configs,
696 const std::set<int32_t>& destinationPortIds,
697 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800698 for (const auto& s : configs) {
699 AudioPortConfig portConfig;
700 bool created = false;
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700701 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
702 s, destinationPortIds, &portConfig, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800703 if (created) {
704 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
705 }
706 ids->push_back(portConfig.id);
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700707 if (portIds != nullptr) {
708 portIds->insert(portConfig.portId);
709 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800710 }
711 return OK;
712 };
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700713 // When looking up port configs, the destinationPortId is only used for mix ports.
714 // Thus, we process device port configs first, and look up the destination port ID from them.
715 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
716 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
717 const std::vector<AudioPortConfig>& devicePortConfigs =
718 sourceIsDevice ? aidlSources : aidlSinks;
719 std::vector<int32_t>* devicePortConfigIds =
720 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
721 const std::vector<AudioPortConfig>& mixPortConfigs =
722 sourceIsDevice ? aidlSinks : aidlSources;
723 std::vector<int32_t>* mixPortConfigIds =
724 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
725 std::set<int32_t> devicePortIds;
726 RETURN_STATUS_IF_ERROR(fillPortConfigs(
727 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
728 RETURN_STATUS_IF_ERROR(fillPortConfigs(
729 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800730 if (existingPatchIt != mPatches.end()) {
731 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
732 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
733 existingPatchIt->second = aidlPatch;
734 } else {
735 bool created = false;
736 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
737 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800738 halPatchId = aidlPatch.id;
739 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800740 }
741 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000742 return OK;
743}
744
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800745status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800746 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000747 TIME_CHECK();
748 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800749 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
750 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800751 return BAD_VALUE;
752 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800753 int32_t halPatchId = static_cast<int32_t>(patch);
754 auto patchIt = mPatches.find(halPatchId);
755 if (patchIt == mPatches.end()) {
756 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
757 return BAD_VALUE;
758 }
759 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
760 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000761 return OK;
762}
763
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700764status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
765 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000766 TIME_CHECK();
767 if (!mModule) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700768 if (port == nullptr) {
769 return BAD_VALUE;
770 }
771 audio_port_v7 portV7;
772 audio_populate_audio_port_v7(port, &portV7);
773 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
774 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
775}
776
777status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
778 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
779 TIME_CHECK();
780 if (!mModule) return NO_INIT;
781 if (port == nullptr) {
782 return BAD_VALUE;
783 }
784 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
785 ::aidl::android::AudioPortDirection::INPUT;
786 auto aidlPort = VALUE_OR_RETURN_STATUS(
787 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
788 if (aidlPort.ext.getTag() != AudioPortExt::device) {
789 ALOGE("%s: provided port is not a device port (module %s): %s",
790 __func__, mInstance.c_str(), aidlPort.toString().c_str());
791 return BAD_VALUE;
792 }
793 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
794 // It seems that we don't have to call HAL since all valid ports have been added either
795 // during initialization, or while handling connection of an external device.
796 auto portsIt = findPort(matchDevice);
797 if (portsIt == mPorts.end()) {
798 ALOGE("%s: device port for device %s is not found in the module %s",
799 __func__, matchDevice.toString().c_str(), mInstance.c_str());
800 return BAD_VALUE;
801 }
802 const int32_t fwkId = aidlPort.id;
803 aidlPort = portsIt->second;
804 aidlPort.id = fwkId;
805 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
806 aidlPort, isInput));
807 return OK;
808}
809
810status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
811 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
812 TIME_CHECK();
813 if (!mModule) return NO_INIT;
814 if (config == nullptr) {
815 return BAD_VALUE;
816 }
817 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
818 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
819 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
820 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
821 *config, isInput, 0 /*portId*/));
822 AudioPortConfig portConfig;
823 bool created = false;
Mikhail Naganovecfafb72023-03-29 10:06:15 -0700824 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
825 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000826 return OK;
827}
828
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800829MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
830 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
831 TIME_CHECK();
832 std::vector<MicrophoneInfo> aidlInfo;
833 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
834 if (status == OK) {
835 mMicrophones.status = Microphones::Status::QUERIED;
836 mMicrophones.info = std::move(aidlInfo);
837 } else if (status == INVALID_OPERATION) {
838 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
839 } else {
840 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
841 return {};
842 }
843 }
844 if (mMicrophones.status == Microphones::Status::QUERIED) {
845 return &mMicrophones.info;
846 }
847 return {}; // NOT_SUPPORTED
848}
849
Shunkai Yao51202502022-12-12 06:11:46 +0000850status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800851 std::vector<audio_microphone_characteristic_t>* microphones) {
852 if (!microphones) {
853 return BAD_VALUE;
854 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000855 TIME_CHECK();
856 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800857 auto staticInfo = getMicrophoneInfo();
858 if (!staticInfo) return INVALID_OPERATION;
859 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
860 emptyDynamicInfo.reserve(staticInfo->size());
861 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
862 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
863 *microphones = VALUE_OR_RETURN_STATUS(
864 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
865 *staticInfo, emptyDynamicInfo,
866 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
867 );
Shunkai Yao51202502022-12-12 06:11:46 +0000868 return OK;
869}
870
Mikhail Naganov31d46652023-01-10 18:29:25 +0000871status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
872 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000873 if (!effect) {
874 return BAD_VALUE;
875 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000876 TIME_CHECK();
877 if (!mModule) return NO_INIT;
878 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000879 return OK;
880}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000881status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000882 sp<EffectHalInterface> effect) {
883 if (!effect) {
884 return BAD_VALUE;
885 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000886 TIME_CHECK();
887 if (!mModule) return NO_INIT;
888 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000889 return OK;
890}
891
892status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800893 media::audio::common::AudioMMapPolicyType policyType,
894 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800896 AudioMMapPolicyType mmapPolicyType =
897 VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
898
899 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
900
901 if (status_t status = statusTFromBinderStatus(
902 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
903 return status;
904 }
905
906 *policyInfos = VALUE_OR_RETURN_STATUS(
907 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
908 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000909 return OK;
910}
911
912int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000913 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800914 int32_t mixerBurstCount = 0;
915 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
916 return mixerBurstCount;
917 }
918 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000919}
920
921int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000922 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800923 int32_t hardwareBurstMinUsec = 0;
924 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
925 return hardwareBurstMinUsec;
926 }
927 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000928}
929
930error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000931 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700932 if (!mModule) return NO_INIT;
933 int32_t aidlHwAvSync;
934 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
935 return VALUE_OR_RETURN_STATUS(
936 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000937}
938
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000939status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
940 TIME_CHECK();
941 if (!mModule) return NO_INIT;
942 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800943}
Shunkai Yao51202502022-12-12 06:11:46 +0000944
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700945int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000946 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700947 if (!mModule) return NO_INIT;
948 if (supports == nullptr) {
949 return BAD_VALUE;
950 }
951 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000952}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000953
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100954status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
955 ::ndk::SpAIBinder* soundDoseBinder) {
956 TIME_CHECK();
957 if (!mModule) return NO_INIT;
958 if (mSoundDose == nullptr) {
959 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
960 if (!status.isOk()) {
961 ALOGE("%s failed to return the sound dose interface for module %s: %s",
962 __func__,
963 module.c_str(),
964 status.getDescription().c_str());
965 return BAD_VALUE;
966 }
967 }
968 *soundDoseBinder = mSoundDose->asBinder();
969 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
970
971 return OK;
972}
973
jiabinc0048632023-04-27 22:04:31 +0000974status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
975 // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
976 // Call `setConnectedState` instead.
977 // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
978 const status_t status = setConnectedState(port, false /*connected*/);
979 if (status == NO_ERROR) {
980 mDeviceDisconnectionNotified.insert(port->id);
981 }
982 return status;
983}
984
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700985status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
986 TIME_CHECK();
987 if (!mModule) return NO_INIT;
988 if (port == nullptr) {
989 return BAD_VALUE;
990 }
jiabinc0048632023-04-27 22:04:31 +0000991 if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
992 // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
993 // and then call `setConnectedState`. However, there is no API for
994 // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
995 // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
996 // previous call is successful. Also remove the cache here to avoid a large cache after
997 // a long run.
998 return NO_ERROR;
999 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001000 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
1001 ::aidl::android::AudioPortDirection::INPUT;
1002 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
1003 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
1004 if (aidlPort.ext.getTag() != AudioPortExt::device) {
1005 ALOGE("%s: provided port is not a device port (module %s): %s",
1006 __func__, mInstance.c_str(), aidlPort.toString().c_str());
1007 return BAD_VALUE;
1008 }
1009 if (connected) {
1010 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1011 // Reset the device address to find the "template" port.
1012 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
1013 auto portsIt = findPort(matchDevice);
1014 if (portsIt == mPorts.end()) {
1015 ALOGW("%s: device port for device %s is not found in the module %s",
1016 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1017 return BAD_VALUE;
1018 }
1019 // Use the ID of the "template" port, use all the information from the provided port.
1020 aidlPort.id = portsIt->first;
1021 AudioPort connectedPort;
1022 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
1023 aidlPort, &connectedPort)));
1024 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
1025 LOG_ALWAYS_FATAL_IF(!inserted,
1026 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
1027 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
1028 it->second.toString().c_str());
1029 } else { // !connected
1030 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
1031 auto portsIt = findPort(matchDevice);
1032 if (portsIt == mPorts.end()) {
1033 ALOGW("%s: device port for device %s is not found in the module %s",
1034 __func__, matchDevice.toString().c_str(), mInstance.c_str());
1035 return BAD_VALUE;
1036 }
1037 // Any streams opened on the external device must be closed by this time,
1038 // thus we can clean up patches and port configs that were created for them.
1039 resetUnusedPatchesAndPortConfigs();
1040 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
1041 portsIt->second.id)));
1042 mPorts.erase(portsIt);
1043 }
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001044 return updateRoutes();
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001045}
1046
1047status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1048 TIME_CHECK();
1049 if (!mModule) return NO_INIT;
1050 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1051 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1052 // This is important to log as it affects HAL behavior.
1053 if (status == OK) {
1054 ALOGI("%s: set enabled: %d", __func__, enabled);
1055 } else {
1056 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1057 }
1058 return status;
1059}
1060
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001061bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1062 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1063 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1064}
1065
1066bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1067 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1068 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1069 return p.portId == mDefaultInputPortId;
1070 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1071 return p.portId == mDefaultOutputPortId;
1072 }
1073 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1074}
1075
David Lia8f1e582023-03-30 21:08:06 +08001076status_t DeviceHalAidl::createOrUpdatePortConfig(
1077 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001078 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001079 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001080 bool applied = false;
1081 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001082 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001083 if (!applied) {
1084 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001085 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001086 if (!applied) {
1087 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001088 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001089 return NO_INIT;
1090 }
1091 }
David Lia8f1e582023-03-30 21:08:06 +08001092
1093 int32_t id = appliedPortConfig.id;
1094 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1095 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1096 requestedPortConfig.id, id);
1097 }
1098
1099 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1100 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001101 *result = it;
David Lia8f1e582023-03-30 21:08:06 +08001102 *created = inserted;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001103 return OK;
1104}
1105
1106status_t DeviceHalAidl::findOrCreatePatch(
1107 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1108 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1109 requestedPatch.sourcePortConfigIds.end());
1110 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1111 requestedPatch.sinkPortConfigIds.end());
1112 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1113}
1114
1115status_t DeviceHalAidl::findOrCreatePatch(
1116 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1117 AudioPatch* patch, bool* created) {
1118 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1119 if (patchIt == mPatches.end()) {
1120 TIME_CHECK();
1121 AudioPatch requestedPatch, appliedPatch;
1122 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1123 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1124 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1125 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1126 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1127 requestedPatch, &appliedPatch)));
1128 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1129 *created = true;
1130 } else {
1131 *created = false;
1132 }
1133 *patch = patchIt->second;
1134 return OK;
1135}
1136
jiabin2248fa12023-04-27 22:04:16 +00001137status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001138 AudioPortConfig* portConfig, bool* created) {
1139 auto portConfigIt = findPortConfig(device);
1140 if (portConfigIt == mPortConfigs.end()) {
1141 auto portsIt = findPort(device);
1142 if (portsIt == mPorts.end()) {
1143 ALOGE("%s: device port for device %s is not found in the module %s",
1144 __func__, device.toString().c_str(), mInstance.c_str());
1145 return BAD_VALUE;
1146 }
1147 AudioPortConfig requestedPortConfig;
1148 requestedPortConfig.portId = portsIt->first;
jiabin2248fa12023-04-27 22:04:16 +00001149 if (config != nullptr) {
1150 setPortConfigFromConfig(&requestedPortConfig, *config);
1151 }
David Lia8f1e582023-03-30 21:08:06 +08001152 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1153 created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001154 } else {
1155 *created = false;
1156 }
1157 *portConfig = portConfigIt->second;
1158 return OK;
1159}
1160
1161status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001162 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001163 AudioSource source, const std::set<int32_t>& destinationPortIds,
1164 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001165 // These flags get removed one by one in this order when retrying port finding.
1166 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1167 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001168 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001169 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001170 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1171 AudioIoFlags matchFlags = flags.value();
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001172 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001173 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1174 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1175 if (!isBitPositionFlagSet(
1176 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1177 ++optionalInputFlagsIt;
1178 continue;
1179 }
1180 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1181 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001182 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001183 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1184 "retried with flags %s", __func__, config.toString().c_str(),
1185 flags.value().toString().c_str(), mInstance.c_str(),
1186 matchFlags.toString().c_str());
1187 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001188 if (portsIt == mPorts.end()) {
1189 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001190 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001191 mInstance.c_str());
1192 return BAD_VALUE;
1193 }
1194 AudioPortConfig requestedPortConfig;
1195 requestedPortConfig.portId = portsIt->first;
1196 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001197 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001198 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1199 && source != AudioSource::SYS_RESERVED_INVALID) {
1200 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1201 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1202 }
David Lia8f1e582023-03-30 21:08:06 +08001203 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1204 created));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001205 } else if (!flags.has_value()) {
1206 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1207 "and was not created as flags are not specified",
1208 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1209 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001210 } else {
David Lia8f1e582023-03-30 21:08:06 +08001211 AudioPortConfig requestedPortConfig = portConfigIt->second;
1212 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1213 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1214 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1215 source != AudioSource::SYS_RESERVED_INVALID) {
1216 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1217 }
1218 }
1219
1220 if (requestedPortConfig != portConfigIt->second) {
1221 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1222 created));
1223 } else {
1224 *created = false;
1225 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001226 }
1227 *portConfig = portConfigIt->second;
1228 return OK;
1229}
1230
1231status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001232 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1233 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001234 using Tag = AudioPortExt::Tag;
1235 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1236 if (const auto& p = requestedPortConfig;
1237 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001238 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001239 ALOGW("%s: provided mix port config is not fully specified: %s",
1240 __func__, p.toString().c_str());
1241 return BAD_VALUE;
1242 }
1243 AudioConfig config;
1244 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001245 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1246 AudioPortMixExtUseCase::Tag::source ?
1247 requestedPortConfig.ext.get<Tag::mix>().usecase.
1248 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001249 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001250 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1251 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001252 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1253 return findOrCreatePortConfig(
jiabin2248fa12023-04-27 22:04:16 +00001254 requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
1255 portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001256 }
1257 ALOGW("%s: unsupported audio port config: %s",
1258 __func__, requestedPortConfig.toString().c_str());
1259 return BAD_VALUE;
1260}
1261
1262DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1263 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1264 return std::find_if(mPatches.begin(), mPatches.end(),
1265 [&](const auto& pair) {
1266 const auto& p = pair.second;
1267 std::set<int32_t> patchSrcs(
1268 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1269 std::set<int32_t> patchSinks(
1270 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1271 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1272}
1273
1274DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001275 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1276 return mPorts.find(mDefaultInputPortId);
1277 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1278 return mPorts.find(mDefaultOutputPortId);
1279 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001280 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001281 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001282}
1283
1284DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001285 const AudioConfig& config, const AudioIoFlags& flags,
1286 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001287 auto belongsToProfile = [&config](const AudioProfile& prof) {
1288 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1289 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1290 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1291 config.base.channelMask) != prof.channelMasks.end()) &&
1292 (config.base.sampleRate == 0 ||
1293 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1294 config.base.sampleRate) != prof.sampleRates.end());
1295 };
jiabin2248fa12023-04-27 22:04:16 +00001296 static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
1297 int optionalFlags = 0;
1298 auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
1299 // Ports should be able to match if the optional flags are not requested.
1300 return portFlags == flags ||
1301 (portFlags.getTag() == AudioIoFlags::Tag::output &&
1302 AudioIoFlags::make<AudioIoFlags::Tag::output>(
1303 portFlags.get<AudioIoFlags::Tag::output>() &
1304 ~optionalFlags) == flags);
1305 };
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001306 auto matcher = [&](const auto& pair) {
1307 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001308 return p.ext.getTag() == AudioPortExt::Tag::mix &&
jiabin2248fa12023-04-27 22:04:16 +00001309 flagMatches(p.flags) &&
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001310 (destinationPortIds.empty() ||
1311 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1312 [&](const int32_t destId) { return mRoutingMatrix.count(
1313 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001314 (p.profiles.empty() ||
1315 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1316 p.profiles.end()); };
jiabin2248fa12023-04-27 22:04:16 +00001317 auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1318 if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
1319 auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
1320 while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
1321 if (isBitPositionFlagSet(
1322 flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
1323 // If the flag is set by the request, it must be matched.
1324 ++optionalOutputFlagsIt;
1325 continue;
1326 }
1327 optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
1328 result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
1329 ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
1330 "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
1331 flags.toString().c_str(), mInstance.c_str(), optionalFlags);
1332 }
1333 }
1334 return result;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001335}
1336
1337DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001338 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001339 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001340}
1341
1342DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001343 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001344 using Tag = AudioPortExt::Tag;
1345 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1346 [&](const auto& pair) {
1347 const auto& p = pair.second;
1348 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1349 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1350 !p.format.has_value() || !p.flags.has_value(),
1351 "%s: stored mix port config is not fully specified: %s",
1352 __func__, p.toString().c_str());
1353 return p.ext.getTag() == Tag::mix &&
1354 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001355 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001356 p.ext.template get<Tag::mix>().handle == ioHandle; });
1357}
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001358
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001359void DeviceHalAidl::resetPatch(int32_t patchId) {
1360 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1361 mPatches.erase(it);
1362 TIME_CHECK();
1363 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1364 ALOGE("%s: error while resetting patch %d: %s",
1365 __func__, patchId, status.getDescription().c_str());
1366 }
1367 return;
1368 }
1369 ALOGE("%s: patch id %d not found", __func__, patchId);
1370}
1371
1372void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1373 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1374 mPortConfigs.erase(it);
1375 TIME_CHECK();
1376 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1377 !status.isOk()) {
1378 ALOGE("%s: error while resetting port config %d: %s",
1379 __func__, portConfigId, status.getDescription().c_str());
1380 }
1381 return;
1382 }
1383 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1384}
1385
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001386void DeviceHalAidl::resetUnusedPatches() {
1387 // Since patches can be created independently of streams via 'createAudioPatch',
1388 // here we only clean up patches for released streams.
1389 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1390 if (auto streamSp = it->first.promote(); streamSp) {
1391 ++it;
1392 } else {
1393 resetPatch(it->second);
1394 it = mStreams.erase(it);
1395 }
1396 }
1397}
1398
1399void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1400 resetUnusedPatches();
1401 resetUnusedPortConfigs();
1402}
1403
1404void DeviceHalAidl::resetUnusedPortConfigs() {
1405 // The assumption is that port configs are used to create patches
1406 // (or to open streams, but that involves creation of patches, too). Thus,
1407 // orphaned port configs can and should be reset.
1408 std::set<int32_t> portConfigIds;
1409 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1410 std::inserter(portConfigIds, portConfigIds.end()),
1411 [](const auto& pcPair) { return pcPair.first; });
1412 for (const auto& p : mPatches) {
1413 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1414 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1415 }
jiabin2248fa12023-04-27 22:04:16 +00001416 for (int32_t id : mInitialPortConfigIds) {
1417 portConfigIds.erase(id);
1418 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001419 for (int32_t id : portConfigIds) resetPortConfig(id);
1420}
1421
Mikhail Naganovecfafb72023-03-29 10:06:15 -07001422status_t DeviceHalAidl::updateRoutes() {
1423 TIME_CHECK();
1424 std::vector<AudioRoute> routes;
1425 RETURN_STATUS_IF_ERROR(
1426 statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
1427 ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
1428 __func__, mInstance.c_str());
1429 mRoutingMatrix.clear();
1430 for (const auto& r : routes) {
1431 for (auto portId : r.sourcePortIds) {
1432 mRoutingMatrix.emplace(r.sinkPortId, portId);
1433 mRoutingMatrix.emplace(portId, r.sinkPortId);
1434 }
1435 }
1436 return OK;
1437}
1438
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001439void DeviceHalAidl::clearCallbacks(void* cookie) {
1440 std::lock_guard l(mLock);
1441 mCallbacks.erase(cookie);
1442}
1443
1444sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1445 return getCallbackImpl(cookie, &Callbacks::out);
1446}
1447
1448void DeviceHalAidl::setStreamOutCallback(
1449 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1450 setCallbackImpl(cookie, &Callbacks::out, cb);
1451}
1452
1453sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1454 void* cookie) {
1455 return getCallbackImpl(cookie, &Callbacks::event);
1456}
1457
1458void DeviceHalAidl::setStreamOutEventCallback(
1459 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1460 setCallbackImpl(cookie, &Callbacks::event, cb);
1461}
1462
1463sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1464 void* cookie) {
1465 return getCallbackImpl(cookie, &Callbacks::latency);
1466}
1467
1468void DeviceHalAidl::setStreamOutLatencyModeCallback(
1469 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1470 setCallbackImpl(cookie, &Callbacks::latency, cb);
1471}
1472
1473template<class C>
1474sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1475 std::lock_guard l(mLock);
1476 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1477 return ((it->second).*field).promote();
1478 }
1479 return nullptr;
1480}
1481template<class C>
1482void DeviceHalAidl::setCallbackImpl(
1483 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1484 std::lock_guard l(mLock);
1485 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1486 (it->second).*field = cb;
1487 }
1488}
1489
Mikhail Naganov31d46652023-01-10 18:29:25 +00001490} // namespace android