blob: c5fbcf86d0d3f1d01a6403f573ad9e7b356b3a62 [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"
Mikhail Naganov89a9f742023-01-30 12:33:18 -080018// #define LOG_NDEBUG 0
Shunkai Yao51202502022-12-12 06:11:46 +000019
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080020#include <algorithm>
21#include <forward_list>
22
Mikhail Naganovdfd594e2023-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 Naganov89a9f742023-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 Naganove93a0862023-03-15 17:06:59 -070039using aidl::android::media::audio::common::AudioChannelLayout;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-01-30 12:33:18 -080043using aidl::android::media::audio::common::AudioDeviceType;
Mikhail Naganove93a0862023-03-15 17:06:59 -070044using aidl::android::media::audio::common::AudioFormatType;
Mikhail Naganov89a9f742023-01-30 12:33:18 -080045using aidl::android::media::audio::common::AudioInputFlags;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080046using aidl::android::media::audio::common::AudioIoFlags;
Mikhail Naganovdfd594e2023-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 Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganove93a0862023-03-15 17:06:59 -070059using aidl::android::media::audio::common::AudioProfile;
Mikhail Naganov5b1eed12023-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 Naganove93a0862023-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 Naganov5b1eed12023-01-25 11:29:11 -080069using aidl::android::hardware::audio::common::RecordTrackMetadata;
70using aidl::android::hardware::audio::core::AudioPatch;
Mikhail Naganov289468a2023-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 Naganove93a0862023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-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 Naganov5b1eed12023-01-25 11:29:11 -0800176 TIME_CHECK();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000177 if (mModule == nullptr) return NO_INIT;
Mikhail Naganov5b1eed12023-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 Naganov89a9f742023-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 Naganov289468a2023-03-29 10:06:15 -0700200 RETURN_STATUS_IF_ERROR(updateRoutes());
Mikhail Naganov5b1eed12023-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); });
207 std::vector<AudioPatch> patches;
208 RETURN_STATUS_IF_ERROR(
209 statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
210 std::transform(patches.begin(), patches.end(),
211 std::inserter(mPatches, mPatches.end()),
212 [](const auto& p) { return std::make_pair(p.id, p); });
Shunkai Yao51202502022-12-12 06:11:46 +0000213 return OK;
214}
215
216status_t DeviceHalAidl::setVoiceVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000217 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000218 if (!mModule) return NO_INIT;
219 std::shared_ptr<ITelephony> telephony;
220 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
221 status.isOk() && telephony != nullptr) {
222 ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
223 RETURN_STATUS_IF_ERROR(
224 statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
225 ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
226 "%s: the resulting voice volume %f is not the same as requested %f",
227 __func__, outConfig.voiceVolume.value().value, volume);
228 }
229 return INVALID_OPERATION;
Shunkai Yao51202502022-12-12 06:11:46 +0000230}
231
232status_t DeviceHalAidl::setMasterVolume(float volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000233 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000234 if (!mModule) return NO_INIT;
235 return statusTFromBinderStatus(mModule->setMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000236}
237
238status_t DeviceHalAidl::getMasterVolume(float *volume) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000239 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000240 if (!mModule) return NO_INIT;
241 return statusTFromBinderStatus(mModule->getMasterVolume(volume));
Shunkai Yao51202502022-12-12 06:11:46 +0000242}
243
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000244status_t DeviceHalAidl::setMode(audio_mode_t mode) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000245 TIME_CHECK();
246 if (!mModule) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000247 AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
248 std::shared_ptr<ITelephony> telephony;
249 if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
250 status.isOk() && telephony != nullptr) {
251 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
252 }
253 return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
Shunkai Yao51202502022-12-12 06:11:46 +0000254}
255
256status_t DeviceHalAidl::setMicMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000257 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000258 if (!mModule) return NO_INIT;
259 return statusTFromBinderStatus(mModule->setMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000260}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000261
Shunkai Yao51202502022-12-12 06:11:46 +0000262status_t DeviceHalAidl::getMicMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000263 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000264 if (!mModule) return NO_INIT;
265 return statusTFromBinderStatus(mModule->getMicMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000266}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000267
Shunkai Yao51202502022-12-12 06:11:46 +0000268status_t DeviceHalAidl::setMasterMute(bool state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000269 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000270 if (!mModule) return NO_INIT;
271 return statusTFromBinderStatus(mModule->setMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000272}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000273
Shunkai Yao51202502022-12-12 06:11:46 +0000274status_t DeviceHalAidl::getMasterMute(bool *state) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000275 TIME_CHECK();
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000276 if (!mModule) return NO_INIT;
277 return statusTFromBinderStatus(mModule->getMasterMute(state));
Shunkai Yao51202502022-12-12 06:11:46 +0000278}
279
Mikhail Naganov31d46652023-01-10 18:29:25 +0000280status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
281 TIME_CHECK();
282 if (!mModule) return NO_INIT;
283 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000284 return OK;
285}
286
Mikhail Naganov31d46652023-01-10 18:29:25 +0000287status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
288 TIME_CHECK();
289 values->clear();
290 if (!mModule) return NO_INIT;
291 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000292 return OK;
293}
294
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800295namespace {
296
297class Cleanup {
298 public:
299 typedef void (DeviceHalAidl::*Cleaner)(int32_t);
300
301 Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
302 mDevice(device), mCleaner(cleaner), mId(id) {}
303 ~Cleanup() { clean(); }
304 void clean() {
305 if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
306 disarm();
307 }
308 void disarm() { mDevice = nullptr; }
309
310 private:
311 DeviceHalAidl* mDevice;
312 const Cleaner mCleaner;
313 const int32_t mId;
314};
315
316} // namespace
317
318// Since the order of container elements destruction is unspecified,
319// ensure that cleanups are performed from the most recent one and upwards.
320// This is the same as if there were individual Cleanup instances on the stack,
321// however the bonus is that we can disarm all of them with just one statement.
322class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
323 public:
324 ~Cleanups() { for (auto& c : *this) c.clean(); }
325 void disarmAll() { for (auto& c : *this) c.disarm(); }
326};
327
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800328status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
329 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
330 if (size == nullptr) return BAD_VALUE;
331 TIME_CHECK();
332 if (!mModule) return NO_INIT;
333 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
334 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
335 AudioDevice aidlDevice;
336 aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800337 AudioSource aidlSource = AudioSource::DEFAULT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800338 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
339 AudioPortConfig mixPortConfig;
340 Cleanups cleanups;
341 audio_config writableConfig = *config;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700342 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800343 RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700344 &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800345 *size = aidlConfig.frameCount *
346 getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
347 // Do not disarm cleanups to release temporary port configs.
348 return OK;
349}
350
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800351status_t DeviceHalAidl::prepareToOpenStream(
352 int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800353 AudioSource aidlSource, struct audio_config* config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800354 Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700355 AudioPatch* aidlPatch) {
356 ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
357 this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
358 aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
359 aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800360 const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
361 // Find / create AudioPortConfigs for the device port and the mix port,
362 // then find / create a patch between them, and open a stream on the mix port.
363 AudioPortConfig devicePortConfig;
364 bool created = false;
365 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
366 if (created) {
367 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
368 }
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800369 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
Mikhail Naganov289468a2023-03-29 10:06:15 -0700370 std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800371 if (created) {
372 cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
373 }
374 setConfigFromPortConfig(aidlConfig, *mixPortConfig);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800375 if (isInput) {
376 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700377 {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800378 } else {
379 RETURN_STATUS_IF_ERROR(findOrCreatePatch(
Mikhail Naganove93a0862023-03-15 17:06:59 -0700380 {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800381 }
382 if (created) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700383 cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800384 }
385 if (aidlConfig->frameCount <= 0) {
Mikhail Naganove93a0862023-03-15 17:06:59 -0700386 aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800387 }
388 *config = VALUE_OR_RETURN_STATUS(
389 ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
390 return OK;
391}
392
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800393namespace {
394
395class StreamCallbackBase {
396 protected:
397 explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
398 public:
399 void* getCookie() const { return mCookie; }
400 void setCookie(void* cookie) { mCookie = cookie; }
401 sp<CallbackBroker> getBroker() const {
402 if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
403 return nullptr;
404 }
405 private:
406 const wp<CallbackBroker> mBroker;
407 std::atomic<void*> mCookie;
408};
409
410template<class C>
411class StreamCallbackBaseHelper {
412 protected:
413 explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
414 sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
415 using CbRef = const sp<C>&;
416 ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
417 if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
418 return ndk::ScopedAStatus::ok();
419 }
420 private:
421 const StreamCallbackBase& mBase;
422};
423
424template<>
425sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
426 const sp<CallbackBroker>& broker, void* cookie) {
427 if (broker != nullptr) return broker->getStreamOutCallback(cookie);
428 return nullptr;
429}
430
431template<>
432sp<StreamOutHalInterfaceEventCallback>
433StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
434 const sp<CallbackBroker>& broker, void* cookie) {
435 if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
436 return nullptr;
437}
438
439template<>
440sp<StreamOutHalInterfaceLatencyModeCallback>
441StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
442 const sp<CallbackBroker>& broker, void* cookie) {
443 if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
444 return nullptr;
445}
446
447/*
448Note on the callback ownership.
449
450In the Binder ownership model, the server implementation is kept alive
451as long as there is any client (proxy object) alive. This is done by
452incrementing the refcount of the server-side object by the Binder framework.
453When it detects that the last client is gone, it decrements the refcount back.
454
455Thus, it is not needed to keep any references to StreamCallback on our
456side (after we have sent an instance to the client), because we are
457the server-side. The callback object will be kept alive as long as the HAL server
458holds a strong ref to IStreamCallback proxy.
459*/
460
461class OutputStreamCallbackAidl : public StreamCallbackBase,
462 public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
463 public ::aidl::android::hardware::audio::core::BnStreamCallback {
464 public:
465 explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
466 : StreamCallbackBase(broker),
467 StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
468 *static_cast<StreamCallbackBase*>(this)) {}
469 ndk::ScopedAStatus onTransferReady() override {
470 return runCb([](CbRef cb) { cb->onWriteReady(); });
471 }
472 ndk::ScopedAStatus onError() override {
473 return runCb([](CbRef cb) { cb->onError(); });
474 }
475 ndk::ScopedAStatus onDrainReady() override {
476 return runCb([](CbRef cb) { cb->onDrainReady(); });
477 }
478};
479
480class OutputStreamEventCallbackAidl :
481 public StreamCallbackBase,
482 public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
483 public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
484 public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
485 public:
486 explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
487 : StreamCallbackBase(broker),
488 StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
489 *static_cast<StreamCallbackBase*>(this)),
490 StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
491 *static_cast<StreamCallbackBase*>(this)) {}
492 ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
493 std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
494 return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
495 [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
496 }
497 ndk::ScopedAStatus onRecommendedLatencyModeChanged(
498 const std::vector<AudioLatencyMode>& in_modes) override {
499 auto halModes = VALUE_OR_FATAL(
500 ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
501 in_modes,
502 ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
503 return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
504 [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
505 }
506};
507
508} // namespace
509
Mikhail Naganov31d46652023-01-10 18:29:25 +0000510status_t DeviceHalAidl::openOutputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800511 audio_io_handle_t handle, audio_devices_t devices,
512 audio_output_flags_t flags, struct audio_config* config,
513 const char* address,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000514 sp<StreamOutHalInterface>* outStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800515 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000516 if (!outStream || !config) {
517 return BAD_VALUE;
518 }
519 TIME_CHECK();
520 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800521 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
522 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
523 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
524 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
525 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
526 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
527 int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
528 ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
529 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
530 AudioPortConfig mixPortConfig;
531 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700532 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800533 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
534 AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700535 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800536 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
537 args.portConfigId = mixPortConfig.id;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800538 const bool isOffload = isBitPositionFlagSet(
539 aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
540 std::shared_ptr<OutputStreamCallbackAidl> streamCb;
541 if (isOffload) {
542 streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
543 }
544 auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
545 if (isOffload) {
546 args.offloadInfo = aidlConfig.offloadInfo;
547 args.callback = streamCb;
548 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800549 args.bufferSizeFrames = aidlConfig.frameCount;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800550 args.eventCallback = eventCb;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800551 ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
552 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800553 StreamContextAidl context(ret.desc, isOffload);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800554 if (!context.isValid()) {
555 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
556 __func__, ret.desc.toString().c_str());
557 return NO_INIT;
558 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700559 *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800560 std::move(ret.stream), this /*callbackBroker*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700561 mStreams.insert(std::pair(*outStream, aidlPatch.id));
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800562 void* cbCookie = (*outStream).get();
563 {
564 std::lock_guard l(mLock);
565 mCallbacks.emplace(cbCookie, Callbacks{});
566 }
567 if (streamCb) streamCb->setCookie(cbCookie);
568 eventCb->setCookie(cbCookie);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800569 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000570 return OK;
571}
572
Mikhail Naganov31d46652023-01-10 18:29:25 +0000573status_t DeviceHalAidl::openInputStream(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800574 audio_io_handle_t handle, audio_devices_t devices,
575 struct audio_config* config, audio_input_flags_t flags,
576 const char* address, audio_source_t source,
577 audio_devices_t outputDevice, const char* outputDeviceAddress,
Mikhail Naganov31d46652023-01-10 18:29:25 +0000578 sp<StreamInHalInterface>* inStream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800579 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000580 if (!inStream || !config) {
581 return BAD_VALUE;
582 }
583 TIME_CHECK();
584 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800585 int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
586 ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
587 AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
588 ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
589 AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
590 ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
591 int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
592 ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
593 AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
594 AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
595 ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
596 AudioPortConfig mixPortConfig;
597 Cleanups cleanups;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700598 AudioPatch aidlPatch;
Mikhail Naganovd8d01f72023-03-09 16:24:40 -0800599 RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
Mikhail Naganove93a0862023-03-15 17:06:59 -0700600 config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800601 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
602 args.portConfigId = mixPortConfig.id;
603 RecordTrackMetadata aidlTrackMetadata{
604 .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
605 if (outputDevice != AUDIO_DEVICE_NONE) {
606 aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
607 ::aidl::android::legacy2aidl_audio_device_AudioDevice(
608 outputDevice, outputDeviceAddress));
609 }
610 args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
611 args.bufferSizeFrames = aidlConfig.frameCount;
612 ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
613 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800614 StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800615 if (!context.isValid()) {
616 ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
617 __func__, ret.desc.toString().c_str());
618 return NO_INIT;
619 }
Mikhail Naganove93a0862023-03-15 17:06:59 -0700620 *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800621 std::move(ret.stream), this /*micInfoProvider*/);
Mikhail Naganove93a0862023-03-15 17:06:59 -0700622 mStreams.insert(std::pair(*inStream, aidlPatch.id));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800623 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000624 return OK;
625}
626
627status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
628 *supportsPatches = true;
629 return OK;
630}
631
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800632status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
633 const struct audio_port_config* sources,
634 unsigned int num_sinks,
635 const struct audio_port_config* sinks,
636 audio_patch_handle_t* patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800637 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000638 TIME_CHECK();
639 if (!mModule) return NO_INIT;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800640 if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
641 sources == nullptr || sinks == nullptr || patch == nullptr) {
642 return BAD_VALUE;
643 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800644 // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
645 // the framework wants to create a new patch. The handle has to be generated
646 // by the HAL. Since handles generated this way can only be unique within
647 // a HAL module, the framework generates a globally unique handle, and maps
648 // it on the <HAL module, patch handle> pair.
649 // When the patch handle is set, it meant the framework intends to update
650 // an existing patch.
651 //
652 // This behavior corresponds to HAL module behavior, with the only difference
653 // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
654 // that both the framework and the HAL use the same value for "no ID":
655 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
656 int32_t halPatchId = static_cast<int32_t>(*patch);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800657
658 // Upon conversion, mix port configs contain audio configuration, while
659 // device port configs contain device address. This data is used to find
660 // or create HAL configs.
661 std::vector<AudioPortConfig> aidlSources, aidlSinks;
662 for (unsigned int i = 0; i < num_sources; ++i) {
663 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
664 sources[i].role, sources[i].type)) ==
665 ::aidl::android::AudioPortDirection::INPUT;
666 aidlSources.push_back(VALUE_OR_RETURN_STATUS(
667 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
668 sources[i], isInput, 0)));
669 }
670 for (unsigned int i = 0; i < num_sinks; ++i) {
671 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
672 sinks[i].role, sinks[i].type)) ==
673 ::aidl::android::AudioPortDirection::INPUT;
674 aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
675 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
676 sinks[i], isInput, 0)));
677 }
678 Cleanups cleanups;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800679 auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800680 AudioPatch aidlPatch;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800681 if (existingPatchIt != mPatches.end()) {
682 aidlPatch = existingPatchIt->second;
683 aidlPatch.sourcePortConfigIds.clear();
684 aidlPatch.sinkPortConfigIds.clear();
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800685 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800686 ALOGD("%s: sources: %s, sinks: %s",
687 __func__, ::android::internal::ToString(aidlSources).c_str(),
688 ::android::internal::ToString(aidlSinks).c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800689 auto fillPortConfigs = [&](
Mikhail Naganov289468a2023-03-29 10:06:15 -0700690 const std::vector<AudioPortConfig>& configs,
691 const std::set<int32_t>& destinationPortIds,
692 std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800693 for (const auto& s : configs) {
694 AudioPortConfig portConfig;
695 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700696 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
697 s, destinationPortIds, &portConfig, &created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800698 if (created) {
699 cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
700 }
701 ids->push_back(portConfig.id);
Mikhail Naganov289468a2023-03-29 10:06:15 -0700702 if (portIds != nullptr) {
703 portIds->insert(portConfig.portId);
704 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800705 }
706 return OK;
707 };
Mikhail Naganov289468a2023-03-29 10:06:15 -0700708 // When looking up port configs, the destinationPortId is only used for mix ports.
709 // Thus, we process device port configs first, and look up the destination port ID from them.
710 bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
711 [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
712 const std::vector<AudioPortConfig>& devicePortConfigs =
713 sourceIsDevice ? aidlSources : aidlSinks;
714 std::vector<int32_t>* devicePortConfigIds =
715 sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
716 const std::vector<AudioPortConfig>& mixPortConfigs =
717 sourceIsDevice ? aidlSinks : aidlSources;
718 std::vector<int32_t>* mixPortConfigIds =
719 sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
720 std::set<int32_t> devicePortIds;
721 RETURN_STATUS_IF_ERROR(fillPortConfigs(
722 devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
723 RETURN_STATUS_IF_ERROR(fillPortConfigs(
724 mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800725 if (existingPatchIt != mPatches.end()) {
726 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
727 mModule->setAudioPatch(aidlPatch, &aidlPatch)));
728 existingPatchIt->second = aidlPatch;
729 } else {
730 bool created = false;
731 RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
732 // Since no cleanup of the patch is needed, 'created' is ignored.
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800733 halPatchId = aidlPatch.id;
734 *patch = static_cast<audio_patch_handle_t>(halPatchId);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800735 }
736 cleanups.disarmAll();
Shunkai Yao51202502022-12-12 06:11:46 +0000737 return OK;
738}
739
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800740status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800741 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000742 TIME_CHECK();
743 if (!mModule) return NO_INIT;
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800744 static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
745 if (patch == AUDIO_PATCH_HANDLE_NONE) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800746 return BAD_VALUE;
747 }
Mikhail Naganov47d1d732023-02-23 15:16:04 -0800748 int32_t halPatchId = static_cast<int32_t>(patch);
749 auto patchIt = mPatches.find(halPatchId);
750 if (patchIt == mPatches.end()) {
751 ALOGE("%s: patch with id %d not found", __func__, halPatchId);
752 return BAD_VALUE;
753 }
754 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
755 mPatches.erase(patchIt);
Shunkai Yao51202502022-12-12 06:11:46 +0000756 return OK;
757}
758
Mikhail Naganove93a0862023-03-15 17:06:59 -0700759status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
760 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000761 TIME_CHECK();
762 if (!mModule) return NO_INIT;
Mikhail Naganove93a0862023-03-15 17:06:59 -0700763 if (port == nullptr) {
764 return BAD_VALUE;
765 }
766 audio_port_v7 portV7;
767 audio_populate_audio_port_v7(port, &portV7);
768 RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
769 return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
770}
771
772status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
773 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
774 TIME_CHECK();
775 if (!mModule) return NO_INIT;
776 if (port == nullptr) {
777 return BAD_VALUE;
778 }
779 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
780 ::aidl::android::AudioPortDirection::INPUT;
781 auto aidlPort = VALUE_OR_RETURN_STATUS(
782 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
783 if (aidlPort.ext.getTag() != AudioPortExt::device) {
784 ALOGE("%s: provided port is not a device port (module %s): %s",
785 __func__, mInstance.c_str(), aidlPort.toString().c_str());
786 return BAD_VALUE;
787 }
788 const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
789 // It seems that we don't have to call HAL since all valid ports have been added either
790 // during initialization, or while handling connection of an external device.
791 auto portsIt = findPort(matchDevice);
792 if (portsIt == mPorts.end()) {
793 ALOGE("%s: device port for device %s is not found in the module %s",
794 __func__, matchDevice.toString().c_str(), mInstance.c_str());
795 return BAD_VALUE;
796 }
797 const int32_t fwkId = aidlPort.id;
798 aidlPort = portsIt->second;
799 aidlPort.id = fwkId;
800 *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
801 aidlPort, isInput));
802 return OK;
803}
804
805status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
806 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
807 TIME_CHECK();
808 if (!mModule) return NO_INIT;
809 if (config == nullptr) {
810 return BAD_VALUE;
811 }
812 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
813 config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
814 AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
815 ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
816 *config, isInput, 0 /*portId*/));
817 AudioPortConfig portConfig;
818 bool created = false;
Mikhail Naganov289468a2023-03-29 10:06:15 -0700819 RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
820 requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
Shunkai Yao51202502022-12-12 06:11:46 +0000821 return OK;
822}
823
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800824MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
825 if (mMicrophones.status == Microphones::Status::UNKNOWN) {
826 TIME_CHECK();
827 std::vector<MicrophoneInfo> aidlInfo;
828 status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
829 if (status == OK) {
830 mMicrophones.status = Microphones::Status::QUERIED;
831 mMicrophones.info = std::move(aidlInfo);
832 } else if (status == INVALID_OPERATION) {
833 mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
834 } else {
835 ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
836 return {};
837 }
838 }
839 if (mMicrophones.status == Microphones::Status::QUERIED) {
840 return &mMicrophones.info;
841 }
842 return {}; // NOT_SUPPORTED
843}
844
Shunkai Yao51202502022-12-12 06:11:46 +0000845status_t DeviceHalAidl::getMicrophones(
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800846 std::vector<audio_microphone_characteristic_t>* microphones) {
847 if (!microphones) {
848 return BAD_VALUE;
849 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000850 TIME_CHECK();
851 if (!mModule) return NO_INIT;
Mikhail Naganovcad0afe2023-03-10 14:25:57 -0800852 auto staticInfo = getMicrophoneInfo();
853 if (!staticInfo) return INVALID_OPERATION;
854 std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
855 emptyDynamicInfo.reserve(staticInfo->size());
856 std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
857 [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
858 *microphones = VALUE_OR_RETURN_STATUS(
859 ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
860 *staticInfo, emptyDynamicInfo,
861 ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
862 );
Shunkai Yao51202502022-12-12 06:11:46 +0000863 return OK;
864}
865
Mikhail Naganov31d46652023-01-10 18:29:25 +0000866status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
867 sp<EffectHalInterface> effect) {
Shunkai Yao51202502022-12-12 06:11:46 +0000868 if (!effect) {
869 return BAD_VALUE;
870 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000871 TIME_CHECK();
872 if (!mModule) return NO_INIT;
873 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000874 return OK;
875}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000876status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
Shunkai Yao51202502022-12-12 06:11:46 +0000877 sp<EffectHalInterface> effect) {
878 if (!effect) {
879 return BAD_VALUE;
880 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000881 TIME_CHECK();
882 if (!mModule) return NO_INIT;
883 ALOGE("%s not implemented yet", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000884 return OK;
885}
886
887status_t DeviceHalAidl::getMmapPolicyInfos(
David Li9cf5e622023-03-21 00:51:10 +0800888 media::audio::common::AudioMMapPolicyType policyType,
889 std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000890 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800891 AudioMMapPolicyType mmapPolicyType =
892 VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
893
894 std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
895
896 if (status_t status = statusTFromBinderStatus(
897 mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
898 return status;
899 }
900
901 *policyInfos = VALUE_OR_RETURN_STATUS(
902 convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
903 mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
Shunkai Yao51202502022-12-12 06:11:46 +0000904 return OK;
905}
906
907int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000908 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800909 int32_t mixerBurstCount = 0;
910 if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
911 return mixerBurstCount;
912 }
913 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000914}
915
916int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000917 TIME_CHECK();
David Li9cf5e622023-03-21 00:51:10 +0800918 int32_t hardwareBurstMinUsec = 0;
919 if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
920 return hardwareBurstMinUsec;
921 }
922 return 0;
Shunkai Yao51202502022-12-12 06:11:46 +0000923}
924
925error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000926 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700927 if (!mModule) return NO_INIT;
928 int32_t aidlHwAvSync;
929 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
930 return VALUE_OR_RETURN_STATUS(
931 ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
Shunkai Yao51202502022-12-12 06:11:46 +0000932}
933
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000934status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
935 TIME_CHECK();
936 if (!mModule) return NO_INIT;
937 return mModule->dump(fd, Args(args).args(), args.size());
David Li9cf5e622023-03-21 00:51:10 +0800938}
Shunkai Yao51202502022-12-12 06:11:46 +0000939
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700940int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000941 TIME_CHECK();
Mikhail Naganov3ac95c92023-04-12 13:14:30 -0700942 if (!mModule) return NO_INIT;
943 if (supports == nullptr) {
944 return BAD_VALUE;
945 }
946 return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
Shunkai Yao51202502022-12-12 06:11:46 +0000947}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000948
Mikhail Naganove93a0862023-03-15 17:06:59 -0700949status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
950 TIME_CHECK();
951 if (!mModule) return NO_INIT;
952 if (port == nullptr) {
953 return BAD_VALUE;
954 }
955 bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
956 ::aidl::android::AudioPortDirection::INPUT;
957 AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
958 ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
959 if (aidlPort.ext.getTag() != AudioPortExt::device) {
960 ALOGE("%s: provided port is not a device port (module %s): %s",
961 __func__, mInstance.c_str(), aidlPort.toString().c_str());
962 return BAD_VALUE;
963 }
964 if (connected) {
965 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
966 // Reset the device address to find the "template" port.
967 matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
968 auto portsIt = findPort(matchDevice);
969 if (portsIt == mPorts.end()) {
970 ALOGW("%s: device port for device %s is not found in the module %s",
971 __func__, matchDevice.toString().c_str(), mInstance.c_str());
972 return BAD_VALUE;
973 }
974 // Use the ID of the "template" port, use all the information from the provided port.
975 aidlPort.id = portsIt->first;
976 AudioPort connectedPort;
977 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
978 aidlPort, &connectedPort)));
979 const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
980 LOG_ALWAYS_FATAL_IF(!inserted,
981 "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
982 __func__, mInstance.c_str(), connectedPort.toString().c_str(),
983 it->second.toString().c_str());
984 } else { // !connected
985 AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
986 auto portsIt = findPort(matchDevice);
987 if (portsIt == mPorts.end()) {
988 ALOGW("%s: device port for device %s is not found in the module %s",
989 __func__, matchDevice.toString().c_str(), mInstance.c_str());
990 return BAD_VALUE;
991 }
992 // Any streams opened on the external device must be closed by this time,
993 // thus we can clean up patches and port configs that were created for them.
994 resetUnusedPatchesAndPortConfigs();
995 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
996 portsIt->second.id)));
997 mPorts.erase(portsIt);
998 }
Mikhail Naganov289468a2023-03-29 10:06:15 -0700999 return updateRoutes();
Mikhail Naganove93a0862023-03-15 17:06:59 -07001000}
1001
1002status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
1003 TIME_CHECK();
1004 if (!mModule) return NO_INIT;
1005 ModuleDebug debug{ .simulateDeviceConnections = enabled };
1006 status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
1007 // This is important to log as it affects HAL behavior.
1008 if (status == OK) {
1009 ALOGI("%s: set enabled: %d", __func__, enabled);
1010 } else {
1011 ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
1012 }
1013 return status;
1014}
1015
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001016bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
1017 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1018 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1019}
1020
1021bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
1022 if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
1023 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1024 return p.portId == mDefaultInputPortId;
1025 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1026 return p.portId == mDefaultOutputPortId;
1027 }
1028 return p.ext.get<AudioPortExt::Tag::device>().device == device;
1029}
1030
David Lia8675d42023-03-30 21:08:06 +08001031status_t DeviceHalAidl::createOrUpdatePortConfig(
1032 const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001033 TIME_CHECK();
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001034 AudioPortConfig appliedPortConfig;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001035 bool applied = false;
1036 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001037 requestedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001038 if (!applied) {
1039 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001040 appliedPortConfig, &appliedPortConfig, &applied)));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001041 if (!applied) {
1042 ALOGE("%s: module %s did not apply suggested config %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001043 __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001044 return NO_INIT;
1045 }
1046 }
David Lia8675d42023-03-30 21:08:06 +08001047
1048 int32_t id = appliedPortConfig.id;
1049 if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
1050 LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
1051 requestedPortConfig.id, id);
1052 }
1053
1054 auto [it, inserted] = mPortConfigs.insert_or_assign(std::move(id),
1055 std::move(appliedPortConfig));
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001056 *result = it;
David Lia8675d42023-03-30 21:08:06 +08001057 *created = inserted;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001058 return OK;
1059}
1060
1061status_t DeviceHalAidl::findOrCreatePatch(
1062 const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
1063 std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
1064 requestedPatch.sourcePortConfigIds.end());
1065 std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
1066 requestedPatch.sinkPortConfigIds.end());
1067 return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
1068}
1069
1070status_t DeviceHalAidl::findOrCreatePatch(
1071 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
1072 AudioPatch* patch, bool* created) {
1073 auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
1074 if (patchIt == mPatches.end()) {
1075 TIME_CHECK();
1076 AudioPatch requestedPatch, appliedPatch;
1077 requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
1078 sourcePortConfigIds.begin(), sourcePortConfigIds.end());
1079 requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
1080 sinkPortConfigIds.begin(), sinkPortConfigIds.end());
1081 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
1082 requestedPatch, &appliedPatch)));
1083 patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
1084 *created = true;
1085 } else {
1086 *created = false;
1087 }
1088 *patch = patchIt->second;
1089 return OK;
1090}
1091
1092status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
1093 AudioPortConfig* portConfig, bool* created) {
1094 auto portConfigIt = findPortConfig(device);
1095 if (portConfigIt == mPortConfigs.end()) {
1096 auto portsIt = findPort(device);
1097 if (portsIt == mPorts.end()) {
1098 ALOGE("%s: device port for device %s is not found in the module %s",
1099 __func__, device.toString().c_str(), mInstance.c_str());
1100 return BAD_VALUE;
1101 }
1102 AudioPortConfig requestedPortConfig;
1103 requestedPortConfig.portId = portsIt->first;
David Lia8675d42023-03-30 21:08:06 +08001104 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1105 created));
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001106 } else {
1107 *created = false;
1108 }
1109 *portConfig = portConfigIt->second;
1110 return OK;
1111}
1112
1113status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001114 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001115 AudioSource source, const std::set<int32_t>& destinationPortIds,
1116 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001117 // These flags get removed one by one in this order when retrying port finding.
1118 static const std::vector<AudioInputFlags> kOptionalInputFlags{
1119 AudioInputFlags::FAST, AudioInputFlags::RAW };
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001120 auto portConfigIt = findPortConfig(config, flags, ioHandle);
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001121 if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001122 auto optionalInputFlagsIt = kOptionalInputFlags.begin();
1123 AudioIoFlags matchFlags = flags.value();
Mikhail Naganov289468a2023-03-29 10:06:15 -07001124 auto portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001125 while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
1126 && optionalInputFlagsIt != kOptionalInputFlags.end()) {
1127 if (!isBitPositionFlagSet(
1128 matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
1129 ++optionalInputFlagsIt;
1130 continue;
1131 }
1132 matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
1133 ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
Mikhail Naganov289468a2023-03-29 10:06:15 -07001134 portsIt = findPort(config, matchFlags, destinationPortIds);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001135 ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
1136 "retried with flags %s", __func__, config.toString().c_str(),
1137 flags.value().toString().c_str(), mInstance.c_str(),
1138 matchFlags.toString().c_str());
1139 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001140 if (portsIt == mPorts.end()) {
1141 ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001142 __func__, config.toString().c_str(), matchFlags.toString().c_str(),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001143 mInstance.c_str());
1144 return BAD_VALUE;
1145 }
1146 AudioPortConfig requestedPortConfig;
1147 requestedPortConfig.portId = portsIt->first;
1148 setPortConfigFromConfig(&requestedPortConfig, config);
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001149 requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001150 if (matchFlags.getTag() == AudioIoFlags::Tag::input
1151 && source != AudioSource::SYS_RESERVED_INVALID) {
1152 requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
1153 AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
1154 }
David Lia8675d42023-03-30 21:08:06 +08001155 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1156 created));
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001157 } else if (!flags.has_value()) {
1158 ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
1159 "and was not created as flags are not specified",
1160 __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
1161 return BAD_VALUE;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001162 } else {
David Lia8675d42023-03-30 21:08:06 +08001163 AudioPortConfig requestedPortConfig = portConfigIt->second;
1164 if (requestedPortConfig.ext.getTag() == AudioPortExt::Tag::mix) {
1165 AudioPortMixExt& mixExt = requestedPortConfig.ext.get<AudioPortExt::Tag::mix>();
1166 if (mixExt.usecase.getTag() == AudioPortMixExtUseCase::Tag::source &&
1167 source != AudioSource::SYS_RESERVED_INVALID) {
1168 mixExt.usecase.get<AudioPortMixExtUseCase::Tag::source>() = source;
1169 }
1170 }
1171
1172 if (requestedPortConfig != portConfigIt->second) {
1173 RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
1174 created));
1175 } else {
1176 *created = false;
1177 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001178 }
1179 *portConfig = portConfigIt->second;
1180 return OK;
1181}
1182
1183status_t DeviceHalAidl::findOrCreatePortConfig(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001184 const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
1185 AudioPortConfig* portConfig, bool* created) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001186 using Tag = AudioPortExt::Tag;
1187 if (requestedPortConfig.ext.getTag() == Tag::mix) {
1188 if (const auto& p = requestedPortConfig;
1189 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001190 !p.format.has_value()) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001191 ALOGW("%s: provided mix port config is not fully specified: %s",
1192 __func__, p.toString().c_str());
1193 return BAD_VALUE;
1194 }
1195 AudioConfig config;
1196 setConfigFromPortConfig(&config, requestedPortConfig);
Mikhail Naganovd8d01f72023-03-09 16:24:40 -08001197 AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
1198 AudioPortMixExtUseCase::Tag::source ?
1199 requestedPortConfig.ext.get<Tag::mix>().usecase.
1200 get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001201 return findOrCreatePortConfig(config, requestedPortConfig.flags,
Mikhail Naganov289468a2023-03-29 10:06:15 -07001202 requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
1203 portConfig, created);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001204 } else if (requestedPortConfig.ext.getTag() == Tag::device) {
1205 return findOrCreatePortConfig(
1206 requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
1207 }
1208 ALOGW("%s: unsupported audio port config: %s",
1209 __func__, requestedPortConfig.toString().c_str());
1210 return BAD_VALUE;
1211}
1212
1213DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
1214 const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
1215 return std::find_if(mPatches.begin(), mPatches.end(),
1216 [&](const auto& pair) {
1217 const auto& p = pair.second;
1218 std::set<int32_t> patchSrcs(
1219 p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
1220 std::set<int32_t> patchSinks(
1221 p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
1222 return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
1223}
1224
1225DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001226 if (device.type.type == AudioDeviceType::IN_DEFAULT) {
1227 return mPorts.find(mDefaultInputPortId);
1228 } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
1229 return mPorts.find(mDefaultOutputPortId);
1230 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001231 return std::find_if(mPorts.begin(), mPorts.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001232 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001233}
1234
Mikhail Naganov289468a2023-03-29 10:06:15 -07001235
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001236DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
Mikhail Naganov289468a2023-03-29 10:06:15 -07001237 const AudioConfig& config, const AudioIoFlags& flags,
1238 const std::set<int32_t>& destinationPortIds) {
Mikhail Naganove93a0862023-03-15 17:06:59 -07001239 auto belongsToProfile = [&config](const AudioProfile& prof) {
1240 return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
1241 (config.base.channelMask.getTag() == AudioChannelLayout::none ||
1242 std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
1243 config.base.channelMask) != prof.channelMasks.end()) &&
1244 (config.base.sampleRate == 0 ||
1245 std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
1246 config.base.sampleRate) != prof.sampleRates.end());
1247 };
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001248 auto matcher = [&](const auto& pair) {
1249 const auto& p = pair.second;
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001250 return p.ext.getTag() == AudioPortExt::Tag::mix &&
1251 p.flags == flags &&
Mikhail Naganov289468a2023-03-29 10:06:15 -07001252 (destinationPortIds.empty() ||
1253 std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
1254 [&](const int32_t destId) { return mRoutingMatrix.count(
1255 std::make_pair(p.id, destId)) != 0; })) &&
Mikhail Naganove93a0862023-03-15 17:06:59 -07001256 (p.profiles.empty() ||
1257 std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
1258 p.profiles.end()); };
Mikhail Naganov1a44bc62023-02-16 17:35:06 -08001259 return std::find_if(mPorts.begin(), mPorts.end(), matcher);
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001260}
1261
1262DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001263 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001264 [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001265}
1266
1267DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001268 const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001269 using Tag = AudioPortExt::Tag;
1270 return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
1271 [&](const auto& pair) {
1272 const auto& p = pair.second;
1273 LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
1274 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
1275 !p.format.has_value() || !p.flags.has_value(),
1276 "%s: stored mix port config is not fully specified: %s",
1277 __func__, p.toString().c_str());
1278 return p.ext.getTag() == Tag::mix &&
1279 isConfigEqualToPortConfig(config, p) &&
Mikhail Naganov89a9f742023-01-30 12:33:18 -08001280 (!flags.has_value() || p.flags.value() == flags.value()) &&
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001281 p.ext.template get<Tag::mix>().handle == ioHandle; });
1282}
Mikhail Naganove93a0862023-03-15 17:06:59 -07001283
Mikhail Naganov5b1eed12023-01-25 11:29:11 -08001284void DeviceHalAidl::resetPatch(int32_t patchId) {
1285 if (auto it = mPatches.find(patchId); it != mPatches.end()) {
1286 mPatches.erase(it);
1287 TIME_CHECK();
1288 if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
1289 ALOGE("%s: error while resetting patch %d: %s",
1290 __func__, patchId, status.getDescription().c_str());
1291 }
1292 return;
1293 }
1294 ALOGE("%s: patch id %d not found", __func__, patchId);
1295}
1296
1297void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
1298 if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
1299 mPortConfigs.erase(it);
1300 TIME_CHECK();
1301 if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
1302 !status.isOk()) {
1303 ALOGE("%s: error while resetting port config %d: %s",
1304 __func__, portConfigId, status.getDescription().c_str());
1305 }
1306 return;
1307 }
1308 ALOGE("%s: port config id %d not found", __func__, portConfigId);
1309}
1310
Mikhail Naganove93a0862023-03-15 17:06:59 -07001311void DeviceHalAidl::resetUnusedPatches() {
1312 // Since patches can be created independently of streams via 'createAudioPatch',
1313 // here we only clean up patches for released streams.
1314 for (auto it = mStreams.begin(); it != mStreams.end(); ) {
1315 if (auto streamSp = it->first.promote(); streamSp) {
1316 ++it;
1317 } else {
1318 resetPatch(it->second);
1319 it = mStreams.erase(it);
1320 }
1321 }
1322}
1323
1324void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
1325 resetUnusedPatches();
1326 resetUnusedPortConfigs();
1327}
1328
1329void DeviceHalAidl::resetUnusedPortConfigs() {
1330 // The assumption is that port configs are used to create patches
1331 // (or to open streams, but that involves creation of patches, too). Thus,
1332 // orphaned port configs can and should be reset.
1333 std::set<int32_t> portConfigIds;
1334 std::transform(mPortConfigs.begin(), mPortConfigs.end(),
1335 std::inserter(portConfigIds, portConfigIds.end()),
1336 [](const auto& pcPair) { return pcPair.first; });
1337 for (const auto& p : mPatches) {
1338 for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
1339 for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
1340 }
1341 for (int32_t id : portConfigIds) resetPortConfig(id);
1342}
1343
Mikhail Naganov289468a2023-03-29 10:06:15 -07001344status_t DeviceHalAidl::updateRoutes() {
1345 TIME_CHECK();
1346 std::vector<AudioRoute> routes;
1347 RETURN_STATUS_IF_ERROR(
1348 statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
1349 ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
1350 __func__, mInstance.c_str());
1351 mRoutingMatrix.clear();
1352 for (const auto& r : routes) {
1353 for (auto portId : r.sourcePortIds) {
1354 mRoutingMatrix.emplace(r.sinkPortId, portId);
1355 mRoutingMatrix.emplace(portId, r.sinkPortId);
1356 }
1357 }
1358 return OK;
1359}
1360
Mikhail Naganovdfd594e2023-02-08 16:59:41 -08001361void DeviceHalAidl::clearCallbacks(void* cookie) {
1362 std::lock_guard l(mLock);
1363 mCallbacks.erase(cookie);
1364}
1365
1366sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
1367 return getCallbackImpl(cookie, &Callbacks::out);
1368}
1369
1370void DeviceHalAidl::setStreamOutCallback(
1371 void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
1372 setCallbackImpl(cookie, &Callbacks::out, cb);
1373}
1374
1375sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
1376 void* cookie) {
1377 return getCallbackImpl(cookie, &Callbacks::event);
1378}
1379
1380void DeviceHalAidl::setStreamOutEventCallback(
1381 void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
1382 setCallbackImpl(cookie, &Callbacks::event, cb);
1383}
1384
1385sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
1386 void* cookie) {
1387 return getCallbackImpl(cookie, &Callbacks::latency);
1388}
1389
1390void DeviceHalAidl::setStreamOutLatencyModeCallback(
1391 void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
1392 setCallbackImpl(cookie, &Callbacks::latency, cb);
1393}
1394
1395template<class C>
1396sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
1397 std::lock_guard l(mLock);
1398 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1399 return ((it->second).*field).promote();
1400 }
1401 return nullptr;
1402}
1403template<class C>
1404void DeviceHalAidl::setCallbackImpl(
1405 void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
1406 std::lock_guard l(mLock);
1407 if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
1408 (it->second).*field = cb;
1409 }
1410}
1411
Mikhail Naganov31d46652023-01-10 18:29:25 +00001412} // namespace android