blob: d9ea0613bb1980e08dfaf8ca972d58fa4c0a3461 [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 Naganovfab697c2023-01-11 19:33:13 +000071using aidl::android::hardware::audio::core::IModule;
72using aidl::android::hardware::audio::core::ITelephony;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -070073using aidl::android::hardware::audio::core::ModuleDebug;
Mikhail Naganovfab697c2023-01-11 19:33:13 +000074using aidl::android::hardware::audio::core::StreamDescriptor;
Mikhail Naganov31d46652023-01-10 18:29:25 +000075
76namespace android {
77
Mikhail Naganovf56ce782023-01-25 11:29:11 -080078namespace {
79
80bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
81 return portConfig.sampleRate.value().value == config.base.sampleRate &&
82 portConfig.channelMask.value() == config.base.channelMask &&
83 portConfig.format.value() == config.base.format;
84}
85
86void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
87 config->base.sampleRate = portConfig.sampleRate.value().value;
88 config->base.channelMask = portConfig.channelMask.value();
89 config->base.format = portConfig.format.value();
90}
91
92void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
93 portConfig->sampleRate = Int{ .value = config.base.sampleRate };
94 portConfig->channelMask = config.base.channelMask;
95 portConfig->format = config.base.format;
96}
97
David Li9cf5e622023-03-21 00:51:10 +080098template<typename OutEnum, typename OutEnumRange, typename InEnum>
99ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
100 using InIntType = std::underlying_type_t<InEnum>;
101 static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
102
103 InIntType inEnumIndex = static_cast<InIntType>(e);
104 OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
105 if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
106 return ::android::base::unexpected(BAD_VALUE);
107 }
108 return outEnum;
109}
110
111template<typename NdkEnum, typename CppEnum>
112ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
113 return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
114}
115
116template<typename CppEnum, typename NdkEnum>
117ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
118 return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
119}
120
121ConversionResult<android::media::audio::common::AudioDeviceAddress>
122ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
123 using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
124 using NdkTag = AudioDeviceAddress::Tag;
125
126 CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
127
128 switch (cppTag) {
129 case CppTag::id:
130 return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
131 ndk.get<NdkTag::id>());
132 case CppTag::mac:
133 return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
134 ndk.get<NdkTag::mac>());
135 case CppTag::ipv4:
136 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
137 ndk.get<NdkTag::ipv4>());
138 case CppTag::ipv6:
139 return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
140 ndk.get<NdkTag::ipv6>());
141 case CppTag::alsa:
142 return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
143 ndk.get<NdkTag::alsa>());
144 }
145
146 return ::android::base::unexpected(BAD_VALUE);
147}
148
149ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
150 media::audio::common::AudioDevice cpp;
151 cpp.type.type = VALUE_OR_RETURN(
152 ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
153 cpp.type.connection = ndk.type.connection;
154 cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
155 return cpp;
156}
157
158ConversionResult<media::audio::common::AudioMMapPolicyInfo>
159ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
160 media::audio::common::AudioMMapPolicyInfo cpp;
161 cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
162 cpp.mmapPolicy = VALUE_OR_RETURN(
163 ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
164 return cpp;
165}
166
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800167} // namespace
168
Mikhail Naganov31d46652023-01-10 18:29:25 +0000169status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
170 // Obsolete.
171 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000172}
173
174status_t DeviceHalAidl::initCheck() {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800175 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000176 if (mModule == nullptr) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800177 std::vector<AudioPort> ports;
178 RETURN_STATUS_IF_ERROR(
179 statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
180 ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
181 __func__, mInstance.c_str());
182 std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
183 [](const auto& p) { return std::make_pair(p.id, p); });
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800184 mDefaultInputPortId = mDefaultOutputPortId = -1;
185 const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
186 for (const auto& pair : mPorts) {
187 const auto& p = pair.second;
188 if (p.ext.getTag() == AudioPortExt::Tag::device &&
189 (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
190 if (p.flags.getTag() == AudioIoFlags::Tag::input) {
191 mDefaultInputPortId = p.id;
192 } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
193 mDefaultOutputPortId = p.id;
194 }
195 }
196 }
197 ALOGI("%s: module %s default port ids: input %d, output %d",
198 __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800199 std::vector<AudioPortConfig> portConfigs;
200 RETURN_STATUS_IF_ERROR(
201 statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
202 std::transform(portConfigs.begin(), portConfigs.end(),
203 std::inserter(mPortConfigs, mPortConfigs.end()),
204 [](const auto& p) { return std::make_pair(p.id, p); });
205 std::vector<AudioPatch> patches;
206 RETURN_STATUS_IF_ERROR(
207 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
208 std::transform(patches.begin(), patches.end(),
209 std::inserter(mPatches, mPatches.end()),
210 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000211 return OK;
212}
213
214status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000215 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000216 if (!mModule) return NO_INIT;
217 std::shared_ptr<ITelephony> telephony;
218 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
219 status.isOk() && telephony != nullptr) {
220 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
221 RETURN_STATUS_IF_ERROR(
222 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
223 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
224 "%s: the resulting voice volume %f is not the same as requested %f",
225 __func__, outConfig.voiceVolume.value().value, volume);
226 }
227 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000228}
229
230status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000231 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000232 if (!mModule) return NO_INIT;
233 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000234}
235
236status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000237 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000238 if (!mModule) return NO_INIT;
239 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000240}
241
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000242status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000243 TIME_CHECK();
244 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000245 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
246 std::shared_ptr<ITelephony> telephony;
247 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
248 status.isOk() && telephony != nullptr) {
249 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
250 }
251 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000252}
253
254status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000255 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000256 if (!mModule) return NO_INIT;
257 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000258}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000259
Shunkai Yao51202502022-12-12 06:11:46 +0000260status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000262 if (!mModule) return NO_INIT;
263 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000264}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000265
Shunkai Yao51202502022-12-12 06:11:46 +0000266status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000267 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000268 if (!mModule) return NO_INIT;
269 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000270}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000271
Shunkai Yao51202502022-12-12 06:11:46 +0000272status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000273 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000274 if (!mModule) return NO_INIT;
275 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000276}
277
Mikhail Naganov31d46652023-01-10 18:29:25 +0000278status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
279 TIME_CHECK();
280 if (!mModule) return NO_INIT;
281 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000282 return OK;
283}
284
Mikhail Naganov31d46652023-01-10 18:29:25 +0000285status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
286 TIME_CHECK();
287 values->clear();
288 if (!mModule) return NO_INIT;
289 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000290 return OK;
291}
292
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800293namespace {
294
295class Cleanup {
296 public:
297 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
298
299 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
300 mDevice(device), mCleaner(cleaner), mId(id) {}
301 ~Cleanup() { clean(); }
302 void clean() {
303 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
304 disarm();
305 }
306 void disarm() { mDevice = nullptr; }
307
308 private:
309 DeviceHalAidl* mDevice;
310 const Cleaner mCleaner;
311 const int32_t mId;
312};
313
314} // namespace
315
316// Since the order of container elements destruction is unspecified,
317// ensure that cleanups are performed from the most recent one and upwards.
318// This is the same as if there were individual Cleanup instances on the stack,
319// however the bonus is that we can disarm all of them with just one statement.
320class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
321 public:
322 ~Cleanups() { for (auto& c : *this) c.clean(); }
323 void disarmAll() { for (auto& c : *this) c.disarm(); }
324};
325
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800326status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
327 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
328 if (size == nullptr) return BAD_VALUE;
329 TIME_CHECK();
330 if (!mModule) return NO_INIT;
331 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
332 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
333 AudioDevice aidlDevice;
334 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800335 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800336 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
337 AudioPortConfig mixPortConfig;
338 Cleanups cleanups;
339 audio_config writableConfig = *config;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700340 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800341 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700342 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800343 *size = aidlConfig.frameCount *
344 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
345 // Do not disarm cleanups to release temporary port configs.
346 return OK;
347}
348
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800349status_t DeviceHalAidl::prepareToOpenStream(
350 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800351 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800352 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700353 AudioPatch* aidlPatch) {
354 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
355 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
356 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
357 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800358 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
359 // Find / create AudioPortConfigs for the device port and the mix port,
360 // then find / create a patch between them, and open a stream on the mix port.
361 AudioPortConfig devicePortConfig;
362 bool created = false;
363 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
364 if (created) {
365 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
366 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800367 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800368 mixPortConfig, &created));
369 if (created) {
370 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
371 }
372 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800373 if (isInput) {
374 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700375 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800376 } else {
377 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700378 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800379 }
380 if (created) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700381 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800382 }
383 if (aidlConfig->frameCount <= 0) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700384 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800385 }
386 *config = VALUE_OR_RETURN_STATUS(
387 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
388 return OK;
389}
390
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800391namespace {
392
393class StreamCallbackBase {
394 protected:
395 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
396 public:
397 void* getCookie() const { return mCookie; }
398 void setCookie(void* cookie) { mCookie = cookie; }
399 sp<CallbackBroker> getBroker() const {
400 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
401 return nullptr;
402 }
403 private:
404 const wp<CallbackBroker> mBroker;
405 std::atomic<void*> mCookie;
406};
407
408template<class C>
409class StreamCallbackBaseHelper {
410 protected:
411 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
412 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
413 using CbRef = const sp<C>&;
414 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
415 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
416 return ndk::ScopedAStatus::ok();
417 }
418 private:
419 const StreamCallbackBase& mBase;
420};
421
422template<>
423sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
424 const sp<CallbackBroker>& broker, void* cookie) {
425 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
426 return nullptr;
427}
428
429template<>
430sp<StreamOutHalInterfaceEventCallback>
431StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
432 const sp<CallbackBroker>& broker, void* cookie) {
433 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
434 return nullptr;
435}
436
437template<>
438sp<StreamOutHalInterfaceLatencyModeCallback>
439StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
440 const sp<CallbackBroker>& broker, void* cookie) {
441 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
442 return nullptr;
443}
444
445/*
446Note on the callback ownership.
447
448In the Binder ownership model, the server implementation is kept alive
449as long as there is any client (proxy object) alive. This is done by
450incrementing the refcount of the server-side object by the Binder framework.
451When it detects that the last client is gone, it decrements the refcount back.
452
453Thus, it is not needed to keep any references to StreamCallback on our
454side (after we have sent an instance to the client), because we are
455the server-side. The callback object will be kept alive as long as the HAL server
456holds a strong ref to IStreamCallback proxy.
457*/
458
459class OutputStreamCallbackAidl : public StreamCallbackBase,
460 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
461 public ::aidl::android::hardware::audio::core::BnStreamCallback {
462 public:
463 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
464 : StreamCallbackBase(broker),
465 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
466 *static_cast<StreamCallbackBase*>(this)) {}
467 ndk::ScopedAStatus onTransferReady() override {
468 return runCb([](CbRef cb) { cb->onWriteReady(); });
469 }
470 ndk::ScopedAStatus onError() override {
471 return runCb([](CbRef cb) { cb->onError(); });
472 }
473 ndk::ScopedAStatus onDrainReady() override {
474 return runCb([](CbRef cb) { cb->onDrainReady(); });
475 }
476};
477
478class OutputStreamEventCallbackAidl :
479 public StreamCallbackBase,
480 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
481 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
482 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
483 public:
484 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
485 : StreamCallbackBase(broker),
486 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
487 *static_cast<StreamCallbackBase*>(this)),
488 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
489 *static_cast<StreamCallbackBase*>(this)) {}
490 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
491 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
492 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
493 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
494 }
495 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
496 const std::vector<AudioLatencyMode>& in_modes) override {
497 auto halModes = VALUE_OR_FATAL(
498 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
499 in_modes,
500 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
501 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
502 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
503 }
504};
505
506} // namespace
507
Mikhail Naganov31d46652023-01-10 18:29:25 +0000508status_t DeviceHalAidl::openOutputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800509 audio_io_handle_t handle, audio_devices_t devices,
510 audio_output_flags_t flags, struct audio_config* config,
511 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000512 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800513 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000514 if (!outStream || !config) {
515 return BAD_VALUE;
516 }
517 TIME_CHECK();
518 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800519 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
520 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
521 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
523 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
524 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
525 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
526 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
527 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
528 AudioPortConfig mixPortConfig;
529 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700530 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800531 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
532 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700533 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800534 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
535 args.portConfigId = mixPortConfig.id;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800536 const bool isOffload = isBitPositionFlagSet(
537 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
538 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
539 if (isOffload) {
540 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
541 }
542 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
543 if (isOffload) {
544 args.offloadInfo = aidlConfig.offloadInfo;
545 args.callback = streamCb;
546 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800547 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800548 args.eventCallback = eventCb;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800549 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
550 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800551 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800552 if (!context.isValid()) {
553 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
554 __func__, ret.desc.toString().c_str());
555 return NO_INIT;
556 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700557 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800558 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700559 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovb0c55252023-02-08 16:59:41 -0800560 void* cbCookie = (*outStream).get();
561 {
562 std::lock_guard l(mLock);
563 mCallbacks.emplace(cbCookie, Callbacks{});
564 }
565 if (streamCb) streamCb->setCookie(cbCookie);
566 eventCb->setCookie(cbCookie);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800567 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000568 return OK;
569}
570
Mikhail Naganov31d46652023-01-10 18:29:25 +0000571status_t DeviceHalAidl::openInputStream(
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800572 audio_io_handle_t handle, audio_devices_t devices,
573 struct audio_config* config, audio_input_flags_t flags,
574 const char* address, audio_source_t source,
575 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000576 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800577 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000578 if (!inStream || !config) {
579 return BAD_VALUE;
580 }
581 TIME_CHECK();
582 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800583 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
584 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
585 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
586 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
587 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
588 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
589 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
590 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
591 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
592 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
593 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
594 AudioPortConfig mixPortConfig;
595 Cleanups cleanups;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700596 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800597 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700598 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800599 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
600 args.portConfigId = mixPortConfig.id;
601 RecordTrackMetadata aidlTrackMetadata{
602 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
603 if (outputDevice != AUDIO_DEVICE_NONE) {
604 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
605 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
606 outputDevice, outputDeviceAddress));
607 }
608 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
609 args.bufferSizeFrames = aidlConfig.frameCount;
610 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
611 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800612 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800613 if (!context.isValid()) {
614 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
615 __func__, ret.desc.toString().c_str());
616 return NO_INIT;
617 }
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700618 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800619 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700620 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800621 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000622 return OK;
623}
624
625status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
626 *supportsPatches = true;
627 return OK;
628}
629
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800630status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
631 const struct audio_port_config* sources,
632 unsigned int num_sinks,
633 const struct audio_port_config* sinks,
634 audio_patch_handle_t* patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800635 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000636 TIME_CHECK();
637 if (!mModule) return NO_INIT;
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800638 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
639 sources == nullptr || sinks == nullptr || patch == nullptr) {
640 return BAD_VALUE;
641 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800642 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
643 // the framework wants to create a new patch. The handle has to be generated
644 // by the HAL. Since handles generated this way can only be unique within
645 // a HAL module, the framework generates a globally unique handle, and maps
646 // it on the <HAL module, patch handle> pair.
647 // When the patch handle is set, it meant the framework intends to update
648 // an existing patch.
649 //
650 // This behavior corresponds to HAL module behavior, with the only difference
651 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
652 // that both the framework and the HAL use the same value for "no ID":
653 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
654 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800655
656 // Upon conversion, mix port configs contain audio configuration, while
657 // device port configs contain device address. This data is used to find
658 // or create HAL configs.
659 std::vector<AudioPortConfig> aidlSources, aidlSinks;
660 for (unsigned int i = 0; i < num_sources; ++i) {
661 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
662 sources[i].role, sources[i].type)) ==
663 ::aidl::android::AudioPortDirection::INPUT;
664 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
665 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
666 sources[i], isInput, 0)));
667 }
668 for (unsigned int i = 0; i < num_sinks; ++i) {
669 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
670 sinks[i].role, sinks[i].type)) ==
671 ::aidl::android::AudioPortDirection::INPUT;
672 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
673 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
674 sinks[i], isInput, 0)));
675 }
676 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800677 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800678 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800679 if (existingPatchIt != mPatches.end()) {
680 aidlPatch = existingPatchIt->second;
681 aidlPatch.sourcePortConfigIds.clear();
682 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800683 }
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800684 ALOGD("%s: sources: %s, sinks: %s",
685 __func__, ::android::internal::ToString(aidlSources).c_str(),
686 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800687 auto fillPortConfigs = [&](
688 const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
689 for (const auto& s : configs) {
690 AudioPortConfig portConfig;
691 bool created = false;
692 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
693 if (created) {
694 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
695 }
696 ids->push_back(portConfig.id);
697 }
698 return OK;
699 };
700 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
701 RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
702 if (existingPatchIt != mPatches.end()) {
703 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
704 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
705 existingPatchIt->second = aidlPatch;
706 } else {
707 bool created = false;
708 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
709 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800710 halPatchId = aidlPatch.id;
711 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800712 }
713 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000714 return OK;
715}
716
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800717status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -0800718 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000719 TIME_CHECK();
720 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800721 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
722 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -0800723 return BAD_VALUE;
724 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800725 int32_t halPatchId = static_cast<int32_t>(patch);
726 auto patchIt = mPatches.find(halPatchId);
727 if (patchIt == mPatches.end()) {
728 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
729 return BAD_VALUE;
730 }
731 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
732 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000733 return OK;
734}
735
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700736status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
737 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000738 TIME_CHECK();
739 if (!mModule) return NO_INIT;
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700740 if (port == nullptr) {
741 return BAD_VALUE;
742 }
743 audio_port_v7 portV7;
744 audio_populate_audio_port_v7(port, &portV7);
745 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
746 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
747}
748
749status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
750 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
751 TIME_CHECK();
752 if (!mModule) return NO_INIT;
753 if (port == nullptr) {
754 return BAD_VALUE;
755 }
756 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
757 ::aidl::android::AudioPortDirection::INPUT;
758 auto aidlPort = VALUE_OR_RETURN_STATUS(
759 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
760 if (aidlPort.ext.getTag() != AudioPortExt::device) {
761 ALOGE("%s: provided port is not a device port (module %s): %s",
762 __func__, mInstance.c_str(), aidlPort.toString().c_str());
763 return BAD_VALUE;
764 }
765 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
766 // It seems that we don't have to call HAL since all valid ports have been added either
767 // during initialization, or while handling connection of an external device.
768 auto portsIt = findPort(matchDevice);
769 if (portsIt == mPorts.end()) {
770 ALOGE("%s: device port for device %s is not found in the module %s",
771 __func__, matchDevice.toString().c_str(), mInstance.c_str());
772 return BAD_VALUE;
773 }
774 const int32_t fwkId = aidlPort.id;
775 aidlPort = portsIt->second;
776 aidlPort.id = fwkId;
777 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
778 aidlPort, isInput));
779 return OK;
780}
781
782status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
783 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
784 TIME_CHECK();
785 if (!mModule) return NO_INIT;
786 if (config == nullptr) {
787 return BAD_VALUE;
788 }
789 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
790 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
791 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
792 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
793 *config, isInput, 0 /*portId*/));
794 AudioPortConfig portConfig;
795 bool created = false;
796 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(requestedPortConfig, &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000797 return OK;
798}
799
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800800MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
801 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
802 TIME_CHECK();
803 std::vector<MicrophoneInfo> aidlInfo;
804 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
805 if (status == OK) {
806 mMicrophones.status = Microphones::Status::QUERIED;
807 mMicrophones.info = std::move(aidlInfo);
808 } else if (status == INVALID_OPERATION) {
809 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
810 } else {
811 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
812 return {};
813 }
814 }
815 if (mMicrophones.status == Microphones::Status::QUERIED) {
816 return &mMicrophones.info;
817 }
818 return {}; // NOT_SUPPORTED
819}
820
Shunkai Yao51202502022-12-12 06:11:46 +0000821status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800822 std::vector<audio_microphone_characteristic_t>* microphones) {
823 if (!microphones) {
824 return BAD_VALUE;
825 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000826 TIME_CHECK();
827 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800828 auto staticInfo = getMicrophoneInfo();
829 if (!staticInfo) return INVALID_OPERATION;
830 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
831 emptyDynamicInfo.reserve(staticInfo->size());
832 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
833 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
834 *microphones = VALUE_OR_RETURN_STATUS(
835 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
836 *staticInfo, emptyDynamicInfo,
837 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
838 );
Shunkai Yao51202502022-12-12 06:11:46 +0000839 return OK;
840}
841
Mikhail Naganov31d46652023-01-10 18:29:25 +0000842status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
843 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000844 if (!effect) {
845 return BAD_VALUE;
846 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000847 TIME_CHECK();
848 if (!mModule) return NO_INIT;
849 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000850 return OK;
851}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000852status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000853 sp<EffectHalInterface> effect) {
854 if (!effect) {
855 return BAD_VALUE;
856 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000857 TIME_CHECK();
858 if (!mModule) return NO_INIT;
859 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000860 return OK;
861}
862
863status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800864 media::audio::common::AudioMMapPolicyType policyType,
865 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000866 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800867 AudioMMapPolicyType mmapPolicyType =
868 VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
869
870 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
871
872 if (status_t status = statusTFromBinderStatus(
873 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
874 return status;
875 }
876
877 *policyInfos = VALUE_OR_RETURN_STATUS(
878 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
879 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000880 return OK;
881}
882
883int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000884 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800885 int32_t mixerBurstCount = 0;
886 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
887 return mixerBurstCount;
888 }
889 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000890}
891
892int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000893 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800894 int32_t hardwareBurstMinUsec = 0;
895 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
896 return hardwareBurstMinUsec;
897 }
898 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000899}
900
901error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000902 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700903 if (!mModule) return NO_INIT;
904 int32_t aidlHwAvSync;
905 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
906 return VALUE_OR_RETURN_STATUS(
907 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000908}
909
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000910status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
911 TIME_CHECK();
912 if (!mModule) return NO_INIT;
913 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800914}
Shunkai Yao51202502022-12-12 06:11:46 +0000915
Mikhail Naganov31d46652023-01-10 18:29:25 +0000916int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
917 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000918 ALOGE("%s not implemented yet", __func__);
919 return INVALID_OPERATION;
920}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000921
Vlad Popa03bd5bc2023-01-17 16:16:51 +0100922status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
923 ::ndk::SpAIBinder* soundDoseBinder) {
924 TIME_CHECK();
925 if (!mModule) return NO_INIT;
926 if (mSoundDose == nullptr) {
927 ndk::ScopedAStatus status = mModule->getSoundDose(&mSoundDose);
928 if (!status.isOk()) {
929 ALOGE("%s failed to return the sound dose interface for module %s: %s",
930 __func__,
931 module.c_str(),
932 status.getDescription().c_str());
933 return BAD_VALUE;
934 }
935 }
936 *soundDoseBinder = mSoundDose->asBinder();
937 ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
938
939 return OK;
940}
941
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -0700942status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
943 TIME_CHECK();
944 if (!mModule) return NO_INIT;
945 if (port == nullptr) {
946 return BAD_VALUE;
947 }
948 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
949 ::aidl::android::AudioPortDirection::INPUT;
950 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
951 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
952 if (aidlPort.ext.getTag() != AudioPortExt::device) {
953 ALOGE("%s: provided port is not a device port (module %s): %s",
954 __func__, mInstance.c_str(), aidlPort.toString().c_str());
955 return BAD_VALUE;
956 }
957 if (connected) {
958 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
959 // Reset the device address to find the "template" port.
960 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
961 auto portsIt = findPort(matchDevice);
962 if (portsIt == mPorts.end()) {
963 ALOGW("%s: device port for device %s is not found in the module %s",
964 __func__, matchDevice.toString().c_str(), mInstance.c_str());
965 return BAD_VALUE;
966 }
967 // Use the ID of the "template" port, use all the information from the provided port.
968 aidlPort.id = portsIt->first;
969 AudioPort connectedPort;
970 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
971 aidlPort, &connectedPort)));
972 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
973 LOG_ALWAYS_FATAL_IF(!inserted,
974 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
975 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
976 it->second.toString().c_str());
977 } else { // !connected
978 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
979 auto portsIt = findPort(matchDevice);
980 if (portsIt == mPorts.end()) {
981 ALOGW("%s: device port for device %s is not found in the module %s",
982 __func__, matchDevice.toString().c_str(), mInstance.c_str());
983 return BAD_VALUE;
984 }
985 // Any streams opened on the external device must be closed by this time,
986 // thus we can clean up patches and port configs that were created for them.
987 resetUnusedPatchesAndPortConfigs();
988 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
989 portsIt->second.id)));
990 mPorts.erase(portsIt);
991 }
992 return OK;
993}
994
995status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
996 TIME_CHECK();
997 if (!mModule) return NO_INIT;
998 ModuleDebug debug{ .simulateDeviceConnections = enabled };
999 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1000 // This is important to log as it affects HAL behavior.
1001 if (status == OK) {
1002 ALOGI("%s: set enabled: %d", __func__, enabled);
1003 } else {
1004 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1005 }
1006 return status;
1007}
1008
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001009bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1010 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1011 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1012}
1013
1014bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1015 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1016 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1017 return p.portId == mDefaultInputPortId;
1018 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1019 return p.portId == mDefaultOutputPortId;
1020 }
1021 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1022}
1023
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001024status_t DeviceHalAidl::createPortConfig(
1025 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001026 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001027 AudioPortConfig appliedPortConfig;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001028 bool applied = false;
1029 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001030 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001031 if (!applied) {
1032 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001033 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001034 if (!applied) {
1035 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001036 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001037 return NO_INIT;
1038 }
1039 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001040 auto id = appliedPortConfig.id;
1041 auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
1042 LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
1043 __func__, it->first);
1044 *result = it;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001045 return OK;
1046}
1047
1048status_t DeviceHalAidl::findOrCreatePatch(
1049 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1050 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1051 requestedPatch.sourcePortConfigIds.end());
1052 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1053 requestedPatch.sinkPortConfigIds.end());
1054 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1055}
1056
1057status_t DeviceHalAidl::findOrCreatePatch(
1058 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1059 AudioPatch* patch, bool* created) {
1060 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1061 if (patchIt == mPatches.end()) {
1062 TIME_CHECK();
1063 AudioPatch requestedPatch, appliedPatch;
1064 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1065 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1066 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1067 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1068 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1069 requestedPatch, &appliedPatch)));
1070 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1071 *created = true;
1072 } else {
1073 *created = false;
1074 }
1075 *patch = patchIt->second;
1076 return OK;
1077}
1078
1079status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
1080 AudioPortConfig* portConfig, bool* created) {
1081 auto portConfigIt = findPortConfig(device);
1082 if (portConfigIt == mPortConfigs.end()) {
1083 auto portsIt = findPort(device);
1084 if (portsIt == mPorts.end()) {
1085 ALOGE("%s: device port for device %s is not found in the module %s",
1086 __func__, device.toString().c_str(), mInstance.c_str());
1087 return BAD_VALUE;
1088 }
1089 AudioPortConfig requestedPortConfig;
1090 requestedPortConfig.portId = portsIt->first;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001091 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001092 *created = true;
1093 } else {
1094 *created = false;
1095 }
1096 *portConfig = portConfigIt->second;
1097 return OK;
1098}
1099
1100status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001101 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001102 AudioSource source, AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001103 // These flags get removed one by one in this order when retrying port finding.
1104 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1105 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001106 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001107 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001108 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1109 AudioIoFlags matchFlags = flags.value();
1110 auto portsIt = findPort(config, matchFlags);
1111 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1112 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1113 if (!isBitPositionFlagSet(
1114 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1115 ++optionalInputFlagsIt;
1116 continue;
1117 }
1118 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1119 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
1120 portsIt = findPort(config, matchFlags);
1121 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1122 "retried with flags %s", __func__, config.toString().c_str(),
1123 flags.value().toString().c_str(), mInstance.c_str(),
1124 matchFlags.toString().c_str());
1125 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001126 if (portsIt == mPorts.end()) {
1127 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001128 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001129 mInstance.c_str());
1130 return BAD_VALUE;
1131 }
1132 AudioPortConfig requestedPortConfig;
1133 requestedPortConfig.portId = portsIt->first;
1134 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001135 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001136 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1137 && source != AudioSource::SYS_RESERVED_INVALID) {
1138 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1139 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1140 }
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001141 RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001142 *created = true;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001143 } else if (!flags.has_value()) {
1144 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1145 "and was not created as flags are not specified",
1146 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1147 return BAD_VALUE;
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001148 } else {
1149 *created = false;
1150 }
1151 *portConfig = portConfigIt->second;
1152 return OK;
1153}
1154
1155status_t DeviceHalAidl::findOrCreatePortConfig(
1156 const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
1157 using Tag = AudioPortExt::Tag;
1158 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1159 if (const auto& p = requestedPortConfig;
1160 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001161 !p.format.has_value()) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001162 ALOGW("%s: provided mix port config is not fully specified: %s",
1163 __func__, p.toString().c_str());
1164 return BAD_VALUE;
1165 }
1166 AudioConfig config;
1167 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001168 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1169 AudioPortMixExtUseCase::Tag::source ?
1170 requestedPortConfig.ext.get<Tag::mix>().usecase.
1171 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001172 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001173 requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001174 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1175 return findOrCreatePortConfig(
1176 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
1177 }
1178 ALOGW("%s: unsupported audio port config: %s",
1179 __func__, requestedPortConfig.toString().c_str());
1180 return BAD_VALUE;
1181}
1182
1183DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1184 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1185 return std::find_if(mPatches.begin(), mPatches.end(),
1186 [&](const auto& pair) {
1187 const auto& p = pair.second;
1188 std::set<int32_t> patchSrcs(
1189 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1190 std::set<int32_t> patchSinks(
1191 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1192 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1193}
1194
1195DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001196 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1197 return mPorts.find(mDefaultInputPortId);
1198 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1199 return mPorts.find(mDefaultOutputPortId);
1200 }
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001201 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001202 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001203}
1204
1205DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
1206 const AudioConfig& config, const AudioIoFlags& flags) {
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001207 auto belongsToProfile = [&config](const AudioProfile& prof) {
1208 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1209 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1210 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1211 config.base.channelMask) != prof.channelMasks.end()) &&
1212 (config.base.sampleRate == 0 ||
1213 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1214 config.base.sampleRate) != prof.sampleRates.end());
1215 };
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001216 auto matcher = [&](const auto& pair) {
1217 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001218 return p.ext.getTag() == AudioPortExt::Tag::mix &&
1219 p.flags == flags &&
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001220 (p.profiles.empty() ||
1221 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1222 p.profiles.end()); };
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001223 return std::find_if(mPorts.begin(), mPorts.end(), matcher);
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001224}
1225
1226DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001227 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001228 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001229}
1230
1231DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001232 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001233 using Tag = AudioPortExt::Tag;
1234 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1235 [&](const auto& pair) {
1236 const auto& p = pair.second;
1237 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1238 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1239 !p.format.has_value() || !p.flags.has_value(),
1240 "%s: stored mix port config is not fully specified: %s",
1241 __func__, p.toString().c_str());
1242 return p.ext.getTag() == Tag::mix &&
1243 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov8bd806e2023-01-30 12:33:18 -08001244 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001245 p.ext.template get<Tag::mix>().handle == ioHandle; });
1246}
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001247
Mikhail Naganovf56ce782023-01-25 11:29:11 -08001248void DeviceHalAidl::resetPatch(int32_t patchId) {
1249 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1250 mPatches.erase(it);
1251 TIME_CHECK();
1252 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1253 ALOGE("%s: error while resetting patch %d: %s",
1254 __func__, patchId, status.getDescription().c_str());
1255 }
1256 return;
1257 }
1258 ALOGE("%s: patch id %d not found", __func__, patchId);
1259}
1260
1261void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1262 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1263 mPortConfigs.erase(it);
1264 TIME_CHECK();
1265 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1266 !status.isOk()) {
1267 ALOGE("%s: error while resetting port config %d: %s",
1268 __func__, portConfigId, status.getDescription().c_str());
1269 }
1270 return;
1271 }
1272 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1273}
1274
Mikhail Naganovb1ddbb02023-03-15 17:06:59 -07001275void DeviceHalAidl::resetUnusedPatches() {
1276 // Since patches can be created independently of streams via 'createAudioPatch',
1277 // here we only clean up patches for released streams.
1278 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1279 if (auto streamSp = it->first.promote(); streamSp) {
1280 ++it;
1281 } else {
1282 resetPatch(it->second);
1283 it = mStreams.erase(it);
1284 }
1285 }
1286}
1287
1288void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1289 resetUnusedPatches();
1290 resetUnusedPortConfigs();
1291}
1292
1293void DeviceHalAidl::resetUnusedPortConfigs() {
1294 // The assumption is that port configs are used to create patches
1295 // (or to open streams, but that involves creation of patches, too). Thus,
1296 // orphaned port configs can and should be reset.
1297 std::set<int32_t> portConfigIds;
1298 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1299 std::inserter(portConfigIds, portConfigIds.end()),
1300 [](const auto& pcPair) { return pcPair.first; });
1301 for (const auto& p : mPatches) {
1302 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1303 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1304 }
1305 for (int32_t id : portConfigIds) resetPortConfig(id);
1306}
1307
Mikhail Naganovb0c55252023-02-08 16:59:41 -08001308void DeviceHalAidl::clearCallbacks(void* cookie) {
1309 std::lock_guard l(mLock);
1310 mCallbacks.erase(cookie);
1311}
1312
1313sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1314 return getCallbackImpl(cookie, &Callbacks::out);
1315}
1316
1317void DeviceHalAidl::setStreamOutCallback(
1318 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1319 setCallbackImpl(cookie, &Callbacks::out, cb);
1320}
1321
1322sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1323 void* cookie) {
1324 return getCallbackImpl(cookie, &Callbacks::event);
1325}
1326
1327void DeviceHalAidl::setStreamOutEventCallback(
1328 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1329 setCallbackImpl(cookie, &Callbacks::event, cb);
1330}
1331
1332sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1333 void* cookie) {
1334 return getCallbackImpl(cookie, &Callbacks::latency);
1335}
1336
1337void DeviceHalAidl::setStreamOutLatencyModeCallback(
1338 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1339 setCallbackImpl(cookie, &Callbacks::latency, cb);
1340}
1341
1342template<class C>
1343sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1344 std::lock_guard l(mLock);
1345 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1346 return ((it->second).*field).promote();
1347 }
1348 return nullptr;
1349}
1350template<class C>
1351void DeviceHalAidl::setCallbackImpl(
1352 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1353 std::lock_guard l(mLock);
1354 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1355 (it->second).*field = cb;
1356 }
1357}
1358
Mikhail Naganov31d46652023-01-10 18:29:25 +00001359} // namespace android